Skip to content

Commit d467bd9

Browse files
authored
[CIR] Add support for emitting multi-vtables (llvm#155027)
This change adds support for emitting multiple tables in a global vtable object to handle the case of multiple-inheritence.
1 parent 7153392 commit d467bd9

File tree

2 files changed

+154
-23
lines changed

2 files changed

+154
-23
lines changed

clang/lib/CIR/CodeGen/CIRGenVTables.cpp

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -144,33 +144,28 @@ void CIRGenVTables::createVTableInitializer(cir::GlobalOp &vtableOp,
144144
layout.getAddressPointIndices();
145145
unsigned nextVTableThunkIndex = 0;
146146

147-
if (layout.getNumVTables() > 1)
148-
cgm.errorNYI("emitVTableDefinitions: multiple vtables");
149-
150-
// We'll need a loop here to handle multiple vtables, but for now we only
151-
// support one.
152-
unsigned vtableIndex = 0;
153-
size_t vtableStart = layout.getVTableOffset(vtableIndex);
154-
size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex);
155-
156-
// Build a ConstArrayAttr of the vtable components.
157-
llvm::SmallVector<mlir::Attribute> components;
158-
for (size_t componentIndex = vtableStart; componentIndex < vtableEnd;
159-
++componentIndex) {
160-
components.push_back(
161-
getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
162-
addressPoints[vtableIndex], vtableHasLocalLinkage));
163-
}
164-
165147
mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
166148

167-
// Create a ConstArrayAttr to hold the components.
168-
auto arr = cir::ConstArrayAttr::get(
169-
cir::ArrayType::get(componentType, components.size()),
170-
mlir::ArrayAttr::get(mlirContext, components));
149+
SmallVector<mlir::Attribute> vtables;
150+
for (auto [vtableIndex, addressPoint] : llvm::enumerate(addressPoints)) {
151+
// Build a ConstArrayAttr of the vtable components.
152+
size_t vtableStart = layout.getVTableOffset(vtableIndex);
153+
size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex);
154+
llvm::SmallVector<mlir::Attribute> components;
155+
components.reserve(vtableEnd - vtableStart);
156+
for (size_t componentIndex : llvm::seq(vtableStart, vtableEnd))
157+
components.push_back(
158+
getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
159+
addressPoint, vtableHasLocalLinkage));
160+
// Create a ConstArrayAttr to hold the components.
161+
auto arr = cir::ConstArrayAttr::get(
162+
cir::ArrayType::get(componentType, components.size()),
163+
mlir::ArrayAttr::get(mlirContext, components));
164+
vtables.push_back(arr);
165+
}
171166

172167
// Create a ConstRecordAttr to hold the component array.
173-
const auto members = mlir::ArrayAttr::get(mlirContext, {arr});
168+
const auto members = mlir::ArrayAttr::get(mlirContext, vtables);
174169
cir::ConstRecordAttr record = cgm.getBuilder().getAnonConstRecord(members);
175170

