Skip to content

Commit 66f93df

Browse files
authored
[CIR] Add support for delegating constructors with VTT args (#156970)
This adds support for handling delegating constructors with VTT arguments.
1 parent 203a0ac commit 66f93df

File tree

2 files changed

+263
-3
lines changed

2 files changed

+263
-3
lines changed

clang/lib/CIR/CodeGen/CIRGenClass.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -820,9 +820,8 @@ mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
820820
uint64_t subVTTIndex;
821821

822822
if (delegating) {
823-
cgm.errorNYI(rd->getSourceRange(),
824-
"getVTTParameter: delegating constructor");
825-
return {};
823+
// If this is a delegating constructor call, just load the VTT.
824+
return loadCXXVTT();
826825
} else if (rd == base) {
827826
// If the record matches the base, this is the complete ctor/dtor
828827
// variant calling the base variant in a class with virtual bases.

clang/test/CIR/CodeGen/delegating-ctor.cpp

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,264 @@ DelegatingWithZeroing::DelegatingWithZeroing(int) : DelegatingWithZeroing() {}
7070
// OGCG: store i32 %[[I_ARG]], ptr %[[I_ADDR]]
7171
// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
7272
// OGCG: call void @llvm.memset.p0.i64(ptr align 4 %[[THIS]], i8 0, i64 4, i1 false)
73+
74+
void other();
75+
76+
class Base {
77+
public:
78+
Base() { squawk(); }
79+
80+
virtual void squawk();
81+
};
82+
83+
class Derived : public virtual Base {
84+
public:
85+
Derived();
86+
Derived(const void *inVoid);
87+
88+
virtual void squawk();
89+
};
90+
91+
Derived::Derived() : Derived(nullptr) { other(); }
92+
Derived::Derived(const void *inVoid) { squawk(); }
93+
94+
// Note: OGCG emits the constructors in a different order.
95+
// OGCG: define {{.*}} void @_ZN7DerivedC2Ev(ptr {{.*}} %[[THIS_ARG:.*]], ptr {{.*}} %[[VTT_ARG:.*]])
96+
// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
97+
// OGCG: %[[VTT_ADDR:.*]] = alloca ptr
98+
// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
99+
// OGCG: store ptr %[[VTT_ARG]], ptr %[[VTT_ADDR]]
100+
// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
101+
// OGCG: %[[VTT:.*]] = load ptr, ptr %[[VTT_ADDR]]
102+
// OGCG: call void @_ZN7DerivedC2EPKv(ptr {{.*}} %[[THIS]], ptr {{.*}} %[[VTT]], ptr {{.*}} null)
103+
// OGCG: call void @_Z5otherv()
104+
// OGCG: ret void
105+
106+
// CIR: cir.func {{.*}} @_ZN7DerivedC2EPKv(
107+
// CIR-SAME: %[[THIS_ARG:.*]]: !cir.ptr<!rec_Derived>
108+
// CIR-SAME: %[[VTT_ARG:.*]]: !cir.ptr<!cir.ptr<!void>>
109+
// CIR-SAME: %[[INVOID_ARG:.*]]: !cir.ptr<!void>
110+
// CIR: %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
111+
// CIR: %[[VTT_ADDR:.*]] = cir.alloca {{.*}} ["vtt", init]
112+
// CIR: %[[INVOID_ADDR:.*]] = cir.alloca {{.*}} ["inVoid", init]
113+
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
114+
// CIR: cir.store %[[VTT_ARG]], %[[VTT_ADDR]]
115+
// CIR: cir.store %[[INVOID_ARG]], %[[INVOID_ADDR]]
116+
// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
117+
// CIR: %[[VTT:.*]] = cir.load{{.*}} %[[VTT_ADDR]]
118+
// CIR: %[[VPTR_GLOBAL_ADDR:.*]] = cir.vtt.address_point %[[VTT]] : !cir.ptr<!cir.ptr<!void>>, offset = 0 -> !cir.ptr<!cir.ptr<!void>>
119+
// CIR: %[[VPTR_PTR:.*]] = cir.cast(bitcast, %[[VPTR_GLOBAL_ADDR]] : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!cir.vptr>
120+
// CIR: %[[VPTR:.*]] = cir.load{{.*}} %[[VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr
121+
// CIR: %[[VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
122+
// CIR: cir.store{{.*}} %[[VPTR]], %[[VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>
123+
// CIR: %[[VPTR_BASE_ADDR:.*]] = cir.vtt.address_point %[[VTT]] : !cir.ptr<!cir.ptr<!void>>, offset = 1 -> !cir.ptr<!cir.ptr<!void>>
124+
// CIR: %[[VPTR_BASE_PTR:.*]] = cir.cast(bitcast, %[[VPTR_BASE_ADDR]] : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!cir.vptr>
125+
// CIR: %[[VPTR_BASE:.*]] = cir.load{{.*}} %[[VPTR_BASE_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr
126+
// CIR: %[[VPTR_DERIVED_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
127+
// CIR: %[[VPTR_DERIVED:.*]] = cir.load{{.*}} %[[VPTR_DERIVED_ADDR]] : !cir.ptr<!cir.vptr>, !cir.vptr
128+
// CIR: %[[VPTR_DERIVED_AS_I8PTR:.*]] = cir.cast(bitcast, %[[VPTR_DERIVED]] : !cir.vptr), !cir.ptr<!u8i>
129+
// CIR: %[[BASE_LOC_OFFSET:.*]] = cir.const #cir.int<-32> : !s64i
130+
// CIR: %[[BASE_OFFSET_PTR:.*]] = cir.ptr_stride(%[[VPTR_DERIVED_AS_I8PTR]] : !cir.ptr<!u8i>, %[[BASE_LOC_OFFSET]] : !s64i), !cir.ptr<!u8i>
131+
// CIR: %[[BASE_OFFSET_I64PTR:.*]] = cir.cast(bitcast, %[[BASE_OFFSET_PTR]] : !cir.ptr<!u8i>), !cir.ptr<!s64i>
132+
// CIR: %[[BASE_OFFSET:.*]] = cir.load{{.*}} %[[BASE_OFFSET_I64PTR]] : !cir.ptr<!s64i>, !s64i
133+
// CIR: %[[THIS_AS_I8PTR:.*]] = cir.cast(bitcast, %[[THIS]] : !cir.ptr<!rec_Derived>), !cir.ptr<!u8i>
134+
// CIR: %[[BASE_PTR:.*]] = cir.ptr_stride(%[[THIS_AS_I8PTR]] : !cir.ptr<!u8i>, %[[BASE_OFFSET]] : !s64i), !cir.ptr<!u8i>
135+
// CIR: %[[BASE_AS_I8PTR:.*]] = cir.cast(bitcast, %[[BASE_PTR]] : !cir.ptr<!u8i>), !cir.ptr<!rec_Derived>
136+
// CIR: %[[BASE_VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[BASE_AS_I8PTR]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
137+
// CIR: cir.store{{.*}} %[[VPTR_BASE]], %[[BASE_VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>
138+
// CIR: %[[VPTR_BASE_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
139+
// CIR: %[[VPTR_BASE:.*]] = cir.load{{.*}} %[[VPTR_BASE_ADDR]] : !cir.ptr<!cir.vptr>, !cir.vptr
140+
// CIR: %[[SQUAWK_FN_ADDR:.*]] = cir.vtable.get_virtual_fn_addr %[[VPTR_BASE]][0] : !cir.vptr -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Derived>)>>>
141+
// CIR: %[[SQUAWK:.*]] = cir.load{{.*}} %[[SQUAWK_FN_ADDR]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Derived>)>>>, !cir.ptr<!cir.func<(!cir.ptr<!rec_Derived>)>>
142+
// CIR: cir.call %[[SQUAWK]](%[[THIS]]) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_Derived>)>>, !cir.ptr<!rec_Derived>) -> ()
143+
// CIR: cir.return
144+
145+
// LLVM: define {{.*}} void @_ZN7DerivedC2EPKv(ptr %[[THIS_ARG:.*]], ptr %[[VTT_ARG:.*]], ptr %[[INVOID_ARG:.*]])
146+
// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
147+
// LLVM: %[[VTT_ADDR:.*]] = alloca ptr
148+
// LLVM: %[[INVOID_ADDR:.*]] = alloca ptr
149+
// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
150+
// LLVM: store ptr %[[VTT_ARG]], ptr %[[VTT_ADDR]]
151+
// LLVM: store ptr %[[INVOID_ARG]], ptr %[[INVOID_ADDR]]
152+
// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
153+
// LLVM: %[[VTT:.*]] = load ptr, ptr %[[VTT_ADDR]]
154+
// LLVM: %[[VPTR:.*]] = load ptr, ptr %[[VTT]]
155+
// LLVM: store ptr %[[VPTR]], ptr %[[THIS]]
156+
// LLVM: %[[VTT_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VTT]], i32 1
157+
// LLVM: %[[VPTR_BASE:.*]] = load ptr, ptr %[[VTT_ADDR]]
158+
// LLVM: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
159+
// LLVM: %[[BASE_OFFSET_ADDR:.*]] = getelementptr i8, ptr %[[VPTR]], i64 -32
160+
// LLVM: %[[BASE_OFFSET:.*]] = load i64, ptr %[[BASE_OFFSET_ADDR]]
161+
// LLVM: %[[BASE_PTR:.*]] = getelementptr i8, ptr %[[THIS]], i64 %[[BASE_OFFSET]]
162+
// LLVM: store ptr %[[VPTR_BASE]], ptr %[[BASE_PTR]]
163+
// LLVM: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
164+
// LLVM: %[[SQUAWK_FN_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VPTR]], i32 0
165+
// LLVM: %[[SQUAWK:.*]] = load ptr, ptr %[[SQUAWK_FN_ADDR]]
166+
// LLVM: call void %[[SQUAWK]](ptr %[[THIS]])
167+
// LLVM: ret void
168+
169+
// OGCG: define {{.*}} void @_ZN7DerivedC2EPKv(ptr {{.*}} %[[THIS_ARG:.*]], ptr {{.*}} %[[VTT_ARG:.*]], ptr {{.*}} %[[INVOID_ARG:.*]])
170+
// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
171+
// OGCG: %[[VTT_ADDR:.*]] = alloca ptr
172+
// OGCG: %[[INVOID_ADDR:.*]] = alloca ptr
173+
// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
174+
// OGCG: store ptr %[[VTT_ARG]], ptr %[[VTT_ADDR]]
175+
// OGCG: store ptr %[[INVOID_ARG]], ptr %[[INVOID_ADDR]]
176+
// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
177+
// OGCG: %[[VTT:.*]] = load ptr, ptr %[[VTT_ADDR]]
178+
// OGCG: %[[VPTR:.*]] = load ptr, ptr %[[VTT]]
179+
// OGCG: store ptr %[[VPTR]], ptr %[[THIS]]
180+
// OGCG: %[[VTT_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VTT]], i64 1
181+
// OGCG: %[[VPTR_BASE:.*]] = load ptr, ptr %[[VTT_ADDR]]
182+
// OGCG: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
183+
// OGCG: %[[BASE_OFFSET_ADDR:.*]] = getelementptr i8, ptr %[[VPTR]], i64 -32
184+
// OGCG: %[[BASE_OFFSET:.*]] = load i64, ptr %[[BASE_OFFSET_ADDR]]
185+
// OGCG: %[[BASE_PTR:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i64 %[[BASE_OFFSET]]
186+
// OGCG: store ptr %[[VPTR_BASE]], ptr %[[BASE_PTR]]
187+
// OGCG: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
188+
// OGCG: %[[SQUAWK_FN_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VPTR]], i64 0
189+
// OGCG: %[[SQUAWK:.*]] = load ptr, ptr %[[SQUAWK_FN_ADDR]]
190+
// OGCG: call void %[[SQUAWK]](ptr {{.*}} %[[THIS]])
191+
// OGCG: ret void
192+
193+
// CIR: cir.func {{.*}} @_ZN7DerivedC2Ev(%[[THIS_ARG:.*]]: !cir.ptr<!rec_Derived> {{.*}}, %[[VTT_ARG:.*]]: !cir.ptr<!cir.ptr<!void>> {{.*}})
194+
// CIR: %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
195+
// CIR: %[[VTT_ADDR:.*]] = cir.alloca {{.*}} ["vtt", init]
196+
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
197+
// CIR: cir.store %[[VTT_ARG]], %[[VTT_ADDR]]
198+
// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
199+
// CIR: %[[VTT:.*]] = cir.load {{.*}} %[[VTT_ADDR]]
200+
// CIR: %[[NULLPTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
201+
// CIR: cir.call @_ZN7DerivedC2EPKv(%[[THIS]], %[[VTT]], %[[NULLPTR]]) : (!cir.ptr<!rec_Derived>, !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>) -> ()
202+
// CIR: cir.call @_Z5otherv() : () -> ()
203+
// CIR: cir.return
204+
205+
// LLVM: define {{.*}} void @_ZN7DerivedC2Ev(ptr %[[THIS_ARG:.*]], ptr %[[VTT_ARG:.*]])
206+
// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
207+
// LLVM: %[[VTT_ADDR:.*]] = alloca ptr
208+
// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
209+
// LLVM: store ptr %[[VTT_ARG]], ptr %[[VTT_ADDR]]
210+
// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
211+
// LLVM: %[[VTT:.*]] = load ptr, ptr %[[VTT_ADDR]]
212+
// LLVM: call void @_ZN7DerivedC2EPKv(ptr %[[THIS]], ptr %[[VTT]], ptr null)
213+
// LLVM: call void @_Z5otherv()
214+
// LLVM: ret void
215+
216+
// See above for the OGCG _ZN7DerivedC2Ev constructor.
217+
218+
// CIR: cir.func {{.*}} @_ZN4BaseC2Ev(%[[THIS_ARG:.*]]: !cir.ptr<!rec_Base> {{.*}})
219+
// CIR: %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
220+
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
221+
// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
222+
// CIR: %[[VTT_ADDR_POINT:.*]] = cir.vtable.address_point(@_ZTV4Base, address_point = <index = 0, offset = 2>) : !cir.vptr
223+
// CIR: %[[VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>
224+
// CIR: cir.store{{.*}} %[[VTT_ADDR_POINT]], %[[VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>
225+
// CIR: %[[VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>
226+
// CIR: %[[VPTR:.*]] = cir.load{{.*}} %[[VPTR_ADDR]] : !cir.ptr<!cir.vptr>, !cir.vptr
227+
// CIR: %[[VIRTUAL_FN_ADDR:.*]] = cir.vtable.get_virtual_fn_addr %[[VPTR]][0] : !cir.vptr -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>
228+
// CIR: %[[VIRTUAL_FN:.*]] = cir.load{{.*}} %[[VIRTUAL_FN_ADDR]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>, !cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>
229+
// CIR: cir.call %[[VIRTUAL_FN]](%[[THIS]]) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>, !cir.ptr<!rec_Base>) -> ()
230+
// CIR: cir.return
231+
232+
// LLVM: define {{.*}} void @_ZN4BaseC2Ev(ptr %[[THIS_ARG:.*]])
233+
// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
234+
// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
235+
// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
236+
// LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV4Base, i64 16), ptr %[[THIS]]
237+
// LLVM: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
238+
// LLVM: %[[SQUAWK_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VPTR]], i32 0
239+
// LLVM: %[[SQUAWK:.*]] = load ptr, ptr %[[SQUAWK_ADDR]]
240+
// LLVM: call void %[[SQUAWK]](ptr %[[THIS]])
241+
// LLVM: ret void
242+
243+
// The base constructor is emitted last for OGCG.
244+
// The _ZN7DerivedC1Ev constructor is emitted earlier for OGCG.
245+
246+
// OGCG: define {{.*}} void @_ZN7DerivedC1Ev(ptr {{.*}} %[[THIS_ARG:.*]])
247+
// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
248+
// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
249+
// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
250+
// OGCG: call void @_ZN7DerivedC1EPKv(ptr {{.*}} %[[THIS]], ptr {{.*}} null)
251+
// OGCG: call void @_Z5otherv()
252+
// OGCG: ret void
253+
254+
// CIR: cir.func {{.*}} @_ZN7DerivedC1EPKv(%[[THIS_ARG:.*]]: !cir.ptr<!rec_Derived> {{.*}}, %[[INVOID_ARG:.*]]: !cir.ptr<!void> {{.*}})
255+
// CIR: %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
256+
// CIR: %[[INVOID_ADDR:.*]] = cir.alloca {{.*}} ["inVoid", init]
257+
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
258+
// CIR: cir.store %[[INVOID_ARG]], %[[INVOID_ADDR]]
259+
// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
260+
// CIR: %[[BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
261+
// CIR: cir.call @_ZN4BaseC2Ev(%[[BASE]])
262+
// CIR: %[[VPTR_GLOBAL:.*]] = cir.vtable.address_point(@_ZTV7Derived, address_point = <index = 0, offset = 4>) : !cir.vptr
263+
// CIR: %[[VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
264+
// CIR: cir.store{{.*}} %[[VPTR_GLOBAL]], %[[VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>
265+
// CIR: %[[VPTR_GLOBAL:.*]] = cir.vtable.address_point(@_ZTV7Derived, address_point = <index = 0, offset = 4>) : !cir.vptr
266+
// CIR: %[[VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
267+
// CIR: cir.store{{.*}} %[[VPTR_GLOBAL]], %[[VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>
268+
// CIR: %[[VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>
269+
// CIR: %[[VPTR:.*]] = cir.load{{.*}} %[[VPTR_ADDR]] : !cir.ptr<!cir.vptr>, !cir.vptr
270+
// CIR: %[[SQUAWK_ADDR:.*]] = cir.vtable.get_virtual_fn_addr %[[VPTR]][0] : !cir.vptr -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Derived>)>>>
271+
// CIR: %[[SQUAWK:.*]] = cir.load{{.*}} %[[SQUAWK_ADDR]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Derived>)>>>, !cir.ptr<!cir.func<(!cir.ptr<!rec_Derived>)>>
272+
// CIR: cir.call %[[SQUAWK]](%[[THIS]])
273+
// CIR: cir.return
274+
275+
// LLVM: define {{.*}} void @_ZN7DerivedC1EPKv(ptr %[[THIS_ARG:.*]], ptr %[[INVOID_ARG:.*]])
276+
// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
277+
// LLVM: %[[INVOID_ADDR:.*]] = alloca ptr
278+
// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
279+
// LLVM: store ptr %[[INVOID_ARG]], ptr %[[INVOID_ADDR]]
280+
// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
281+
// LLVM: call void @_ZN4BaseC2Ev(ptr %[[THIS]])
282+
// LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV7Derived, i64 32), ptr %[[THIS]]
283+
// LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV7Derived, i64 32), ptr %[[THIS]]
284+
// LLVM: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
285+
// LLVM: %[[SQUAWK_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VPTR]], i32 0
286+
// LLVM: %[[SQUAWK:.*]] = load ptr, ptr %[[SQUAWK_ADDR]]
287+
// LLVM: call void %[[SQUAWK]](ptr %[[THIS]])
288+
// LLVM: ret void
289+
290+
// OGCG: define {{.*}} void @_ZN7DerivedC1EPKv(ptr {{.*}} %[[THIS_ARG:.*]], ptr {{.*}} %[[INVOID_ARG:.*]])
291+
// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
292+
// OGCG: %[[INVOID_ADDR:.*]] = alloca ptr
293+
// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
294+
// OGCG: store ptr %[[INVOID_ARG]], ptr %[[INVOID_ADDR]]
295+
// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
296+
// OGCG: call void @_ZN4BaseC2Ev(ptr {{.*}} %[[THIS]])
297+
// OGCG: store ptr getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTV7Derived, i32 0, i32 0, i32 4), ptr %[[THIS]]
298+
// OGCG: store ptr getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTV7Derived, i32 0, i32 0, i32 4), ptr %[[THIS]]
299+
// OGCG: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
300+
// OGCG: %[[SQUAWK_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VPTR]], i64 0
301+
// OGCG: %[[SQUAWK:.*]] = load ptr, ptr %[[SQUAWK_ADDR]]
302+
// OGCG: call void %[[SQUAWK]](ptr {{.*}} %[[THIS]])
303+
// OGCG: ret void
304+
305+
// CIR: cir.func {{.*}} @_ZN7DerivedC1Ev(%[[THIS_ARG:.*]]: !cir.ptr<!rec_Derived> {{.*}})
306+
// CIR: %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
307+
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
308+
// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
309+
// CIR: %[[NULLPTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
310+
// CIR: cir.call @_ZN7DerivedC1EPKv(%[[THIS]], %[[NULLPTR]]) : (!cir.ptr<!rec_Derived>, !cir.ptr<!void>) -> ()
311+
// CIR: cir.call @_Z5otherv() : () -> ()
312+
// CIR: cir.return
313+
314+
// LLVM: define {{.*}} void @_ZN7DerivedC1Ev(ptr %[[THIS_ARG:.*]])
315+
// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
316+
// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
317+
// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
318+
// LLVM: call void @_ZN7DerivedC1EPKv(ptr %[[THIS]], ptr null)
319+
// LLVM: call void @_Z5otherv()
320+
// LLVM: ret void
321+
322+
// The _ZN7DerivedC1Ev constructor was emitted earlier for OGCG.
323+
324+
// OGCG: define {{.*}} void @_ZN4BaseC2Ev(ptr {{.*}} %[[THIS_ARG:.*]])
325+
// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
326+
// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
327+
// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
328+
// OGCG: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV4Base, i32 0, i32 0, i32 2), ptr %[[THIS]]
329+
// OGCG: %[[VPTR:.*]] = load ptr, ptr %[[THIS]]
330+
// OGCG: %[[SQUAWK_ADDR:.*]] = getelementptr inbounds ptr, ptr %[[VPTR]], i64 0
331+
// OGCG: %[[SQUAWK:.*]] = load ptr, ptr %[[SQUAWK_ADDR]]
332+
// OGCG: call void %[[SQUAWK]](ptr {{.*}} %[[THIS]])
333+
// OGCG: ret void

0 commit comments

Comments
 (0)