@@ -81,6 +81,8 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
8181 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
8282 clang::BaseSubobject base,
8383 const clang::CXXRecordDecl *nearestVBase) override ;
84+ void emitVTableDefinitions (CIRGenVTables &cgvt,
85+ const CXXRecordDecl *rd) override ;
8486
8587 bool doStructorsInitializeVPtrs (const CXXRecordDecl *vtableClass) override {
8688 return true ;
@@ -270,6 +272,67 @@ bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
270272 return false ;
271273}
272274
275+ void CIRGenItaniumCXXABI::emitVTableDefinitions (CIRGenVTables &cgvt,
276+ const CXXRecordDecl *rd) {
277+ cir::GlobalOp vtable = getAddrOfVTable (rd, CharUnits ());
278+ if (vtable.hasInitializer ())
279+ return ;
280+
281+ ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext ();
282+ const VTableLayout &vtLayout = vtContext.getVTableLayout (rd);
283+ cir::GlobalLinkageKind linkage = cgm.getVTableLinkage (rd);
284+ mlir::Attribute rtti =
285+ cgm.getAddrOfRTTIDescriptor (cgm.getLoc (rd->getBeginLoc ()),
286+ cgm.getASTContext ().getCanonicalTagType (rd));
287+
288+ // Classic codegen uses ConstantInitBuilder here, which is a very general
289+ // and feature-rich class to generate initializers for global values.
290+ // For now, this is using a simpler approach to create the initializer in CIR.
291+ cgvt.createVTableInitializer (vtable, vtLayout, rtti,
292+ cir::isLocalLinkage (linkage));
293+
294+ // Set the correct linkage.
295+ vtable.setLinkage (linkage);
296+
297+ if (cgm.supportsCOMDAT () && cir::isWeakForLinker (linkage))
298+ vtable.setComdat (true );
299+
300+ // Set the right visibility.
301+ cgm.setGVProperties (vtable, rd);
302+
303+ // If this is the magic class __cxxabiv1::__fundamental_type_info,
304+ // we will emit the typeinfo for the fundamental types. This is the
305+ // same behaviour as GCC.
306+ const DeclContext *DC = rd->getDeclContext ();
307+ if (rd->getIdentifier () &&
308+ rd->getIdentifier ()->isStr (" __fundamental_type_info" ) &&
309+ isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier () &&
310+ cast<NamespaceDecl>(DC)->getIdentifier ()->isStr (" __cxxabiv1" ) &&
311+ DC->getParent ()->isTranslationUnit ()) {
312+ cgm.errorNYI (rd->getSourceRange (),
313+ " emitVTableDefinitions: __fundamental_type_info" );
314+ }
315+
316+ auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
317+ assert (vtableAsGlobalValue && " VTable must support CIRGlobalValueInterface" );
318+ // Always emit type metadata on non-available_externally definitions, and on
319+ // available_externally definitions if we are performing whole program
320+ // devirtualization. For WPD we need the type metadata on all vtable
321+ // definitions to ensure we associate derived classes with base classes
322+ // defined in headers but with a strong definition only in a shared
323+ // library.
324+ assert (!cir::MissingFeatures::vtableEmitMetadata ());
325+ if (cgm.getCodeGenOpts ().WholeProgramVTables ) {
326+ cgm.errorNYI (rd->getSourceRange (),
327+ " emitVTableDefinitions: WholeProgramVTables" );
328+ }
329+
330+ assert (!cir::MissingFeatures::vtableRelativeLayout ());
331+ if (vtContext.isRelativeLayout ()) {
332+ cgm.errorNYI (rd->getSourceRange (), " vtableRelativeLayout" );
333+ }
334+ }
335+
273336void CIRGenItaniumCXXABI::emitDestructorCall (
274337 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
275338 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
0 commit comments