176171
// Create a VTableAttr
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fno-rtti -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fno-rtti -fclangir -emit-llvm %s -o %t-cir.ll
4+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fno-rtti -emit-llvm %s -o %t.ll
6+
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
7+
8+
// Note: This test is using -fno-rtti so that we can delay implemntation of that handling.
9+
// When rtti handling for vtables is implemented, that option should be removed.
10+
11+
class Mother {
12+
public:
13+
virtual void MotherKey();
14+
void simple() { }
15+
virtual void MotherNonKey() {}
16+
};
17+
18+
class Father {
19+
public:
20+
virtual void FatherKey();
21+
};
22+
23+
class Child : public Mother, public Father {
24+
public:
25+
void MotherKey() override;
26+
};
27+
28+
void Mother::MotherKey() {}
29+
void Father::FatherKey() {}
30+
void Child::MotherKey() {}
31+
32+
// CIR-DAG: [[MOTHER_VTABLE_TYPE:.*]] = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>
33+
// CIR-DAG: [[FATHER_VTABLE_TYPE:.*]] = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 3>}>
34+
// CIR-DAG: [[CHILD_VTABLE_TYPE:.*]] = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>, !cir.array<!cir.ptr<!u8i> x 3>}>
35+
// CIR-DAG: !rec_Father = !cir.record<class "Father" {!cir.vptr}
36+
// CIR-DAG: !rec_Mother = !cir.record<class "Mother" {!cir.vptr}
37+
// CIR-DAG: !rec_Child = !cir.record<class "Child" {!rec_Mother, !rec_Father}
38+
39+
// Mother vtable
40+
41+
// CIR: cir.global "private" external @_ZTV6Mother = #cir.vtable<{
42+
// CIR-SAME: #cir.const_array<[
43+
// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
44+
// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
45+
// CIR-SAME: #cir.global_view<@_ZN6Mother9MotherKeyEv> : !cir.ptr<!u8i>,
46+
// CIR-SAME: #cir.global_view<@_ZN6Mother12MotherNonKeyEv> : !cir.ptr<!u8i>
47+
// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 4>
48+
// CIR-SAME: }> : [[MOTHER_VTABLE_TYPE]]
49+
50+
// LLVM: @_ZTV6Mother = global { [4 x ptr] } {
51+
// LLVM-SAME: [4 x ptr] [
52+
// LLVM-SAME: ptr null,
53+
// LLVM-SAME: ptr null,
54+
// LLVM-SAME: ptr @_ZN6Mother9MotherKeyEv,
55+
// LLVM-SAME: ptr @_ZN6Mother12MotherNonKeyEv
56+
// LLVM-SAME: ]
57+
// LLVM-SAME: }
58+
59+
// OGCG: @_ZTV6Mother = unnamed_addr constant { [4 x ptr] } {
60+
// OGCG-SAME: [4 x ptr] [
61+
// OGCG-SAME: ptr null,
62+
// OGCG-SAME: ptr null,
63+
// OGCG-SAME: ptr @_ZN6Mother9MotherKeyEv,
64+
// OGCG-SAME: ptr @_ZN6Mother12MotherNonKeyEv
65+
// OGCG-SAME: ]
66+
// OGCG-SAME: }
67+
68+
// Father vtable
69+
70+
// CIR: cir.global "private" external @_ZTV6Father = #cir.vtable<{
71+
// CIR-SAME: #cir.const_array<[
72+
// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
73+
// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
74+
// CIR-SAME: #cir.global_view<@_ZN6Father9FatherKeyEv> : !cir.ptr<!u8i>
75+
// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 3>
76+
// CIR-SAME: }> : [[FATHER_VTABLE_TYPE]]
77+
78+
// LLVM: @_ZTV6Father = global { [3 x ptr] } {
79+
// LLVM-SAME: [3 x ptr] [
80+
// LLVM-SAME: ptr null,
81+
// LLVM-SAME: ptr null,
82+
// LLVM-SAME: ptr @_ZN6Father9FatherKeyEv
83+
// LLVM-SAME: ]
84+
// LLVM-SAME: }
85+
86+
// OGCG: @_ZTV6Father = unnamed_addr constant { [3 x ptr] } {
87+
// OGCG-SAME: [3 x ptr] [
88+
// OGCG-SAME: ptr null,
89+
// OGCG-SAME: ptr null,
90+
// OGCG-SAME: ptr @_ZN6Father9FatherKeyEv
91+
// OGCG-SAME: ]
92+
// OGCG-SAME: }
93+
94+
// Child vtable
95+
96+
// CIR: cir.global "private" external @_ZTV5Child = #cir.vtable<{
97+
// CIR-SAME: #cir.const_array<[
98+
// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
99+
// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
100+
// CIR-SAME: #cir.global_view<@_ZN5Child9MotherKeyEv> : !cir.ptr<!u8i>,
101+
// CIR-SAME: #cir.global_view<@_ZN6Mother12MotherNonKeyEv> : !cir.ptr<!u8i>
102+
// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 4>,
103+
// CIR-SAME: #cir.const_array<[
104+
// CIR-SAME: #cir.ptr<-8 : i64> : !cir.ptr<!u8i>,
105+
// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
106+
// CIR-SAME: #cir.global_view<@_ZN6Father9FatherKeyEv> : !cir.ptr<!u8i>
107+
// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 3>
108+
// CIR-SAME: }> : [[CHILD_VTABLE_TYPE]]
109+
110+
// LLVM: @_ZTV5Child = global { [4 x ptr], [3 x ptr] } {
111+
// LLVM-SAME: [4 x ptr] [
112+
// LLVM-SAME: ptr null,
113+
// LLVM-SAME: ptr null,
114+
// LLVM-SAME: ptr @_ZN5Child9MotherKeyEv,
115+
// LLVM-SAME: ptr @_ZN6Mother12MotherNonKeyEv
116+
// LLVM-SAME: ],
117+
// LLVM-SAME: [3 x ptr] [
118+
// LLVM-SAME: ptr inttoptr (i64 -8 to ptr),
119+
// LLVM-SAME: ptr null,
120+
// LLVM-SAME: ptr @_ZN6Father9FatherKeyEv
121+
// LLVM-SAME: ]
122+
// LLVM-SAME: }
123+
124+
// OGCG: @_ZTV5Child = unnamed_addr constant { [4 x ptr], [3 x ptr] } {
125+
// OGCG-SAME: [4 x ptr] [
126+
// OGCG-SAME: ptr null,
127+
// OGCG-SAME: ptr null,
128+
// OGCG-SAME: ptr @_ZN5Child9MotherKeyEv,
129+
// OGCG-SAME: ptr @_ZN6Mother12MotherNonKeyEv
130+
// OGCG-SAME: ],
131+
// OGCG-SAME: [3 x ptr] [
132+
// OGCG-SAME: ptr inttoptr (i64 -8 to ptr),
133+
// OGCG-SAME: ptr null,
134+
// OGCG-SAME: ptr @_ZN6Father9FatherKeyEv
135+
// OGCG-SAME: ]
136+
// OGCG-SAME: }

0 commit comments

Comments
 (0)