@@ -500,6 +500,26 @@ class ConstRecordBuilder {
500
500
bool appendBitField (const FieldDecl *field, uint64_t fieldOffset,
501
501
cir::IntAttr ci, bool allowOverwrite = false );
502
502
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
+
503
523
bool build (InitListExpr *ile, bool allowOverwrite);
504
524
bool build (const APValue &val, const RecordDecl *rd, bool isPrimaryBase,
505
525
const CXXRecordDecl *vTableClass, CharUnits baseOffset);
@@ -548,6 +568,49 @@ bool ConstRecordBuilder::appendBitField(const FieldDecl *field,
548
568
allowOverwrite);
549
569
}
550
570
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
+ sizeSoFar = totalSize;
611
+ return true ;
612
+ }
613
+
551
614
bool ConstRecordBuilder::build (InitListExpr *ile, bool allowOverwrite) {
552
615
RecordDecl *rd = ile->getType ()
553
616
->castAs <clang::RecordType>()
@@ -562,11 +625,9 @@ bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
562
625
if (cxxrd->getNumBases ())
563
626
return false ;
564
627
565
- if (cgm.shouldZeroInitPadding ()) {
566
- assert (!cir::MissingFeatures::recordZeroInitPadding ());
567
- cgm.errorNYI (rd->getSourceRange (), " zero init padding" );
568
- return false ;
569
- }
628
+ const bool zeroInitPadding = cgm.shouldZeroInitPadding ();
629
+ bool zeroFieldSize = false ;
630
+ CharUnits sizeSoFar = CharUnits::Zero ();
570
631
571
632
unsigned elementNo = 0 ;
572
633
for (auto [index, field] : llvm::enumerate (rd->fields ())) {
@@ -596,7 +657,10 @@ bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
596
657
continue ;
597
658
}
598
659
599
- assert (!cir::MissingFeatures::recordZeroInitPadding ());
660
+ if (zeroInitPadding &&
661
+ !applyZeroInitPadding (layout, index, *field, allowOverwrite, sizeSoFar,
662
+ zeroFieldSize))
663
+ return false ;
600
664
601
665
// When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
602
666
// represents additional overwriting of our current constant value, and not
@@ -641,8 +705,8 @@ bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
641
705
}
642
706
}
643
707
644
- assert (! cir::MissingFeatures::recordZeroInitPadding ());
645
- return true ;
708
+ return !zeroInitPadding ||
709
+ applyZeroInitPadding (layout, allowOverwrite, sizeSoFar) ;
646
710
}
647
711
648
712
namespace {
0 commit comments