================
@@ -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

Reply via email to