@@ -42,6 +42,16 @@ using namespace CodeGen;
42
42
namespace {
43
43
class ConstExprEmitter ;
44
44
45
+ llvm::Constant *getPadding (const CodeGenModule &CGM, CharUnits PadSize) {
46
+ llvm::Type *Ty = CGM.CharTy ;
47
+ if (PadSize > CharUnits::One ())
48
+ Ty = llvm::ArrayType::get (Ty, PadSize.getQuantity ());
49
+ if (CGM.shouldZeroInitPadding ()) {
50
+ return llvm::Constant::getNullValue (Ty);
51
+ }
52
+ return llvm::UndefValue::get (Ty);
53
+ }
54
+
45
55
struct ConstantAggregateBuilderUtils {
46
56
CodeGenModule &CGM;
47
57
@@ -61,10 +71,7 @@ struct ConstantAggregateBuilderUtils {
61
71
}
62
72
63
73
llvm::Constant *getPadding (CharUnits PadSize) const {
64
- llvm::Type *Ty = CGM.CharTy ;
65
- if (PadSize > CharUnits::One ())
66
- Ty = llvm::ArrayType::get (Ty, PadSize.getQuantity ());
67
- return llvm::UndefValue::get (Ty);
74
+ return ::getPadding (CGM, PadSize);
68
75
}
69
76
70
77
llvm::Constant *getZeroes (CharUnits ZeroSize) const {
@@ -591,6 +598,11 @@ class ConstStructBuilder {
591
598
bool Build (const InitListExpr *ILE, bool AllowOverwrite);
592
599
bool Build (const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
593
600
const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
601
+ bool DoZeroInitPadding (const ASTRecordLayout &Layout, unsigned FieldNo,
602
+ const FieldDecl &Field, bool AllowOverwrite,
603
+ CharUnits &SizeSoFar, bool &ZeroFieldSize);
604
+ bool DoZeroInitPadding (const ASTRecordLayout &Layout, bool AllowOverwrite,
605
+ CharUnits SizeSoFar);
594
606
llvm::Constant *Finalize (QualType Ty);
595
607
};
596
608
@@ -715,6 +727,10 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
715
727
if (CXXRD->getNumBases ())
716
728
return false ;
717
729
730
+ const bool ZeroInitPadding = CGM.shouldZeroInitPadding ();
731
+ bool ZeroFieldSize = false ;
732
+ CharUnits SizeSoFar = CharUnits::Zero ();
733
+
718
734
for (FieldDecl *Field : RD->fields ()) {
719
735
++FieldNo;
720
736
@@ -732,8 +748,13 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
732
748
const Expr *Init = nullptr ;
733
749
if (ElementNo < ILE->getNumInits ())
734
750
Init = ILE->getInit (ElementNo++);
735
- if (isa_and_nonnull<NoInitExpr>(Init))
751
+ if (isa_and_nonnull<NoInitExpr>(Init)) {
752
+ if (ZeroInitPadding &&
753
+ !DoZeroInitPadding (Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
754
+ ZeroFieldSize))
755
+ return false ;
736
756
continue ;
757
+ }
737
758
738
759
// Zero-sized fields are not emitted, but their initializers may still
739
760
// prevent emission of this struct as a constant.
@@ -743,6 +764,11 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
743
764
continue ;
744
765
}
745
766
767
+ if (ZeroInitPadding &&
768
+ !DoZeroInitPadding (Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
769
+ ZeroFieldSize))
770
+ return false ;
771
+
746
772
// When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
747
773
// represents additional overwriting of our current constant value, and not
748
774
// a new constant to emit independently.
@@ -768,6 +794,10 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
768
794
if (!EltInit)
769
795
return false ;
770
796
797
+ if (ZeroInitPadding && ZeroFieldSize)
798
+ SizeSoFar += CharUnits::fromQuantity (
799
+ CGM.getDataLayout ().getTypeAllocSize (EltInit->getType ()));
800
+
771
801
if (!Field->isBitField ()) {
772
802
// Handle non-bitfield members.
773
803
if (!AppendField (Field, Layout.getFieldOffset (FieldNo), EltInit,
@@ -785,6 +815,9 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
785
815
}
786
816
}
787
817
818
+ if (ZeroInitPadding && !DoZeroInitPadding (Layout, AllowOverwrite, SizeSoFar))
819
+ return false ;
820
+
788
821
return true ;
789
822
}
790
823
@@ -849,6 +882,9 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
849
882
850
883
unsigned FieldNo = 0 ;
851
884
uint64_t OffsetBits = CGM.getContext ().toBits (Offset);
885
+ const bool ZeroInitPadding = CGM.shouldZeroInitPadding ();
886
+ bool ZeroFieldSize = false ;
887
+ CharUnits SizeSoFar = CharUnits::Zero ();
852
888
853
889
bool AllowOverwrite = false ;
854
890
for (RecordDecl::field_iterator Field = RD->field_begin (),
@@ -870,6 +906,15 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
870
906
if (!EltInit)
871
907
return false ;
872
908
909
+ if (ZeroInitPadding) {
910
+ if (!DoZeroInitPadding (Layout, FieldNo, **Field, AllowOverwrite,
911
+ SizeSoFar, ZeroFieldSize))
912
+ return false ;
913
+ if (ZeroFieldSize)
914
+ SizeSoFar += CharUnits::fromQuantity (
915
+ CGM.getDataLayout ().getTypeAllocSize (EltInit->getType ()));
916
+ }
917
+
873
918
if (!Field->isBitField ()) {
874
919
// Handle non-bitfield members.
875
920
if (!AppendField (*Field, Layout.getFieldOffset (FieldNo) + OffsetBits,
@@ -886,7 +931,49 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
886
931
return false ;
887
932
}
888
933
}
934
+ if (ZeroInitPadding && !DoZeroInitPadding (Layout, AllowOverwrite, SizeSoFar))
935
+ return false ;
936
+
937
+ return true ;
938
+ }
939
+
940
+ bool ConstStructBuilder::DoZeroInitPadding (
941
+ const ASTRecordLayout &Layout, unsigned FieldNo, const FieldDecl &Field,
942
+ bool AllowOverwrite, CharUnits &SizeSoFar, bool &ZeroFieldSize) {
943
+ uint64_t StartBitOffset = Layout.getFieldOffset (FieldNo);
944
+ CharUnits StartOffset = CGM.getContext ().toCharUnitsFromBits (StartBitOffset);
945
+ if (SizeSoFar < StartOffset)
946
+ if (!AppendBytes (SizeSoFar, getPadding (CGM, StartOffset - SizeSoFar),
947
+ AllowOverwrite))
948
+ return false ;
949
+
950
+ if (!Field.isBitField ()) {
951
+ CharUnits FieldSize = CGM.getContext ().getTypeSizeInChars (Field.getType ());
952
+ SizeSoFar = StartOffset + FieldSize;
953
+ ZeroFieldSize = FieldSize.isZero ();
954
+ } else {
955
+ const CGRecordLayout &RL =
956
+ CGM.getTypes ().getCGRecordLayout (Field.getParent ());
957
+ const CGBitFieldInfo &Info = RL.getBitFieldInfo (&Field);
958
+ uint64_t EndBitOffset = StartBitOffset + Info.Size ;
959
+ SizeSoFar = CGM.getContext ().toCharUnitsFromBits (EndBitOffset);
960
+ if (EndBitOffset % CGM.getContext ().getCharWidth () != 0 ) {
961
+ SizeSoFar++;
962
+ }
963
+ ZeroFieldSize = Info.Size == 0 ;
964
+ }
965
+ return true ;
966
+ }
889
967
968
+ bool ConstStructBuilder::DoZeroInitPadding (const ASTRecordLayout &Layout,
969
+ bool AllowOverwrite,
970
+ CharUnits SizeSoFar) {
971
+ CharUnits TotalSize = Layout.getSize ();
972
+ if (SizeSoFar < TotalSize)
973
+ if (!AppendBytes (SizeSoFar, getPadding (CGM, TotalSize - SizeSoFar),
974
+ AllowOverwrite))
975
+ return false ;
976
+ SizeSoFar = TotalSize;
890
977
return true ;
891
978
}
892
979
@@ -1127,12 +1214,10 @@ class ConstExprEmitter
1127
1214
1128
1215
assert (CurSize <= TotalSize && " Union size mismatch!" );
1129
1216
if (unsigned NumPadBytes = TotalSize - CurSize) {
1130
- llvm::Type *Ty = CGM.CharTy ;
1131
- if (NumPadBytes > 1 )
1132
- Ty = llvm::ArrayType::get (Ty, NumPadBytes);
1133
-
1134
- Elts.push_back (llvm::UndefValue::get (Ty));
1135
- Types.push_back (Ty);
1217
+ llvm::Constant *Padding =
1218
+ getPadding (CGM, CharUnits::fromQuantity (NumPadBytes));
1219
+ Elts.push_back (Padding);
1220
+ Types.push_back (Padding->getType ());
1136
1221
}
1137
1222
1138
1223
llvm::StructType *STy = llvm::StructType::get (VMContext, Types, false );
0 commit comments