@@ -22,6 +22,7 @@ class Father {
22
22
23
23
class Child : public Mother , public Father {
24
24
public:
25
+ Child ();
25
26
void MotherKey () override ;
26
27
};
27
28
@@ -36,6 +37,50 @@ void Child::MotherKey() {}
36
37
// CIR-DAG: !rec_Mother = !cir.record<class "Mother" {!cir.vptr}
37
38
// CIR-DAG: !rec_Child = !cir.record<class "Child" {!rec_Mother, !rec_Father}
38
39
40
+ // Child vtable
41
+
42
+ // CIR: cir.global "private" external @_ZTV5Child = #cir.vtable<{
43
+ // CIR-SAME: #cir.const_array<[
44
+ // CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
45
+ // CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
46
+ // CIR-SAME: #cir.global_view<@_ZN5Child9MotherKeyEv> : !cir.ptr<!u8i>,
47
+ // CIR-SAME: #cir.global_view<@_ZN6Mother12MotherNonKeyEv> : !cir.ptr<!u8i>
48
+ // CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 4>,
49
+ // CIR-SAME: #cir.const_array<[
50
+ // CIR-SAME: #cir.ptr<-8 : i64> : !cir.ptr<!u8i>,
51
+ // CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,
52
+ // CIR-SAME: #cir.global_view<@_ZN6Father9FatherKeyEv> : !cir.ptr<!u8i>
53
+ // CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 3>
54
+ // CIR-SAME: }> : [[CHILD_VTABLE_TYPE]]
55
+
56
+ // LLVM: @_ZTV5Child = global { [4 x ptr], [3 x ptr] } {
57
+ // LLVM-SAME: [4 x ptr] [
58
+ // LLVM-SAME: ptr null,
59
+ // LLVM-SAME: ptr null,
60
+ // LLVM-SAME: ptr @_ZN5Child9MotherKeyEv,
61
+ // LLVM-SAME: ptr @_ZN6Mother12MotherNonKeyEv
62
+ // LLVM-SAME: ],
63
+ // LLVM-SAME: [3 x ptr] [
64
+ // LLVM-SAME: ptr inttoptr (i64 -8 to ptr),
65
+ // LLVM-SAME: ptr null,
66
+ // LLVM-SAME: ptr @_ZN6Father9FatherKeyEv
67
+ // LLVM-SAME: ]
68
+ // LLVM-SAME: }
69
+
70
+ // OGCG: @_ZTV5Child = unnamed_addr constant { [4 x ptr], [3 x ptr] } {
71
+ // OGCG-SAME: [4 x ptr] [
72
+ // OGCG-SAME: ptr null,
73
+ // OGCG-SAME: ptr null,
74
+ // OGCG-SAME: ptr @_ZN5Child9MotherKeyEv,
75
+ // OGCG-SAME: ptr @_ZN6Mother12MotherNonKeyEv
76
+ // OGCG-SAME: ],
77
+ // OGCG-SAME: [3 x ptr] [
78
+ // OGCG-SAME: ptr inttoptr (i64 -8 to ptr),
79
+ // OGCG-SAME: ptr null,
80
+ // OGCG-SAME: ptr @_ZN6Father9FatherKeyEv
81
+ // OGCG-SAME: ]
82
+ // OGCG-SAME: }
83
+
39
84
// Mother vtable
40
85
41
86
// CIR: cir.global "private" external @_ZTV6Mother = #cir.vtable<{
@@ -91,46 +136,48 @@ void Child::MotherKey() {}
91
136
// OGCG-SAME: ]
92
137
// OGCG-SAME: }
93
138
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
139
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: }
140
+ Child::Child () {}
141
+
142
+ // CIR: cir.func {{.*}} @_ZN5ChildC2Ev(%[[THIS_ARG:.*]]: !cir.ptr<!rec_Child>
143
+ // CIR: %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
144
+ // CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
145
+ // CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
146
+ // CIR: %[[MOTHER_BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Child> nonnull [0] -> !cir.ptr<!rec_Mother>
147
+ // CIR: cir.call @_ZN6MotherC2Ev(%[[MOTHER_BASE]]) nothrow : (!cir.ptr<!rec_Mother>) -> ()
148
+ // CIR: %[[FATHER_BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Child> nonnull [8] -> !cir.ptr<!rec_Father>
149
+ // CIR: cir.call @_ZN6FatherC2Ev(%[[FATHER_BASE]]) nothrow : (!cir.ptr<!rec_Father>) -> ()
150
+ // CIR: %[[CHILD_VPTR:.*]] = cir.vtable.address_point(@_ZTV5Child, address_point = <index = 0, offset = 2>) : !cir.vptr
151
+ // CIR: %[[CHILD_VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Child> -> !cir.ptr<!cir.vptr>
152
+ // CIR: cir.store{{.*}} %[[CHILD_VPTR]], %[[CHILD_VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>
153
+ // CIR: %[[FATHER_IN_CHILD_VPTR:.*]] = cir.vtable.address_point(@_ZTV5Child, address_point = <index = 1, offset = 2>) : !cir.vptr
154
+ // CIR: %[[FATHER_BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Child> nonnull [8] -> !cir.ptr<!rec_Father>
155
+ // CIR: %[[FATHER_IN_CHILD_VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[FATHER_BASE]] : !cir.ptr<!rec_Father> -> !cir.ptr<!cir.vptr>
156
+ // CIR: cir.store{{.*}} %[[FATHER_IN_CHILD_VPTR]], %[[FATHER_IN_CHILD_VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>
157
+ // CIR: cir.return
158
+
159
+ // The GEP instructions are different between LLVM and OGCG, but they calculate the same addresses.
160
+
161
+ // LLVM: define{{.*}} void @_ZN5ChildC2Ev(ptr{{.*}} %[[THIS_ARG:.*]])
162
+ // LLVM: %[[THIS_ADDR:.*]] = alloca ptr
163
+ // LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
164
+ // LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
165
+ // LLVM: call void @_ZN6MotherC2Ev(ptr{{.*}} %[[THIS]])
166
+ // LLVM: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i32 8
167
+ // LLVM: call void @_ZN6FatherC2Ev(ptr{{.*}} %[[FATHER_BASE]])
168
+ // LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV5Child, i64 16), ptr %[[THIS]]
169
+ // LLVM: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i32 8
170
+ // LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV5Child, i64 48), ptr %[[FATHER_BASE]]
171
+ // LLVM: ret void
172
+
173
+ // OGCG: define{{.*}} void @_ZN5ChildC2Ev(ptr{{.*}} %[[THIS_ARG:.*]])
174
+ // OGCG: %[[THIS_ADDR:.*]] = alloca ptr
175
+ // OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
176
+ // OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
177
+ // OGCG: call void @_ZN6MotherC2Ev(ptr {{.*}} %[[THIS]])
178
+ // OGCG: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i64 8
179
+ // OGCG: call void @_ZN6FatherC2Ev(ptr{{.*}} %[[FATHER_BASE]])
180
+ // OGCG: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV5Child, i32 0, i32 0, i32 2), ptr %[[THIS]]
181
+ // OGCG: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i64 8
182
+ // OGCG: store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV5Child, i32 0, i32 1, i32 2), ptr %[[FATHER_BASE]]
183
+ // OGCG: ret void
0 commit comments