@@ -42,6 +42,16 @@ using namespace CodeGen;
4242namespace {
4343class ConstExprEmitter ;
4444
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+
4555struct ConstantAggregateBuilderUtils {
4656 CodeGenModule &CGM;
4757
@@ -61,10 +71,7 @@ struct ConstantAggregateBuilderUtils {
6171 }
6272
6373 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);
6875 }
6976
7077 llvm::Constant *getZeroes (CharUnits ZeroSize) const {
@@ -591,6 +598,11 @@ class ConstStructBuilder {
591598 bool Build (const InitListExpr *ILE, bool AllowOverwrite);
592599 bool Build (const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
593600 const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
601+ bool DoZeroInitPadding (const ASTRecordLayout &Layout, unsigned FieldNo,
602+ const FieldDecl &Field, bool AllowOverwrite,
603+ CharUnits &FieldSize, CharUnits &SizeSoFar);
604+ bool DoZeroInitPadding (const ASTRecordLayout &Layout, bool AllowOverwrite,
605+ CharUnits &SizeSoFar);
594606 llvm::Constant *Finalize (QualType Ty);
595607};
596608
@@ -715,6 +727,10 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
715727 if (CXXRD->getNumBases ())
716728 return false ;
717729
730+ const bool ZeroInitPadding = CGM.shouldZeroInitPadding ();
731+ CharUnits FieldSize = CharUnits::Zero ();
732+ CharUnits SizeSoFar = CharUnits::Zero ();
733+
718734 for (FieldDecl *Field : RD->fields ()) {
719735 ++FieldNo;
720736
@@ -732,8 +748,13 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
732748 const Expr *Init = nullptr ;
733749 if (ElementNo < ILE->getNumInits ())
734750 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, FieldSize,
754+ SizeSoFar))
755+ return false ;
736756 continue ;
757+ }
737758
738759 // Zero-sized fields are not emitted, but their initializers may still
739760 // prevent emission of this struct as a constant.
@@ -743,6 +764,11 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
743764 continue ;
744765 }
745766
767+ if (ZeroInitPadding &&
768+ !DoZeroInitPadding (Layout, FieldNo, *Field, AllowOverwrite, FieldSize,
769+ SizeSoFar))
770+ return false ;
771+
746772 // When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
747773 // represents additional overwriting of our current constant value, and not
748774 // a new constant to emit independently.
@@ -768,6 +794,10 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
768794 if (!EltInit)
769795 return false ;
770796
797+ if (ZeroInitPadding && FieldSize.isZero ())
798+ SizeSoFar += CharUnits::fromQuantity (
799+ CGM.getDataLayout ().getTypeAllocSize (EltInit->getType ()));
800+
771801 if (!Field->isBitField ()) {
772802 // Handle non-bitfield members.
773803 if (!AppendField (Field, Layout.getFieldOffset (FieldNo), EltInit,
@@ -785,6 +815,9 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
785815 }
786816 }
787817
818+ if (ZeroInitPadding && !DoZeroInitPadding (Layout, AllowOverwrite, SizeSoFar))
819+ return false ;
820+
788821 return true ;
789822}
790823
@@ -849,6 +882,9 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
849882
850883 unsigned FieldNo = 0 ;
851884 uint64_t OffsetBits = CGM.getContext ().toBits (Offset);
885+ const bool ZeroInitPadding = CGM.shouldZeroInitPadding ();
886+ CharUnits FieldSize = CharUnits::Zero ();
887+ CharUnits SizeSoFar = CharUnits::Zero ();
852888
853889 bool AllowOverwrite = false ;
854890 for (RecordDecl::field_iterator Field = RD->field_begin (),
@@ -870,6 +906,15 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
870906 if (!EltInit)
871907 return false ;
872908
909+ if (ZeroInitPadding) {
910+ if (!DoZeroInitPadding (Layout, FieldNo, **Field, AllowOverwrite,
911+ FieldSize, SizeSoFar))
912+ return false ;
913+ if (FieldSize.isZero ())
914+ SizeSoFar += CharUnits::fromQuantity (
915+ CGM.getDataLayout ().getTypeAllocSize (EltInit->getType ()));
916+ }
917+
873918 if (!Field->isBitField ()) {
874919 // Handle non-bitfield members.
875920 if (!AppendField (*Field, Layout.getFieldOffset (FieldNo) + OffsetBits,
@@ -886,7 +931,35 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
886931 return false ;
887932 }
888933 }
934+ if (ZeroInitPadding && !DoZeroInitPadding (Layout, AllowOverwrite, SizeSoFar))
935+ return false ;
936+
937+ return true ;
938+ }
889939
940+ bool ConstStructBuilder::DoZeroInitPadding (
941+ const ASTRecordLayout &Layout, unsigned FieldNo, const FieldDecl &Field,
942+ bool AllowOverwrite, CharUnits &FieldSize, CharUnits &SizeSoFar) {
943+ CharUnits Offset =
944+ CGM.getContext ().toCharUnitsFromBits (Layout.getFieldOffset (FieldNo));
945+ if (SizeSoFar < Offset)
946+ if (!AppendBytes (SizeSoFar, getPadding (CGM, Offset - SizeSoFar),
947+ AllowOverwrite))
948+ return false ;
949+ FieldSize = CGM.getContext ().getTypeSizeInChars (Field.getType ());
950+ SizeSoFar = Offset + FieldSize;
951+ return true ;
952+ }
953+
954+ bool ConstStructBuilder::DoZeroInitPadding (const ASTRecordLayout &Layout,
955+ bool AllowOverwrite,
956+ CharUnits &SizeSoFar) {
957+ CharUnits TotalSize = Layout.getSize ();
958+ if (SizeSoFar < TotalSize)
959+ if (!AppendBytes (SizeSoFar, getPadding (CGM, TotalSize - SizeSoFar),
960+ AllowOverwrite))
961+ return false ;
962+ SizeSoFar = TotalSize;
890963 return true ;
891964}
892965
@@ -1127,12 +1200,10 @@ class ConstExprEmitter
11271200
11281201 assert (CurSize <= TotalSize && " Union size mismatch!" );
11291202 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);
1203+ llvm::Constant *Padding =
1204+ getPadding (CGM, CharUnits::fromQuantity (NumPadBytes));
1205+ Elts.push_back (Padding);
1206+ Types.push_back (Padding->getType ());
11361207 }
11371208
11381209 llvm::StructType *STy = llvm::StructType::get (VMContext, Types, false );
0 commit comments