1515#include " CIRGenCXXABI.h"
1616#include " CIRGenModule.h"
1717#include " mlir/IR/Types.h"
18+ #include " clang/AST/VTTBuilder.h"
1819#include " clang/AST/VTableBuilder.h"
1920#include " llvm/ADT/SmallVector.h"
2021
@@ -60,7 +61,7 @@ void CIRGenVTables::generateClassData(const CXXRecordDecl *rd) {
6061 assert (!cir::MissingFeatures::generateDebugInfo ());
6162
6263 if (rd->getNumVBases ())
63- cgm.errorNYI (rd-> getSourceRange (), " emitVirtualInheritanceTables" );
64+ cgm.getCXXABI (). emitVirtualInheritanceTables (rd );
6465
6566 cgm.getCXXABI ().emitVTableDefinitions (*this , rd);
6667}
@@ -76,12 +77,6 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
7677 assert (!cir::MissingFeatures::vtableRelativeLayout ());
7778
7879 switch (component.getKind ()) {
79- case VTableComponent::CK_VCallOffset:
80- cgm.errorNYI (" getVTableComponent: VCallOffset" );
81- return mlir::Attribute ();
82- case VTableComponent::CK_VBaseOffset:
83- cgm.errorNYI (" getVTableComponent: VBaseOffset" );
84- return mlir::Attribute ();
8580 case VTableComponent::CK_CompleteDtorPointer:
8681 cgm.errorNYI (" getVTableComponent: CompleteDtorPointer" );
8782 return mlir::Attribute ();
@@ -92,6 +87,14 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
9287 cgm.errorNYI (" getVTableComponent: UnusedFunctionPointer" );
9388 return mlir::Attribute ();
9489
90+ case VTableComponent::CK_VCallOffset:
91+ return builder.getConstPtrAttr (builder.getUInt8PtrTy (),
92+ component.getVCallOffset ().getQuantity ());
93+
94+ case VTableComponent::CK_VBaseOffset:
95+ return builder.getConstPtrAttr (builder.getUInt8PtrTy (),
96+ component.getVBaseOffset ().getQuantity ());
97+
9598 case VTableComponent::CK_OffsetToTop:
9699 return builder.getConstPtrAttr (builder.getUInt8PtrTy (),
97100 component.getOffsetToTop ().getQuantity ());
@@ -175,6 +178,66 @@ void CIRGenVTables::createVTableInitializer(cir::GlobalOp &vtableOp,
175178 cgm.setInitializer (vtableOp, vtableAttr);
176179}
177180
181+ cir::GlobalOp CIRGenVTables::generateConstructionVTable (
182+ const CXXRecordDecl *rd, const BaseSubobject &base, bool baseIsVirtual,
183+ cir::GlobalLinkageKind linkage, VTableAddressPointsMapTy &addressPoints) {
184+ assert (!cir::MissingFeatures::generateDebugInfo ());
185+
186+ std::unique_ptr<VTableLayout> vtLayout (
187+ getItaniumVTableContext ().createConstructionVTableLayout (
188+ base.getBase (), base.getBaseOffset (), baseIsVirtual, rd));
189+
190+ // Add the address points.
191+ addressPoints = vtLayout->getAddressPoints ();
192+
193+ // Get the mangled construction vtable name.
194+ SmallString<256 > outName;
195+ llvm::raw_svector_ostream out (outName);
196+ cast<ItaniumMangleContext>(cgm.getCXXABI ().getMangleContext ())
197+ .mangleCXXCtorVTable (rd, base.getBaseOffset ().getQuantity (),
198+ base.getBase (), out);
199+ SmallString<256 > name (outName);
200+
201+ assert (!cir::MissingFeatures::vtableRelativeLayout ());
202+
203+ cir::RecordType vtType = getVTableType (*vtLayout);
204+
205+ // Construction vtable symbols are not part of the Itanium ABI, so we cannot
206+ // guarantee that they actually will be available externally. Instead, when
207+ // emitting an available_externally VTT, we provide references to an internal
208+ // linkage construction vtable. The ABI only requires complete-object vtables
209+ // to be the same for all instances of a type, not construction vtables.
210+ if (linkage == cir::GlobalLinkageKind::AvailableExternallyLinkage)
211+ linkage = cir::GlobalLinkageKind::InternalLinkage;
212+
213+ llvm::Align align = cgm.getDataLayout ().getABITypeAlign (vtType);
214+ mlir::Location loc = cgm.getLoc (rd->getSourceRange ());
215+
216+ // Create the variable that will hold the construction vtable.
217+ cir::GlobalOp vtable = cgm.createOrReplaceCXXRuntimeVariable (
218+ loc, name, vtType, linkage, CharUnits::fromQuantity (align));
219+
220+ // V-tables are always unnamed_addr.
221+ assert (!cir::MissingFeatures::opGlobalUnnamedAddr ());
222+
223+ mlir::Attribute rtti = cgm.getAddrOfRTTIDescriptor (
224+ loc, cgm.getASTContext ().getCanonicalTagType (base.getBase ()));
225+
226+ // Create and set the initializer.
227+ createVTableInitializer (vtable, *vtLayout, rtti,
228+ cir::isLocalLinkage (vtable.getLinkage ()));
229+
230+ // Set properties only after the initializer has been set to ensure that the
231+ // GV is treated as definition and not declaration.
232+ assert (!vtable.isDeclaration () && " Shouldn't set properties on declaration" );
233+ cgm.setGVProperties (vtable, rd);
234+
235+ assert (!cir::MissingFeatures::vtableEmitMetadata ());
236+ assert (!cir::MissingFeatures::vtableRelativeLayout ());
237+
238+ return vtable;
239+ }
240+
178241// / Compute the required linkage of the vtable for the given class.
179242// /
180243// / Note that we only call this at the end of the translation unit.
@@ -226,6 +289,109 @@ cir::GlobalLinkageKind CIRGenModule::getVTableLinkage(const CXXRecordDecl *rd) {
226289 return cir::GlobalLinkageKind::ExternalLinkage;
227290}
228291
292+ cir::GlobalOp CIRGenVTables::getAddrOfVTT (const CXXRecordDecl *rd) {
293+ assert (rd->getNumVBases () && " Only classes with virtual bases need a VTT" );
294+
295+ SmallString<256 > outName;
296+ llvm::raw_svector_ostream out (outName);
297+ cast<ItaniumMangleContext>(cgm.getCXXABI ().getMangleContext ())
298+ .mangleCXXVTT (rd, out);
299+ StringRef name = outName.str ();
300+
301+ // This will also defer the definition of the VTT.
302+ (void )cgm.getCXXABI ().getAddrOfVTable (rd, CharUnits ());
303+
304+ VTTBuilder builder (cgm.getASTContext (), rd, /* GenerateDefinition=*/ false );
305+
306+ auto arrayType = cir::ArrayType::get (cgm.getBuilder ().getUInt8PtrTy (),
307+ builder.getVTTComponents ().size ());
308+ llvm::Align align =
309+ cgm.getDataLayout ().getABITypeAlign (cgm.getBuilder ().getUInt8PtrTy ());
310+ cir::GlobalOp vtt = cgm.createOrReplaceCXXRuntimeVariable (
311+ cgm.getLoc (rd->getSourceRange ()), name, arrayType,
312+ cir::GlobalLinkageKind::ExternalLinkage, CharUnits::fromQuantity (align));
313+ cgm.setGVProperties (vtt, rd);
314+ return vtt;
315+ }
316+
317+ static cir::GlobalOp
318+ getAddrOfVTTVTable (CIRGenVTables &cgvt, CIRGenModule &cgm,
319+ const CXXRecordDecl *mostDerivedClass,
320+ const VTTVTable &vtable, cir::GlobalLinkageKind linkage,
321+ VTableLayout::AddressPointsMapTy &addressPoints) {
322+ if (vtable.getBase () == mostDerivedClass) {
323+ assert (vtable.getBaseOffset ().isZero () &&
324+ " Most derived class vtable must have a zero offset!" );
325+ // This is a regular vtable.
326+ return cgm.getCXXABI ().getAddrOfVTable (mostDerivedClass, CharUnits ());
327+ }
328+ return cgvt.generateConstructionVTable (
329+ mostDerivedClass, vtable.getBaseSubobject (), vtable.isVirtual (), linkage,
330+ addressPoints);
331+ }
332+
333+ // / Emit the definition of the given vtable.
334+ void CIRGenVTables::emitVTTDefinition (cir::GlobalOp vttOp,
335+ cir::GlobalLinkageKind linkage,
336+ const CXXRecordDecl *rd) {
337+ VTTBuilder builder (cgm.getASTContext (), rd, /* GenerateDefinition=*/ true );
338+
339+ mlir::MLIRContext *mlirContext = &cgm.getMLIRContext ();
340+
341+ auto arrayType = cir::ArrayType::get (cgm.getBuilder ().getUInt8PtrTy (),
342+ builder.getVTTComponents ().size ());
343+
344+ SmallVector<cir::GlobalOp> vtables;
345+ SmallVector<VTableAddressPointsMapTy> vtableAddressPoints;
346+ for (const VTTVTable &vtt : builder.getVTTVTables ()) {
347+ vtableAddressPoints.push_back (VTableAddressPointsMapTy ());
348+ vtables.push_back (getAddrOfVTTVTable (*this , cgm, rd, vtt, linkage,
349+ vtableAddressPoints.back ()));
350+ }
351+
352+ SmallVector<mlir::Attribute> vttComponents;
353+ for (const VTTComponent &vttComponent : builder.getVTTComponents ()) {
354+ const VTTVTable &vttVT = builder.getVTTVTables ()[vttComponent.VTableIndex ];
355+ cir::GlobalOp vtable = vtables[vttComponent.VTableIndex ];
356+ VTableLayout::AddressPointLocation addressPoint;
357+ if (vttVT.getBase () == rd) {
358+ // Just get the address point for the regular vtable.
359+ addressPoint =
360+ getItaniumVTableContext ().getVTableLayout (rd).getAddressPoint (
361+ vttComponent.VTableBase );
362+ } else {
363+ addressPoint = vtableAddressPoints[vttComponent.VTableIndex ].lookup (
364+ vttComponent.VTableBase );
365+ assert (addressPoint.AddressPointIndex != 0 &&
366+ " Did not find ctor vtable address point!" );
367+ }
368+
369+ mlir::Attribute indices[2 ] = {
370+ cgm.getBuilder ().getI32IntegerAttr (addressPoint.VTableIndex ),
371+ cgm.getBuilder ().getI32IntegerAttr (addressPoint.AddressPointIndex ),
372+ };
373+
374+ auto indicesAttr = mlir::ArrayAttr::get (mlirContext, indices);
375+ cir::GlobalViewAttr init = cgm.getBuilder ().getGlobalViewAttr (
376+ cgm.getBuilder ().getUInt8PtrTy (), vtable, indicesAttr);
377+
378+ vttComponents.push_back (init);
379+ }
380+
381+ auto init = cir::ConstArrayAttr::get (
382+ arrayType, mlir::ArrayAttr::get (mlirContext, vttComponents));
383+
384+ vttOp.setInitialValueAttr (init);
385+
386+ // Set the correct linkage.
387+ vttOp.setLinkage (linkage);
388+ mlir::SymbolTable::setSymbolVisibility (
389+ vttOp, CIRGenModule::getMLIRVisibility (vttOp));
390+
391+ if (cgm.supportsCOMDAT () && vttOp.isWeakForLinker ())
392+ vttOp.setComdat (true );
393+ }
394+
229395void CIRGenVTables::emitThunks (GlobalDecl gd) {
230396 const CXXMethodDecl *md =
231397 cast<CXXMethodDecl>(gd.getDecl ())->getCanonicalDecl ();
0 commit comments