@@ -500,6 +500,26 @@ class ConstRecordBuilder {
500500 bool appendBitField (const FieldDecl *field, uint64_t fieldOffset,
501501 cir::IntAttr ci, bool allowOverwrite = false );
502502
503+ // / Applies zero-initialization to padding bytes before and within a field.
504+ // / \param layout The record layout containing field offset information.
505+ // / \param fieldNo The field index in the record.
506+ // / \param field The field declaration.
507+ // / \param allowOverwrite Whether to allow overwriting existing values.
508+ // / \param sizeSoFar The current size processed, updated by this function.
509+ // / \param zeroFieldSize Set to true if the field has zero size.
510+ // / \returns true on success, false if padding could not be applied.
511+ bool applyZeroInitPadding (const ASTRecordLayout &layout, unsigned fieldNo,
512+ const FieldDecl &field, bool allowOverwrite,
513+ CharUnits &sizeSoFar, bool &zeroFieldSize);
514+
515+ // / Applies zero-initialization to trailing padding bytes in a record.
516+ // / \param layout The record layout containing size information.
517+ // / \param allowOverwrite Whether to allow overwriting existing values.
518+ // / \param sizeSoFar The current size processed.
519+ // / \returns true on success, false if padding could not be applied.
520+ bool applyZeroInitPadding (const ASTRecordLayout &layout, bool allowOverwrite,
521+ CharUnits &sizeSoFar);
522+
503523 bool build (InitListExpr *ile, bool allowOverwrite);
504524 bool build (const APValue &val, const RecordDecl *rd, bool isPrimaryBase,
505525 const CXXRecordDecl *vTableClass, CharUnits baseOffset);
@@ -548,6 +568,48 @@ bool ConstRecordBuilder::appendBitField(const FieldDecl *field,
548568 allowOverwrite);
549569}
550570
571+ bool ConstRecordBuilder::applyZeroInitPadding (
572+ const ASTRecordLayout &layout, unsigned fieldNo, const FieldDecl &field,
573+ bool allowOverwrite, CharUnits &sizeSoFar, bool &zeroFieldSize) {
574+ uint64_t startBitOffset = layout.getFieldOffset (fieldNo);
575+ CharUnits startOffset =
576+ cgm.getASTContext ().toCharUnitsFromBits (startBitOffset);
577+ if (sizeSoFar < startOffset) {
578+ if (!appendBytes (sizeSoFar, computePadding (cgm, startOffset - sizeSoFar),
579+ allowOverwrite))
580+ return false ;
581+ }
582+
583+ if (!field.isBitField ()) {
584+ CharUnits fieldSize =
585+ cgm.getASTContext ().getTypeSizeInChars (field.getType ());
586+ sizeSoFar = startOffset + fieldSize;
587+ zeroFieldSize = fieldSize.isZero ();
588+ } else {
589+ const CIRGenRecordLayout &rl =
590+ cgm.getTypes ().getCIRGenRecordLayout (field.getParent ());
591+ const CIRGenBitFieldInfo &info = rl.getBitFieldInfo (&field);
592+ uint64_t endBitOffset = startBitOffset + info.size ;
593+ sizeSoFar = cgm.getASTContext ().toCharUnitsFromBits (endBitOffset);
594+ if (endBitOffset % cgm.getASTContext ().getCharWidth () != 0 )
595+ sizeSoFar++;
596+ zeroFieldSize = info.size == 0 ;
597+ }
598+ return true ;
599+ }
600+
601+ bool ConstRecordBuilder::applyZeroInitPadding (const ASTRecordLayout &layout,
602+ bool allowOverwrite,
603+ CharUnits &sizeSoFar) {
604+ CharUnits totalSize = layout.getSize ();
605+ if (sizeSoFar < totalSize) {
606+ if (!appendBytes (sizeSoFar, computePadding (cgm, totalSize - sizeSoFar),
607+ allowOverwrite))
608+ return false ;
609+ }
610+ return true ;
611+ }
612+
551613bool ConstRecordBuilder::build (InitListExpr *ile, bool allowOverwrite) {
552614 RecordDecl *rd = ile->getType ()
553615 ->castAs <clang::RecordType>()
@@ -562,11 +624,9 @@ bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
562624 if (cxxrd->getNumBases ())
563625 return false ;
564626
565- if (cgm.shouldZeroInitPadding ()) {
566- assert (!cir::MissingFeatures::recordZeroInitPadding ());
567- cgm.errorNYI (rd->getSourceRange (), " zero init padding" );
568- return false ;
569- }
627+ const bool zeroInitPadding = cgm.shouldZeroInitPadding ();
628+ bool zeroFieldSize = false ;
629+ CharUnits sizeSoFar = CharUnits::Zero ();
570630
571631 unsigned elementNo = 0 ;
572632 for (auto [index, field] : llvm::enumerate (rd->fields ())) {
@@ -596,7 +656,10 @@ bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
596656 continue ;
597657 }
598658
599- assert (!cir::MissingFeatures::recordZeroInitPadding ());
659+ if (zeroInitPadding &&
660+ !applyZeroInitPadding (layout, index, *field, allowOverwrite, sizeSoFar,
661+ zeroFieldSize))
662+ return false ;
600663
601664 // When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
602665 // represents additional overwriting of our current constant value, and not
@@ -641,8 +704,8 @@ bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
641704 }
642705 }
643706
644- assert (! cir::MissingFeatures::recordZeroInitPadding ());
645- return true ;
707+ return !zeroInitPadding ||
708+ applyZeroInitPadding (layout, allowOverwrite, sizeSoFar) ;
646709}
647710
648711namespace {
0 commit comments