@@ -105,3 +105,293 @@ extern "C" void *test_return_address(void) {
105
105
// LLVM-LABEL: @test_return_address
106
106
// LLVM: {{%.*}} = call ptr @llvm.returnaddress(i32 1)
107
107
}
108
+
109
+
110
+ // Following block of tests are for __builtin_launder
111
+ // FIXME: Once we fully __builtin_launder by allowing -fstrict-vtable-pointers,
112
+ // we should move following block of tests to a separate file.
113
+ namespace launder_test {
114
+ // ===----------------------------------------------------------------------===//
115
+ // Positive Cases
116
+ // ===----------------------------------------------------------------------===//
117
+
118
+ struct TestVirtualFn {
119
+ virtual void foo () {}
120
+ };
121
+
122
+ // CIR-LABEL: test_builtin_launder_virtual_fn
123
+ // LLVM: define{{.*}} void @test_builtin_launder_virtual_fn(ptr [[P:%.*]])
124
+ extern " C" void test_builtin_launder_virtual_fn (TestVirtualFn *p) {
125
+ // CIR: cir.return
126
+
127
+ // LLVM: store ptr [[P]], ptr [[P_ADDR:%.*]], align 8
128
+ // LLVM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
129
+ // LLVM-NEXT: store ptr [[TMP0]], ptr {{%.*}}
130
+ // LLVM-NEXT: ret void
131
+ TestVirtualFn *d = __builtin_launder (p);
132
+ }
133
+
134
+ struct TestPolyBase : TestVirtualFn {
135
+ };
136
+
137
+ // CIR-LABEL: test_builtin_launder_poly_base
138
+ // LLVM: define{{.*}} void @test_builtin_launder_poly_base(ptr [[P:%.*]])
139
+ extern " C" void test_builtin_launder_poly_base (TestPolyBase *p) {
140
+ // CIR: cir.return
141
+
142
+ // LLVM: store ptr [[P]], ptr [[P_ADDR:%.*]], align 8
143
+ // LLVM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
144
+ // LLVM-NEXT: store ptr [[TMP0]], ptr {{%.*}}
145
+ // LLVM-NEXT: ret void
146
+ TestPolyBase *d = __builtin_launder (p);
147
+ }
148
+
149
+ struct TestBase {};
150
+ struct TestVirtualBase : virtual TestBase {};
151
+
152
+ // CIR-LABEL: test_builtin_launder_virtual_base
153
+ // LLVM: define{{.*}} void @test_builtin_launder_virtual_base(ptr [[P:%.*]])
154
+ extern " C" void test_builtin_launder_virtual_base (TestVirtualBase *p) {
155
+ TestVirtualBase *d = __builtin_launder (p);
156
+
157
+ // CIR: cir.return
158
+
159
+ // LLVM: store ptr [[P]], ptr [[P_ADDR:%.*]], align 8
160
+ // LLVM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
161
+ // LLVM-NEXT: store ptr [[TMP0]], ptr {{%.*}}
162
+ // LLVM-NEXT: ret void
163
+ }
164
+
165
+ // ===----------------------------------------------------------------------===//
166
+ // Negative Cases
167
+ // ===----------------------------------------------------------------------===//
168
+
169
+ // CIR-LABEL: test_builtin_launder_ommitted_one
170
+ // LLVM: define{{.*}} void @test_builtin_launder_ommitted_one(ptr [[P:%.*]])
171
+ extern " C" void test_builtin_launder_ommitted_one (int *p) {
172
+ int *d = __builtin_launder (p);
173
+
174
+ // CIR: cir.return
175
+
176
+ // LLVM-NEXT: [[P_ADDR:%.*]] = alloca ptr, i64 1, align 8
177
+ // LLVM-NEXT: [[D:%.*]] = alloca ptr, i64 1, align 8
178
+ // LLVM: store ptr [[P]], ptr [[P_ADDR:%.*]], align 8
179
+ // LLVM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
180
+ // LLVM-NEXT: store ptr [[TMP0]], ptr [[D]]
181
+ // LLVM-NEXT: ret void
182
+ }
183
+
184
+ struct TestNoInvariant {
185
+ int x;
186
+ };
187
+
188
+ // CIR-LABEL: test_builtin_launder_ommitted_two
189
+ // LLVM: define{{.*}} void @test_builtin_launder_ommitted_two(ptr [[P:%.*]])
190
+ extern " C" void test_builtin_launder_ommitted_two (TestNoInvariant *p) {
191
+ TestNoInvariant *d = __builtin_launder (p);
192
+ // CIR: cir.return
193
+
194
+ // LLVM-NOT: llvm.launder.invariant.group
195
+ // LLVM-NEXT: [[P_ADDR:%.*]] = alloca ptr, i64 1, align 8
196
+ // LLVM-NEXT: [[D:%.*]] = alloca ptr, i64 1, align 8
197
+ // LLVM: store ptr [[P]], ptr [[P_ADDR:%.*]], align 8
198
+ // LLVM-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
199
+ // LLVM-NEXT: store ptr [[TMP0]], ptr [[D]]
200
+ // LLVM-NEXT: ret void
201
+ }
202
+
203
+ struct TestVirtualMember {
204
+ TestVirtualFn member;
205
+ };
206
+
207
+ // CIR-LABEL: test_builtin_launder_virtual_member
208
+ // LLVM: define{{.*}} void @test_builtin_launder_virtual_member
209
+ extern " C" void test_builtin_launder_virtual_member (TestVirtualMember *p) {
210
+ // CIR: cir.return
211
+
212
+ // LLVM-NOT: llvm.launder.invariant.group
213
+ // LLVM: ret void
214
+ TestVirtualMember *d = __builtin_launder (p);
215
+ }
216
+
217
+ struct TestVirtualMemberDepth2 {
218
+ TestVirtualMember member;
219
+ };
220
+
221
+ // CIR-LABEL: test_builtin_launder_virtual_member_depth_2
222
+ // LLVM: define{{.*}} void @test_builtin_launder_virtual_member_depth_2
223
+ extern " C" void test_builtin_launder_virtual_member_depth_2 (TestVirtualMemberDepth2 *p) {
224
+ // CIR: cir.return
225
+
226
+ // LLVM-NOT: llvm.launder.invariant.group
227
+ // LLVM: ret void
228
+ TestVirtualMemberDepth2 *d = __builtin_launder (p);
229
+ }
230
+
231
+ struct TestVirtualReferenceMember {
232
+ TestVirtualFn &member;
233
+ };
234
+
235
+ // CIR-LABEL: test_builtin_launder_virtual_reference_member
236
+ // LLVM: define{{.*}} void @test_builtin_launder_virtual_reference_member
237
+ extern " C" void test_builtin_launder_virtual_reference_member (TestVirtualReferenceMember *p) {
238
+ // CIR: cir.return
239
+
240
+ // LLVM-NOT: llvm.launder.invariant.group
241
+ // LLVM: ret void
242
+ TestVirtualReferenceMember *d = __builtin_launder (p);
243
+ }
244
+
245
+ struct TestRecursiveMember {
246
+ TestRecursiveMember () : member(*this ) {}
247
+ TestRecursiveMember &member;
248
+ };
249
+
250
+ // CIR-LABEL: test_builtin_launder_recursive_member
251
+ // LLVM: define{{.*}} void @test_builtin_launder_recursive_member
252
+ extern " C" void test_builtin_launder_recursive_member (TestRecursiveMember *p) {
253
+ // CIR: cir.return
254
+
255
+ // LLVM-NOT: llvm.launder.invariant.group
256
+ // LLVM: ret void
257
+ TestRecursiveMember *d = __builtin_launder (p);
258
+ }
259
+
260
+ struct TestVirtualRecursiveMember {
261
+ TestVirtualRecursiveMember () : member(*this ) {}
262
+ TestVirtualRecursiveMember &member;
263
+ virtual void foo ();
264
+ };
265
+
266
+ // CIR-LABEL: test_builtin_launder_virtual_recursive_member
267
+ // LLVM: define{{.*}} void @test_builtin_launder_virtual_recursive_member
268
+ extern " C" void test_builtin_launder_virtual_recursive_member (TestVirtualRecursiveMember *p) {
269
+ // CIR: cir.return
270
+
271
+ // LLVM-NOT: llvm.launder.invariant.group
272
+ // LLVM: ret void
273
+ TestVirtualRecursiveMember *d = __builtin_launder (p);
274
+ }
275
+
276
+ // CIR-LABEL: test_builtin_launder_array
277
+ // LLVM: define{{.*}} void @test_builtin_launder_array
278
+ extern " C" void test_builtin_launder_array (TestVirtualFn (&Arr)[5]) {
279
+ // CIR: cir.return
280
+
281
+ // LLVM-NOT: llvm.launder.invariant.group
282
+ // LLVM: ret void
283
+ TestVirtualFn *d = __builtin_launder (Arr);
284
+ }
285
+
286
+ // CIR-LABEL: test_builtin_launder_array_nested
287
+ // LLVM: define{{.*}} void @test_builtin_launder_array_nested
288
+ extern " C" void test_builtin_launder_array_nested (TestVirtualFn (&Arr)[5][2]) {
289
+ // CIR: cir.return
290
+
291
+ // LLVM-NOT: llvm.launder.invariant.group
292
+ // LLVM: ret void
293
+ using RetTy = TestVirtualFn (*)[2 ];
294
+ RetTy d = __builtin_launder (Arr);
295
+ }
296
+
297
+ // CIR-LABEL: test_builtin_launder_array_no_invariant
298
+ // LLVM: define{{.*}} void @test_builtin_launder_array_no_invariant
299
+ extern " C" void test_builtin_launder_array_no_invariant (TestNoInvariant (&Arr)[5]) {
300
+ // CIR: cir.return
301
+
302
+ // LLVM-NOT: llvm.launder.invariant.group
303
+ // LLVM: ret void
304
+ TestNoInvariant *d = __builtin_launder (Arr);
305
+ }
306
+
307
+ // CIR-LABEL: test_builtin_launder_array_nested_no_invariant
308
+ // LLVM: define{{.*}} void @test_builtin_launder_array_nested_no_invariant
309
+ extern " C" void test_builtin_launder_array_nested_no_invariant (TestNoInvariant (&Arr)[5][2]) {
310
+ // CIR: cir.return
311
+
312
+ // LLVM-NOT: llvm.launder.invariant.group
313
+ // LLVM: ret void
314
+ using RetTy = TestNoInvariant (*)[2 ];
315
+ RetTy d = __builtin_launder (Arr);
316
+ }
317
+
318
+ template <class Member >
319
+ struct WithMember {
320
+ Member mem;
321
+ };
322
+
323
+ template struct WithMember <TestVirtualFn[5 ]>;
324
+
325
+ // CIR-LABEL: test_builtin_launder_member_array
326
+ // LLVM: define{{.*}} void @test_builtin_launder_member_array
327
+ extern " C" void test_builtin_launder_member_array (WithMember<TestVirtualFn[5 ]> *p) {
328
+ // CIR: cir.return
329
+
330
+ // LLVM-NOT: llvm.launder.invariant.group
331
+ // LLVM: ret void
332
+ auto *d = __builtin_launder (p);
333
+ }
334
+
335
+ template struct WithMember <TestVirtualFn[5 ][2 ]>;
336
+
337
+ // CIR-LABEL: test_builtin_launder_member_array_nested
338
+ // LLVM: define{{.*}} void @test_builtin_launder_member_array_nested
339
+ extern " C" void test_builtin_launder_member_array_nested (WithMember<TestVirtualFn[5 ][2 ]> *p) {
340
+ // CIR: cir.return
341
+
342
+ // LLVM-NOT: llvm.launder.invariant.group
343
+ // LLVM: ret void
344
+ auto *d = __builtin_launder (p);
345
+ }
346
+
347
+ template struct WithMember <TestNoInvariant[5 ]>;
348
+
349
+ // CIR-LABEL: test_builtin_launder_member_array_no_invariant
350
+ // LLVM: define{{.*}} void @test_builtin_launder_member_array_no_invariant
351
+ extern " C" void test_builtin_launder_member_array_no_invariant (WithMember<TestNoInvariant[5 ]> *p) {
352
+ // CIR: cir.return
353
+
354
+ // LLVM-NOT: llvm.launder.invariant.group
355
+ // LLVM: ret void
356
+ auto *d = __builtin_launder (p);
357
+ }
358
+
359
+ template struct WithMember <TestNoInvariant[5 ][2 ]>;
360
+
361
+ // CIR-LABEL: test_builtin_launder_member_array_nested_no_invariant
362
+ // LLVM: define{{.*}} void @test_builtin_launder_member_array_nested_no_invariant
363
+ extern " C" void test_builtin_launder_member_array_nested_no_invariant (WithMember<TestNoInvariant[5 ][2 ]> *p) {
364
+ // CIR: cir.return
365
+
366
+ // LLVM-NOT: llvm.launder.invariant.group
367
+ // LLVM: ret void
368
+ auto *d = __builtin_launder (p);
369
+ }
370
+
371
+ template <class T >
372
+ struct WithBase : T {};
373
+
374
+ template struct WithBase <TestNoInvariant>;
375
+
376
+ // CIR-LABEL: test_builtin_launder_base_no_invariant
377
+ // LLVM: define{{.*}} void @test_builtin_launder_base_no_invariant
378
+ extern " C" void test_builtin_launder_base_no_invariant (WithBase<TestNoInvariant> *p) {
379
+ // CIR: cir.return
380
+
381
+ // LLVM-NOT: llvm.launder.invariant.group
382
+ // LLVM: ret void
383
+ auto *d = __builtin_launder (p);
384
+ }
385
+
386
+ template struct WithBase <TestVirtualFn>;
387
+
388
+ // CIR-LABEL: test_builtin_launder_base
389
+ // LLVM: define{{.*}} void @test_builtin_launder_base
390
+ extern " C" void test_builtin_launder_base (WithBase<TestVirtualFn> *p) {
391
+ // CIR: cir.return
392
+
393
+ // LLVM-NOT: llvm.launder.invariant.group
394
+ // LLVM: ret void
395
+ auto *d = __builtin_launder (p);
396
+ }
397
+ }
0 commit comments