llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

This change adds support for emitting multiple tables in a global vtable object 
to handle the case of multiple-inheritence.

---
Full diff: https://github.com/llvm/llvm-project/pull/155027.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenVTables.cpp (+20-23) 
- (added) clang/test/CIR/CodeGen/multi-vtable.cpp (+136) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp 
b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index 438b483ccb9c2..28a630becc3dc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -144,33 +144,30 @@ void CIRGenVTables::createVTableInitializer(cir::GlobalOp 
&vtableOp,
       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> components;
-  for (size_t componentIndex = vtableStart; componentIndex < vtableEnd;
-       ++componentIndex) {
-    components.push_back(
-        getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
-                           addressPoints[vtableIndex], vtableHasLocalLinkage));
-  }
-
   mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
 
-  // Create a ConstArrayAttr to hold the components.
-  auto arr = cir::ConstArrayAttr::get(
-      cir::ArrayType::get(componentType, components.size()),
-      mlir::ArrayAttr::get(mlirContext, components));
+  SmallVector<mlir::Attribute> vtables;
+  for (unsigned vtableIndex = 0, endIndex = layout.getNumVTables();
+       vtableIndex != endIndex; ++vtableIndex) {
+    // Build a ConstArrayAttr of the vtable components.
+    size_t vtableStart = layout.getVTableOffset(vtableIndex);
+    size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex);
+    llvm::SmallVector<mlir::Attribute> components;
+    for (size_t componentIndex = vtableStart; componentIndex < vtableEnd;
+         ++componentIndex) {
+      components.push_back(getVTableComponent(
+          layout, componentIndex, rtti, nextVTableThunkIndex,
+          addressPoints[vtableIndex], vtableHasLocalLinkage));
+    }
+    // Create a ConstArrayAttr to hold the components.
+    auto arr = cir::ConstArrayAttr::get(
+        cir::ArrayType::get(componentType, components.size()),
+        mlir::ArrayAttr::get(mlirContext, components));
+    vtables.push_back(arr);
+  }
 
   // Create a ConstRecordAttr to hold the component array.
-  const auto members = mlir::ArrayAttr::get(mlirContext, {arr});
+  const auto members = mlir::ArrayAttr::get(mlirContext, vtables);
   cir::ConstRecordAttr record = cgm.getBuilder().getAnonConstRecord(members);
 
   // Create a VTableAttr
