================ @@ -33,13 +35,215 @@ mlir::Type CIRGenVTables::getVTableComponentType() { return cgm.getVTableComponentType(); } -mlir::Type CIRGenVTables::getVTableType(const VTableLayout &layout) { +cir::RecordType CIRGenVTables::getVTableType(const VTableLayout &layout) { SmallVector<mlir::Type, 4> tys; - auto componentType = getVTableComponentType(); + mlir::Type componentType = getVTableComponentType(); for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) tys.push_back(cir::ArrayType::get(componentType, layout.getVTableSize(i))); // FIXME(cir): should VTableLayout be encoded like we do for some // AST nodes? return cgm.getBuilder().getAnonRecordTy(tys, /*incomplete=*/false); } + +/// This is a callback from Sema to tell us that a particular vtable is +/// required to be emitted in this translation unit. +/// +/// This is only called for vtables that _must_ be emitted (mainly due to key +/// functions). For weak vtables, CodeGen tracks when they are needed and +/// emits them as-needed. +void CIRGenModule::emitVTable(const CXXRecordDecl *rd) { + vtables.generateClassData(rd); +} + +void CIRGenVTables::generateClassData(const CXXRecordDecl *rd) { + assert(!cir::MissingFeatures::generateDebugInfo()); + + if (rd->getNumVBases()) + cgm.errorNYI(rd->getSourceRange(), "emitVirtualInheritanceTables"); + + cgm.getCXXABI().emitVTableDefinitions(*this, rd); +} + +mlir::Attribute CIRGenVTables::getVTableComponent( + const VTableLayout &layout, unsigned componentIndex, mlir::Attribute rtti, + unsigned &nextVTableThunkIndex, unsigned vtableAddressPoint, + bool vtableHasLocalLinkage) { + auto &component = layout.vtable_components()[componentIndex]; + + CIRGenBuilderTy builder = cgm.getBuilder(); + + assert(!cir::MissingFeatures::vtableRelativeLayout()); + + switch (component.getKind()) { + case VTableComponent::CK_VCallOffset: + cgm.errorNYI("getVTableComponent: VCallOffset"); + return mlir::Attribute(); + case VTableComponent::CK_VBaseOffset: + cgm.errorNYI("getVTableComponent: VBaseOffset"); + return mlir::Attribute(); + case VTableComponent::CK_CompleteDtorPointer: + cgm.errorNYI("getVTableComponent: CompleteDtorPointer"); + return mlir::Attribute(); + case VTableComponent::CK_DeletingDtorPointer: + cgm.errorNYI("getVTableComponent: DeletingDtorPointer"); + return mlir::Attribute(); + case VTableComponent::CK_UnusedFunctionPointer: + cgm.errorNYI("getVTableComponent: UnusedFunctionPointer"); + return mlir::Attribute(); + + case VTableComponent::CK_OffsetToTop: + return builder.getConstPtrAttr(builder.getUInt8PtrTy(), + component.getOffsetToTop().getQuantity()); + + case VTableComponent::CK_RTTI: + assert((mlir::isa<cir::GlobalViewAttr>(rtti) || + mlir::isa<cir::ConstPtrAttr>(rtti)) && + "expected GlobalViewAttr or ConstPtrAttr"); + return rtti; + + case VTableComponent::CK_FunctionPointer: { + GlobalDecl gd = component.getGlobalDecl(); + + assert(!cir::MissingFeatures::cudaSupport()); + + cir::FuncOp fnPtr; + if (cast<CXXMethodDecl>(gd.getDecl())->isPureVirtual()) { + cgm.errorNYI("getVTableComponent: CK_FunctionPointer: pure virtual"); + return mlir::Attribute(); + } else if (cast<CXXMethodDecl>(gd.getDecl())->isDeleted()) { + cgm.errorNYI("getVTableComponent: CK_FunctionPointer: deleted virtual"); + return mlir::Attribute(); + } else if (nextVTableThunkIndex < layout.vtable_thunks().size() && + layout.vtable_thunks()[nextVTableThunkIndex].first == + componentIndex) { + cgm.errorNYI("getVTableComponent: CK_FunctionPointer: thunk"); + return mlir::Attribute(); + } else { + // Otherwise we can use the method definition directly. + cir::FuncType fnTy = cgm.getTypes().getFunctionTypeForVTable(gd); + fnPtr = cgm.getAddrOfFunction(gd, fnTy, /*ForVTable=*/true); + } + + return cir::GlobalViewAttr::get( + builder.getUInt8PtrTy(), + mlir::FlatSymbolRefAttr::get(fnPtr.getSymNameAttr())); + } + } + + llvm_unreachable("Unexpected vtable component kind"); +} + +void CIRGenVTables::createVTableInitializer(cir::GlobalOp &vtableOp, + const clang::VTableLayout &layout, + mlir::Attribute rtti, + bool vtableHasLocalLinkage) { + mlir::Type componentType = getVTableComponentType(); + + const llvm::SmallVector<unsigned, 4> &addressPoints = + layout.getAddressPointIndices(); + unsigned nextVTableThunkIndex = 0; + + if (layout.getNumVTables() > 1) + cgm.errorNYI("emitVTableDefinitions: multiple vtables"); + + // We'll need a loop here to handle multiple vtables, but for now we only + // support one. + unsigned vtableIndex = 0; + size_t vtableStart = layout.getVTableOffset(vtableIndex); + size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex); + + // Build a ConstArrayAttr of the vtable components. + llvm::SmallVector<mlir::Attribute, 4> components; ---------------- erichkeane wrote:
```suggestion llvm::SmallVector<mlir::Attribute> components; ``` https://github.com/llvm/llvm-project/pull/154808 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits