1 | // RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=i386-pc-win32 -emit-llvm -o %t |
2 | // RUN: FileCheck %s < %t |
3 | // RUN: FileCheck --check-prefix=CHECK2 %s < %t |
4 | |
5 | // For now, just make sure x86_64 doesn't crash. |
6 | // RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=x86_64-pc-win32 -emit-llvm -o %t |
7 | |
8 | struct VBase { |
9 | virtual ~VBase(); |
10 | virtual void foo(); |
11 | virtual void bar(); |
12 | int field; |
13 | }; |
14 | |
15 | struct B : virtual VBase { |
16 | B(); |
17 | virtual ~B(); |
18 | virtual void foo(); |
19 | virtual void bar(); |
20 | }; |
21 | |
22 | B::B() { |
23 | // CHECK-LABEL: define dso_local x86_thiscallcc %struct.B* @"??0B@@QAE@XZ" |
24 | // CHECK: %[[THIS:.*]] = load %struct.B*, %struct.B** |
25 | // CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] |
26 | |
27 | // Don't check the INIT_VBASES case as it's covered by the ctor tests. |
28 | |
29 | // CHECK: %[[SKIP_VBASES]] |
30 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
31 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0 |
32 | // ... |
33 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
34 | // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}} |
35 | // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** |
36 | // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] |
37 | |
38 | // Initialize vtorDisp: |
39 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
40 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0 |
41 | // ... |
42 | // CHECK: %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}} |
43 | // CHECK: %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8 |
44 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
45 | // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]] |
46 | // CHECK: %[[VTORDISP_i8:.*]] = getelementptr i8, i8* %[[VBASE_i8]], i32 -4 |
47 | // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32* |
48 | // CHECK: store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]] |
49 | |
50 | // CHECK: ret |
51 | } |
52 | |
53 | B::~B() { |
54 | // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ" |
55 | // Store initial this: |
56 | // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B* |
57 | // CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4 |
58 | // Reload and adjust the this parameter: |
59 | // CHECK: %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] |
60 | // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8* |
61 | // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8 |
62 | // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B* |
63 | |
64 | // Restore the vfptr that could have been changed by a subclass. |
65 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
66 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0 |
67 | // ... |
68 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
69 | // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}} |
70 | // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** |
71 | // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] |
72 | |
73 | // Initialize vtorDisp: |
74 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
75 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0 |
76 | // ... |
77 | // CHECK: %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}} |
78 | // CHECK: %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8 |
79 | // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
80 | // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]] |
81 | // CHECK: %[[VTORDISP_i8:.*]] = getelementptr i8, i8* %[[VBASE_i8]], i32 -4 |
82 | // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32* |
83 | // CHECK: store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]] |
84 | |
85 | foo(); // Avoid the "trivial destructor" optimization. |
86 | |
87 | // CHECK: ret |
88 | |
89 | // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* |
90 | // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}} |
91 | // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
92 | // CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8 |
93 | // CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B* |
94 | // CHECK2: call x86_thiscallcc void @"??1B@@UAE@XZ"(%struct.B* %[[B]]) |
95 | // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
96 | // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 8 |
97 | // CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase* |
98 | // CHECK2: call x86_thiscallcc void @"??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]]) |
99 | // CHECK2: ret |
100 | |
101 | // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GB@@UAEPAXI@Z" |
102 | // CHECK2: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4 |
103 | // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] |
104 | // CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
105 | // CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8:.*]], i32 -8 |
106 | // CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B* |
107 | // CHECK2: call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* %[[THIS]]) |
108 | // ... |
109 | // CHECK2: ret |
110 | } |
111 | |
112 | void B::foo() { |
113 | // CHECK-LABEL: define dso_local x86_thiscallcc void @"?foo@B@@UAEXXZ"(i8* |
114 | // |
115 | // B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we |
116 | // need to adjust 'this' before use. |
117 | // |
118 | // Coerce this to correct type: |
119 | // CHECK: %[[THIS_STORE:.*]] = alloca %struct.B* |
120 | // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B* |
121 | // CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %{{.*}} to %struct.B* |
122 | // CHECK: store %struct.B* %[[COERCE_VAL]], %struct.B** %[[THIS_STORE]], align 4 |
123 | // |
124 | // Store initial this: |
125 | // CHECK: %[[THIS_INIT:.*]] = load %struct.B*, %struct.B** %[[THIS_STORE]] |
126 | // CHECK: store %struct.B* %[[THIS_INIT]], %struct.B** %[[THIS_ADDR]], align 4 |
127 | // |
128 | // Reload and adjust the this parameter: |
129 | // CHECK: %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] |
130 | // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8* |
131 | // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8 |
132 | // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B* |
133 | |
134 | field = 42; |
135 | // CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
136 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS8]], i32 0 |
137 | // CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** |
138 | // CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]] |
139 | // CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1 |
140 | // CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]] |
141 | // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] |
142 | // CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8* |
143 | // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS8]], i32 %[[VBOFFSET]] |
144 | // CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase* |
145 | // CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase, %struct.VBase* %[[VBASE]], i32 0, i32 1 |
146 | // CHECK: store i32 42, i32* %[[FIELD]], align 4 |
147 | // |
148 | // CHECK: ret void |
149 | } |
150 | |
151 | void call_vbase_bar(B *obj) { |
152 | // CHECK-LABEL: define dso_local void @"?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj) |
153 | // CHECK: %[[OBJ:.*]] = load %struct.B |
154 | |
155 | obj->bar(); |
156 | // When calling a vbase's virtual method, one needs to adjust 'this' |
157 | // at the caller site. |
158 | // |
159 | // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* |
160 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0 |
161 | // CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** |
162 | // CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]] |
163 | // CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1 |
164 | // CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]] |
165 | // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] |
166 | // CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] |
167 | // |
168 | // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* |
169 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0 |
170 | // CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** |
171 | // CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]] |
172 | // CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1 |
173 | // CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]] |
174 | // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] |
175 | // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] |
176 | // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)*** |
177 | // CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]] |
178 | // CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2 |
179 | // CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]] |
180 | // |
181 | // CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[VBASE]]) |
182 | // |
183 | // CHECK: ret void |
184 | } |
185 | |
186 | void delete_B(B *obj) { |
187 | // CHECK-LABEL: define dso_local void @"?delete_B@@YAXPAUB@@@Z"(%struct.B* %obj) |
188 | // CHECK: %[[OBJ:.*]] = load %struct.B |
189 | |
190 | delete obj; |
191 | // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* |
192 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0 |
193 | // CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** |
194 | // CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]] |
195 | // CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1 |
196 | // CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]] |
197 | // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] |
198 | // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] |
199 | // CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B* |
200 | // |
201 | // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* |
202 | // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0 |
203 | // CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** |
204 | // CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]] |
205 | // CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1 |
206 | // CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]] |
207 | // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] |
208 | // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] |
209 | // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)*** |
210 | // CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)**, i8* (%struct.B*, i32)*** %[[VFPTR]] |
211 | // CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0 |
212 | // CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFUN]] |
213 | // |
214 | // CHECK: call x86_thiscallcc i8* %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1) |
215 | // CHECK: ret void |
216 | } |
217 | |
218 | void call_complete_dtor() { |
219 | // CHECK-LABEL: define dso_local void @"?call_complete_dtor@@YAXXZ" |
220 | B b; |
221 | // CHECK: call x86_thiscallcc %struct.B* @"??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1) |
222 | // CHECK-NOT: getelementptr |
223 | // CHECK: call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* %[[B]]) |
224 | // CHECK: ret |
225 | } |
226 | |
227 | struct C : B { |
228 | C(); |
229 | // has an implicit vdtor. |
230 | }; |
231 | |
232 | // Used to crash on an assertion. |
233 | C::C() { |
234 | // CHECK-LABEL: define dso_local x86_thiscallcc %struct.C* @"??0C@@QAE@XZ" |
235 | } |
236 | |
237 | namespace multiple_vbases { |
238 | struct A { |
239 | virtual void a(); |
240 | }; |
241 | |
242 | struct B { |
243 | virtual void b(); |
244 | }; |
245 | |
246 | struct C { |
247 | virtual void c(); |
248 | }; |
249 | |
250 | struct D : virtual A, virtual B, virtual C { |
251 | virtual void a(); |
252 | virtual void b(); |
253 | virtual void c(); |
254 | D(); |
255 | }; |
256 | |
257 | D::D() { |
258 | // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.multiple_vbases::D"* @"??0D@multiple_vbases@@QAE@XZ" |
259 | // Just make sure we emit 3 vtordisps after initializing vfptrs. |
260 | // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}} |
261 | // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}} |
262 | // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}} |
263 | // ... |
264 | // CHECK: store i32 %{{.*}}, i32* %{{.*}} |
265 | // CHECK: store i32 %{{.*}}, i32* %{{.*}} |
266 | // CHECK: store i32 %{{.*}}, i32* %{{.*}} |
267 | // CHECK: ret |
268 | } |
269 | } |
270 | |
271 | namespace diamond { |
272 | struct A { |
273 | A(); |
274 | virtual ~A(); |
275 | }; |
276 | |
277 | struct B : virtual A { |
278 | B(); |
279 | ~B(); |
280 | }; |
281 | |
282 | struct C : virtual A { |
283 | C(); |
284 | ~C(); |
285 | int c1, c2, c3; |
286 | }; |
287 | |
288 | struct Z { |
289 | int z; |
290 | }; |
291 | |
292 | struct D : virtual Z, B, C { |
293 | D(); |
294 | ~D(); |
295 | } d; |
296 | |
297 | D::~D() { |
298 | // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}}) |
299 | // Store initial this: |
300 | // CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"* |
301 | // CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4 |
302 | // |
303 | // Reload and adjust the this parameter: |
304 | // CHECK: %[[THIS_RELOAD:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_ADDR]] |
305 | // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS_RELOAD]] to i8* |
306 | // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -24 |
307 | // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.diamond::D"* |
308 | // |
309 | // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8* |
310 | // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[D_i8]], i32 4 |
311 | // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"* |
312 | // CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8* |
313 | // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 16 |
314 | // FIXME: We might consider changing the dtor this parameter type to i8*. |
315 | // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"* |
316 | // CHECK: call x86_thiscallcc void @"??1C@diamond@@UAE@XZ"(%"struct.diamond::C"* %[[ARG]]) |
317 | |
318 | // CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"* |
319 | // CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8* |
320 | // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[B_i8]], i32 4 |
321 | // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"* |
322 | // CHECK: call x86_thiscallcc void @"??1B@diamond@@UAE@XZ"(%"struct.diamond::B"* %[[ARG]]) |
323 | // CHECK: ret void |
324 | } |
325 | |
326 | } |
327 | |
328 | namespace test2 { |
329 | struct A { A(); }; |
330 | struct B : virtual A { B() {} }; |
331 | struct C : B, A { C() {} }; |
332 | |
333 | // PR18435: Order mattered here. We were generating code for the delegating |
334 | // call to B() from C(). |
335 | void callC() { C x; } |
336 | |
337 | // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::C"* @"??0C@test2@@QAE@XZ" |
338 | // CHECK: (%"struct.test2::C"* returned %this, i32 %is_most_derived) |
339 | // CHECK: br i1 |
340 | // Virtual bases |
341 | // CHECK: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}}) |
342 | // CHECK: br label |
343 | // Non-virtual bases |
344 | // CHECK: call x86_thiscallcc %"struct.test2::B"* @"??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0) |
345 | // CHECK: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}}) |
346 | // CHECK: ret |
347 | |
348 | // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::B"* @"??0B@test2@@QAE@XZ" |
349 | // CHECK2: (%"struct.test2::B"* returned %this, i32 %is_most_derived) |
350 | // CHECK2: call x86_thiscallcc %"struct.test2::A"* @"??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}}) |
351 | // CHECK2: ret |
352 | |
353 | } |
354 | |
355 | namespace test3 { |
356 | // PR19104: A non-virtual call of a virtual method doesn't use vftable thunks, |
357 | // so requires only static adjustment which is different to the one used |
358 | // for virtual calls. |
359 | struct A { |
360 | virtual void foo(); |
361 | }; |
362 | |
363 | struct B : virtual A { |
364 | virtual void bar(); |
365 | }; |
366 | |
367 | struct C : virtual A { |
368 | virtual void foo(); |
369 | }; |
370 | |
371 | struct D : B, C { |
372 | virtual void bar(); |
373 | int field; // Laid out between C and A subobjects in D. |
374 | }; |
375 | |
376 | void D::bar() { |
377 | // CHECK-LABEL: define dso_local x86_thiscallcc void @"?bar@D@test3@@UAEXXZ"(%"struct.test3::D"* %this) |
378 | |
379 | C::foo(); |
380 | // Shouldn't need any vbtable lookups. All we have to do is adjust to C*, |
381 | // then compensate for the adjustment performed in the C::foo() prologue. |
382 | // CHECK-NOT: load i8*, i8** |
383 | // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test3::D"* %{{.*}} to i8* |
384 | // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 8 |
385 | // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"* |
386 | // CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8* |
387 | // CHECK: %[[ARG:.*]] = getelementptr i8, i8* %[[C_i8]], i32 4 |
388 | // CHECK: call x86_thiscallcc void @"?foo@C@test3@@UAEXXZ"(i8* %[[ARG]]) |
389 | // CHECK: ret |
390 | } |
391 | } |
392 | |
393 | namespace test4{ |
394 | // PR19172: We used to merge method vftable locations wrong. |
395 | |
396 | struct A { |
397 | virtual ~A() {} |
398 | }; |
399 | |
400 | struct B { |
401 | virtual ~B() {} |
402 | }; |
403 | |
404 | struct C : virtual A, B { |
405 | virtual ~C(); |
406 | }; |
407 | |
408 | void foo(void*); |
409 | |
410 | C::~C() { |
411 | // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this) |
412 | |
413 | // In this case "this" points to the most derived class, so no GEPs needed. |
414 | // CHECK-NOT: getelementptr |
415 | // CHECK-NOT: bitcast |
416 | // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)*** |
417 | // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] |
418 | |
419 | foo(this); |
420 | // CHECK: ret |
421 | } |
422 | |
423 | void destroy(C *obj) { |
424 | // CHECK-LABEL: define dso_local void @"?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj) |
425 | |
426 | delete obj; |
427 | // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to i8* (%"struct.test4::C"*, i32)*** |
428 | // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::C"*, i32)**, i8* (%"struct.test4::C"*, i32)*** %[[VPTR]] |
429 | // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::C"*, i32)*, i8* (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0 |
430 | // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::C"*, i32)*, i8* (%"struct.test4::C"*, i32)** %[[VFTENTRY]] |
431 | // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1) |
432 | // CHECK: ret |
433 | } |
434 | |
435 | struct D { |
436 | virtual void d(); |
437 | }; |
438 | |
439 | // The first non-virtual base doesn't have a vdtor, |
440 | // but "this adjustment" is not needed. |
441 | struct E : D, B, virtual A { |
442 | virtual ~E(); |
443 | }; |
444 | |
445 | E::~E() { |
446 | // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1E@test4@@UAE@XZ"(%"struct.test4::E"* %this) |
447 | |
448 | // In this case "this" points to the most derived class, so no GEPs needed. |
449 | // CHECK-NOT: getelementptr |
450 | // CHECK-NOT: bitcast |
451 | // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)*** |
452 | // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] |
453 | foo(this); |
454 | } |
455 | |
456 | void destroy(E *obj) { |
457 | // CHECK-LABEL: define dso_local void @"?destroy@test4@@YAXPAUE@1@@Z"(%"struct.test4::E"* %obj) |
458 | |
459 | // CHECK-NOT: getelementptr |
460 | // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8* |
461 | // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4 |
462 | // FIXME: in fact, the call should take i8* and the bitcast is redundant. |
463 | // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"* |
464 | // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8* |
465 | // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4 |
466 | // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (%"struct.test4::E"*, i32)*** |
467 | // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::E"*, i32)**, i8* (%"struct.test4::E"*, i32)*** %[[VPTR]] |
468 | // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::E"*, i32)*, i8* (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0 |
469 | // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::E"*, i32)*, i8* (%"struct.test4::E"*, i32)** %[[VFTENTRY]] |
470 | // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1) |
471 | delete obj; |
472 | } |
473 | |
474 | } |
475 | |
476 | namespace test5 { |
477 | // PR25370: Don't zero-initialize vbptrs in virtual bases. |
478 | struct A { |
479 | virtual void f(); |
480 | }; |
481 | |
482 | struct B : virtual A { |
483 | int Field; |
484 | }; |
485 | |
486 | struct C : B { |
487 | C(); |
488 | }; |
489 | |
490 | C::C() : B() {} |
491 | // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.test5::C"* @"??0C@test5@@QAE@XZ"( |
492 | // CHECK: %[[THIS:.*]] = load %"struct.test5::C"*, %"struct.test5::C"** |
493 | // CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] |
494 | |
495 | // CHECK: %[[SKIP_VBASES]] |
496 | // CHECK: %[[B:.*]] = bitcast %"struct.test5::C"* %[[THIS]] to %"struct.test5::B"* |
497 | // CHECK: %[[B_i8:.*]] = bitcast %"struct.test5::B"* %[[B]] to i8* |
498 | // CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[B_i8]], i32 4 |
499 | // CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false) |
500 | } |
501 | |
502 | namespace pr27621 { |
503 | // Devirtualization through a static_cast used to make us compute the 'this' |
504 | // adjustment for B::g instead of C::g. When we directly call C::g, 'this' is a |
505 | // B*, and the prologue of C::g will adjust it to a C*. |
506 | struct A { virtual void f(); }; |
507 | struct B { virtual void g(); }; |
508 | struct C final : A, B { |
509 | virtual void h(); |
510 | void g() override; |
511 | }; |
512 | void callit(C *p) { |
513 | static_cast<B*>(p)->g(); |
514 | } |
515 | // CHECK-LABEL: define dso_local void @"?callit@pr27621@@YAXPAUC@1@@Z"(%"struct.pr27621::C"* %{{.*}}) |
516 | // CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 4 |
517 | // CHECK: call x86_thiscallcc void @"?g@C@pr27621@@UAEXXZ"(i8* %[[B_i8]]) |
518 | } |
519 | |
520 | namespace test6 { |
521 | class A {}; |
522 | class B : virtual A {}; |
523 | class C : virtual B { |
524 | virtual void m_fn1(); |
525 | float field; |
526 | }; |
527 | class D : C { |
528 | D(); |
529 | }; |
530 | D::D() : C() {} |
531 | // CHECK-LABEL: define dso_local x86_thiscallcc %"class.test6::D"* @"??0D@test6@@AAE@XZ"( |
532 | // CHECK: %[[THIS:.*]] = load %"class.test6::D"*, %"class.test6::D"** |
533 | // CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] |
534 | |
535 | // CHECK: %[[SKIP_VBASES]] |
536 | // CHECK: %[[C:.*]] = bitcast %"class.test6::D"* %[[THIS]] to %"class.test6::C"* |
537 | // CHECK: %[[C_i8:.*]] = bitcast %"class.test6::C"* %[[C]] to i8* |
538 | // CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8 |
539 | // CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false) |
540 | } |
541 | |
542 | namespace pr36921 { |
543 | struct A { |
544 | virtual ~A() {} |
545 | }; |
546 | struct B { |
547 | virtual ~B() {} |
548 | }; |
549 | struct C : virtual B {}; |
550 | struct D : virtual A, C {}; |
551 | D d; |
552 | // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GD@pr36921@@UAEPAXI@Z"( |
553 | // CHECK: %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"** |
554 | // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8* |
555 | // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4 |
556 | // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"* |
557 | } |
558 | |