@@ -199,10 +199,6 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
199199 return ;
200200 }
201201
202- // If there are no member initializers, we can just return.
203- if (cd->getNumCtorInitializers () == 0 )
204- return ;
205-
206202 const CXXRecordDecl *classDecl = cd->getParent ();
207203
208204 // This code doesn't use range-based iteration because we may need to emit
@@ -227,7 +223,8 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
227223 }
228224
229225 const mlir::Value oldThisValue = cxxThisValue;
230- if (!constructVBases && (*b)->isBaseInitializer () && (*b)->isBaseVirtual ()) {
226+ if (!constructVBases && b != e && (*b)->isBaseInitializer () &&
227+ (*b)->isBaseVirtual ()) {
231228 cgm.errorNYI (cd->getSourceRange (),
232229 " emitCtorPrologue: virtual base initializer" );
233230 return ;
@@ -249,11 +246,7 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
249246
250247 cxxThisValue = oldThisValue;
251248
252- if (classDecl->isDynamicClass ()) {
253- cgm.errorNYI (cd->getSourceRange (),
254- " emitCtorPrologue: initialize vtable pointers" );
255- return ;
256- }
249+ initializeVTablePointers (getLoc (cd->getBeginLoc ()), classDecl);
257250
258251 // Finally, initialize class members.
259252 FieldConstructionScope fcs (*this , loadCXXThisAddress ());
@@ -271,6 +264,95 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
271264 }
272265}
273266
267+ void CIRGenFunction::initializeVTablePointer (mlir::Location loc,
268+ const VPtr &vptr) {
269+ // Compute the address point.
270+ mlir::Value vtableAddressPoint =
271+ cgm.getCXXABI ().getVTableAddressPointInStructor (
272+ *this , vptr.vtableClass , vptr.base , vptr.nearestVBase );
273+
274+ if (!vtableAddressPoint)
275+ return ;
276+
277+ // Compute where to store the address point.
278+ mlir::Value virtualOffset{};
279+ CharUnits nonVirtualOffset = CharUnits::Zero ();
280+
281+ mlir::Type baseValueTy;
282+ if (cgm.getCXXABI ().isVirtualOffsetNeededForVTableField (*this , vptr)) {
283+ cgm.errorNYI (loc, " initializeVTablePointer: virtual offset for vtable" );
284+ } else {
285+ // We can just use the base offset in the complete class.
286+ nonVirtualOffset = vptr.base .getBaseOffset ();
287+ baseValueTy = convertType (getContext ().getTagDeclType (vptr.base .getBase ()));
288+ }
289+
290+ // Apply the offsets.
291+ Address vtableField = loadCXXThisAddress ();
292+ if (!nonVirtualOffset.isZero () || virtualOffset) {
293+ cgm.errorNYI (loc,
294+ " initializeVTablePointer: non-virtual and virtual offset" );
295+ }
296+
297+ // Finally, store the address point. Use the same CIR types as the field.
298+ //
299+ // vtable field is derived from `this` pointer, therefore they should be in
300+ // the same addr space.
301+ assert (!cir::MissingFeatures::addressSpace ());
302+ // TODO(cir): This should be cir.vtable.get_vptr.
303+ vtableField = builder.createElementBitCast (loc, vtableField,
304+ vtableAddressPoint.getType ());
305+ builder.createStore (loc, vtableAddressPoint, vtableField);
306+ assert (!cir::MissingFeatures::opTBAA ());
307+ assert (!cir::MissingFeatures::createInvariantGroup ());
308+ }
309+
310+ void CIRGenFunction::initializeVTablePointers (mlir::Location loc,
311+ const CXXRecordDecl *rd) {
312+ // Ignore classes without a vtable.
313+ if (!rd->isDynamicClass ())
314+ return ;
315+
316+ // Initialize the vtable pointers for this class and all of its bases.
317+ if (cgm.getCXXABI ().doStructorsInitializeVPtrs (rd))
318+ for (const auto &vptr : getVTablePointers (rd))
319+ initializeVTablePointer (loc, vptr);
320+
321+ if (rd->getNumVBases ())
322+ cgm.errorNYI (loc, " initializeVTablePointers: virtual base" );
323+ }
324+
325+ CIRGenFunction::VPtrsVector
326+ CIRGenFunction::getVTablePointers (const CXXRecordDecl *vtableClass) {
327+ CIRGenFunction::VPtrsVector vptrsResult;
328+ getVTablePointers (BaseSubobject (vtableClass, CharUnits::Zero ()),
329+ /* NearestVBase=*/ nullptr ,
330+ /* OffsetFromNearestVBase=*/ CharUnits::Zero (),
331+ /* BaseIsNonVirtualPrimaryBase=*/ false , vtableClass,
332+ vptrsResult);
333+ return vptrsResult;
334+ }
335+
336+ void CIRGenFunction::getVTablePointers (BaseSubobject base,
337+ const CXXRecordDecl *nearestVBase,
338+ CharUnits offsetFromNearestVBase,
339+ bool baseIsNonVirtualPrimaryBase,
340+ const CXXRecordDecl *vtableClass,
341+ VPtrsVector &vptrs) {
342+ // If this base is a non-virtual primary base the address point has already
343+ // been set.
344+ if (!baseIsNonVirtualPrimaryBase) {
345+ // Initialize the vtable pointer for this base.
346+ VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
347+ vptrs.push_back (vptr);
348+ }
349+
350+ const CXXRecordDecl *rd = base.getBase ();
351+
352+ if (rd->getNumBases ())
353+ cgm.errorNYI (rd->getSourceRange (), " getVTablePointers: traverse bases" );
354+ }
355+
274356Address CIRGenFunction::loadCXXThisAddress () {
275357 assert (curFuncDecl && " loading 'this' without a func declaration?" );
276358 assert (isa<CXXMethodDecl>(curFuncDecl));
0 commit comments