diff --git a/clang/test/CIR/CodeGen/multi-vtable.cpp 
b/clang/test/CIR/CodeGen/multi-vtable.cpp
new file mode 100644
index 0000000000000..c127285800844
--- /dev/null
+++ b/clang/test/CIR/CodeGen/multi-vtable.cpp
@@ -0,0 +1,136 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases 
-fno-rtti -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases 
-fno-rtti -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases 
-fno-rtti -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+// Note: This test is using -fno-rtti so that we can delay implemntation of 
that handling.
+//       When rtti handling for vtables is implemented, that option should be 
removed.
+
+class Mother {
+public:
+  virtual void MotherKey();
+  void simple() { }
+  virtual void MotherNonKey() {}
+};
+
+class Father {
+public:
+  virtual void FatherKey();
+};
+
+class Child : public Mother, public Father {
+public:
+  void MotherKey() override;
+};
+
+void Mother::MotherKey() {}
+void Father::FatherKey() {}
+void Child::MotherKey() {}
+
+// CIR-DAG: [[MOTHER_VTABLE_TYPE:.*]] = !cir.record<struct  
{!cir.array<!cir.ptr<!u8i> x 4>}>
+// CIR-DAG: [[FATHER_VTABLE_TYPE:.*]] = !cir.record<struct  
{!cir.array<!cir.ptr<!u8i> x 3>}>
+// CIR-DAG: [[CHILD_VTABLE_TYPE:.*]] = !cir.record<struct  
{!cir.array<!cir.ptr<!u8i> x 4>, !cir.array<!cir.ptr<!u8i> x 3>}>
+// CIR-DAG: !rec_Father = !cir.record<class "Father" {!cir.vptr}
+// CIR-DAG: !rec_Mother = !cir.record<class "Mother" {!cir.vptr}
+// CIR-DAG: !rec_Child = !cir.record<class "Child" {!rec_Mother, !rec_Father}
+
+// Mother vtable
+
+// CIR:      cir.global "private" external @_ZTV6Mother = #cir.vtable<{
+// CIR-SAME:      #cir.const_array<[
+// CIR-SAME:          #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:          #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:          #cir.global_view<@_ZN6Mother9MotherKeyEv> : 
!cir.ptr<!u8i>,
+// CIR-SAME:          #cir.global_view<@_ZN6Mother12MotherNonKeyEv> : 
!cir.ptr<!u8i>
+// CIR-SAME:      ]> : !cir.array<!cir.ptr<!u8i> x 4>
+// CIR-SAME: }> : [[MOTHER_VTABLE_TYPE]]
+
+// LLVM:      @_ZTV6Mother = global { [4 x ptr] } {
+// LLVM-SAME:     [4 x ptr] [
+// LLVM-SAME:         ptr null,
+// LLVM-SAME:         ptr null,
+// LLVM-SAME:         ptr @_ZN6Mother9MotherKeyEv,
+// LLVM-SAME:         ptr @_ZN6Mother12MotherNonKeyEv
+// LLVM-SAME:     ]
+// LLVM-SAME: }
+
+// OGCG:      @_ZTV6Mother = unnamed_addr constant { [4 x ptr] } {
+// OGCG-SAME:     [4 x ptr] [
+// OGCG-SAME:         ptr null,
+// OGCG-SAME:         ptr null,
+// OGCG-SAME:         ptr @_ZN6Mother9MotherKeyEv,
+// OGCG-SAME:         ptr @_ZN6Mother12MotherNonKeyEv
+// OGCG-SAME:     ]
+// OGCG-SAME: }
+
+// Father vtable
+
+// CIR:      cir.global "private" external @_ZTV6Father = #cir.vtable<{
+// CIR-SAME:     #cir.const_array<[
+// CIR-SAME:         #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:         #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:         #cir.global_view<@_ZN6Father9FatherKeyEv> : !cir.ptr<!u8i>
+// CIR-SAME:     ]> : !cir.array<!cir.ptr<!u8i> x 3>
+// CIR-SAME: }> : [[FATHER_VTABLE_TYPE]]
+
+// LLVM:      @_ZTV6Father = global { [3 x ptr] } {
+// LLVM-SAME:     [3 x ptr] [
+// LLVM-SAME:         ptr null,
+// LLVM-SAME:         ptr null,
+// LLVM-SAME:         ptr @_ZN6Father9FatherKeyEv
+// LLVM-SAME:     ]
+// LLVM-SAME: }
+
+// OGCG:      @_ZTV6Father = unnamed_addr constant { [3 x ptr] } {
+// OGCG-SAME:     [3 x ptr] [
+// OGCG-SAME:         ptr null,
+// OGCG-SAME:         ptr null,
+// OGCG-SAME:         ptr @_ZN6Father9FatherKeyEv
+// OGCG-SAME:     ]
+// OGCG-SAME: }
+
+// Child vtable
+
+// CIR:      cir.global "private" external @_ZTV5Child = #cir.vtable<{
+// CIR-SAME:     #cir.const_array<[
+// CIR-SAME:         #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:         #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:         #cir.global_view<@_ZN5Child9MotherKeyEv> : !cir.ptr<!u8i>,
+// CIR-SAME:         #cir.global_view<@_ZN6Mother12MotherNonKeyEv> : 
!cir.ptr<!u8i>
+// CIR-SAME:     ]> : !cir.array<!cir.ptr<!u8i> x 4>,
+// CIR-SAME:     #cir.const_array<[
+// CIR-SAME:         #cir.ptr<-8 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:         #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:         #cir.global_view<@_ZN6Father9FatherKeyEv> : !cir.ptr<!u8i>
+// CIR-SAME:     ]> : !cir.array<!cir.ptr<!u8i> x 3>
+// CIR-SAME: }> : [[CHILD_VTABLE_TYPE]]
+
+// LLVM:      @_ZTV5Child = global { [4 x ptr], [3 x ptr] } {
+// LLVM-SAME:     [4 x ptr] [
+// LLVM-SAME:         ptr null,
+// LLVM-SAME:         ptr null,
+// LLVM-SAME:         ptr @_ZN5Child9MotherKeyEv,
+// LLVM-SAME:         ptr @_ZN6Mother12MotherNonKeyEv
+// LLVM-SAME:     ],
+// LLVM-SAME:     [3 x ptr] [
+// LLVM-SAME:         ptr inttoptr (i64 -8 to ptr),
+// LLVM-SAME:         ptr null,
+// LLVM-SAME:         ptr @_ZN6Father9FatherKeyEv
+// LLVM-SAME:     ]
+// LLVM-SAME: }
+
+// OGCG:      @_ZTV5Child = unnamed_addr constant { [4 x ptr], [3 x ptr] } {
+// OGCG-SAME:     [4 x ptr] [
+// OGCG-SAME:         ptr null,
+// OGCG-SAME:         ptr null,
+// OGCG-SAME:         ptr @_ZN5Child9MotherKeyEv,
+// OGCG-SAME:         ptr @_ZN6Mother12MotherNonKeyEv
+// OGCG-SAME:     ],
+// OGCG-SAME:     [3 x ptr] [
+// OGCG-SAME:         ptr inttoptr (i64 -8 to ptr),
+// OGCG-SAME:         ptr null,
+// OGCG-SAME:         ptr @_ZN6Father9FatherKeyEv
+// OGCG-SAME:     ]
+// OGCG-SAME: }

``````````

</details>


https://github.com/llvm/llvm-project/pull/155027
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to