@@ -344,6 +344,51 @@ CIRGenFunction::buildCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
344344 /* IsArrow=*/ false , E->getArg (0 ));
345345}
346346
347+ static void buildNullBaseClassInitialization (CIRGenFunction &CGF,
348+ Address DestPtr,
349+ const CXXRecordDecl *Base) {
350+ if (Base->isEmpty ())
351+ return ;
352+
353+ DestPtr = DestPtr.withElementType (CGF.UInt8Ty );
354+
355+ const ASTRecordLayout &Layout = CGF.getContext ().getASTRecordLayout (Base);
356+ CharUnits NVSize = Layout.getNonVirtualSize ();
357+
358+ // We cannot simply zero-initialize the entire base sub-object if vbptrs are
359+ // present, they are initialized by the most derived class before calling the
360+ // constructor.
361+ SmallVector<std::pair<CharUnits, CharUnits>, 1 > Stores;
362+ Stores.emplace_back (CharUnits::Zero (), NVSize);
363+
364+ // Each store is split by the existence of a vbptr.
365+ CharUnits VBPtrWidth = CGF.getPointerSize ();
366+ std::vector<CharUnits> VBPtrOffsets =
367+ CGF.CGM .getCXXABI ().getVBPtrOffsets (Base);
368+ for (CharUnits VBPtrOffset : VBPtrOffsets) {
369+ // Stop before we hit any virtual base pointers located in virtual bases.
370+ if (VBPtrOffset >= NVSize)
371+ break ;
372+ std::pair<CharUnits, CharUnits> LastStore = Stores.pop_back_val ();
373+ CharUnits LastStoreOffset = LastStore.first ;
374+ CharUnits LastStoreSize = LastStore.second ;
375+
376+ CharUnits SplitBeforeOffset = LastStoreOffset;
377+ CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset;
378+ assert (!SplitBeforeSize.isNegative () && " negative store size!" );
379+ if (!SplitBeforeSize.isZero ())
380+ Stores.emplace_back (SplitBeforeOffset, SplitBeforeSize);
381+
382+ CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth;
383+ CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset;
384+ assert (!SplitAfterSize.isNegative () && " negative store size!" );
385+ if (!SplitAfterSize.isZero ())
386+ Stores.emplace_back (SplitAfterOffset, SplitAfterSize);
387+ }
388+
389+ llvm_unreachable (" NYI" );
390+ }
391+
347392void CIRGenFunction::buildCXXConstructExpr (const CXXConstructExpr *E,
348393 AggValueSlot Dest) {
349394 assert (!Dest.isIgnored () && " Must have a destination!" );
@@ -362,7 +407,8 @@ void CIRGenFunction::buildCXXConstructExpr(const CXXConstructExpr *E,
362407 break ;
363408 case CXXConstructionKind::VirtualBase:
364409 case CXXConstructionKind::NonVirtualBase:
365- llvm_unreachable (" NYI" );
410+ buildNullBaseClassInitialization (*this , Dest.getAddress (),
411+ CD->getParent ());
366412 break ;
367413 }
368414 }
0 commit comments