xref: /llvm-project/clang/test/CodeGenCXX/arm.cpp (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
1 // RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -std=gnu++98 -o - -fexceptions | FileCheck -check-prefix=CHECK -check-prefix=CHECK98 %s
2 // RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -std=gnu++11 -o - -fexceptions | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s
3 
4 // CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4
5 // CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0
6 // CHECK: @_ZZN5test84testEvE1x = internal global [[TEST8A:.*]] zeroinitializer, align 1
7 // CHECK: @_ZGVZN5test84testEvE1x = internal global i32 0
8 
9 typedef typeof(sizeof(int)) size_t;
10 
11 class foo {
12 public:
13     foo();
14     virtual ~foo();
15 };
16 
17 class bar : public foo {
18 public:
19 	bar();
20 };
21 
22 // The global dtor needs the right calling conv with -fno-use-cxa-atexit
23 bar baz;
24 
25 // PR9593
26 // Make sure atexit(3) is used for global dtors.
27 
28 // CHECK:      call ptr @_ZN3barC1Ev(
29 // CHECK-NEXT: call i32 @atexit(ptr @__dtor_baz)
30 
31 // CHECK-NOT: @_GLOBAL__D_a()
32 // CHECK-LABEL: define internal void @__dtor_baz()
33 // CHECK: call ptr @_ZN3barD1Ev(ptr @baz)
34 
35 // Destructors and constructors must return this.
36 namespace test1 {
37   void foo();
38 
39   struct A {
Atest1::A40     A(int i) { foo(); }
~Atest1::A41     ~A() { foo(); }
bartest1::A42     void bar() { foo(); }
43   };
44 
45   // CHECK-LABEL: define{{.*}} void @_ZN5test14testEv()
test()46   void test() {
47     // CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1
48     // CHECK: call ptr @_ZN5test11AC1Ei(ptr {{[^,]*}} [[AV]], i32 10)
49     // CHECK: invoke void @_ZN5test11A3barEv(ptr {{[^,]*}} [[AV]])
50     // CHECK: call ptr @_ZN5test11AD1Ev(ptr {{[^,]*}} [[AV]])
51     // CHECK: ret void
52     A a = 10;
53     a.bar();
54   }
55 
56   // CHECK: define linkonce_odr ptr @_ZN5test11AC1Ei(ptr {{[^,]*}} returned {{[^,]*}} %this, i32 %i) unnamed_addr
57   // CHECK:   [[THIS:%.*]] = alloca ptr, align 4
58   // CHECK:   store ptr {{.*}}, ptr [[THIS]]
59   // CHECK:   [[THIS1:%.*]] = load ptr, ptr [[THIS]]
60   // CHECK:   {{%.*}} = call ptr @_ZN5test11AC2Ei(
61   // CHECK:   ret ptr [[THIS1]]
62 
63   // CHECK: define linkonce_odr ptr @_ZN5test11AD1Ev(ptr {{[^,]*}} returned {{[^,]*}} %this) unnamed_addr
64   // CHECK:   [[THIS:%.*]] = alloca ptr, align 4
65   // CHECK:   store ptr {{.*}}, ptr [[THIS]]
66   // CHECK:   [[THIS1:%.*]] = load ptr, ptr [[THIS]]
67   // CHECK:   {{%.*}} = call ptr @_ZN5test11AD2Ev(
68   // CHECK:   ret ptr [[THIS1]]
69 }
70 
71 // Awkward virtual cases.
72 namespace test2 {
73   void foo();
74 
75   struct A {
76     int x;
77 
78     A(int);
~Atest2::A79     virtual ~A() { foo(); }
80   };
81 
82   struct B {
83     int y;
84     int z;
85 
86     B(int);
~Btest2::B87     virtual ~B() { foo(); }
88   };
89 
90   struct C : A, virtual B {
91     int q;
92 
Ctest2::C93     C(int i) : A(i), B(i) { foo(); }
~Ctest2::C94     ~C() { foo(); }
95   };
96 
test()97   void test() {
98     C c = 10;
99   }
100 
101   // Tests at eof
102 }
103 
104 namespace test3 {
105   struct A {
106     int x;
107     ~A();
108   };
109 
a()110   void a() {
111     // CHECK-LABEL: define{{.*}} void @_ZN5test31aEv()
112     // CHECK: call noalias nonnull ptr @_Znam(i32 48)
113     // CHECK: store i32 4
114     // CHECK: store i32 10
115     A *x = new A[10];
116   }
117 
b(int n)118   void b(int n) {
119     // CHECK-LABEL: define{{.*}} void @_ZN5test31bEi(
120     // CHECK: [[N:%.*]] = load i32, ptr
121     // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
122     // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
123     // CHECK: [[OR:%.*]] = or i1
124     // CHECK: [[SZ:%.*]] = select i1 [[OR]]
125     // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])
126     // CHECK: store i32 4
127     // CHECK: store i32 [[N]]
128     A *x = new A[n];
129   }
130 
c()131   void c() {
132     // CHECK-LABEL: define{{.*}} void @_ZN5test31cEv()
133     // CHECK: call noalias nonnull ptr @_Znam(i32 808)
134     // CHECK: store i32 4
135     // CHECK: store i32 200
136     A (*x)[20] = new A[10][20];
137   }
138 
d(int n)139   void d(int n) {
140     // CHECK-LABEL: define{{.*}} void @_ZN5test31dEi(
141     // CHECK: [[N:%.*]] = load i32, ptr
142     // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
143     // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
144     // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
145     // CHECK: [[SZ:%.*]] = select
146     // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])
147     // CHECK: store i32 4
148     // CHECK: store i32 [[NE]]
149     A (*x)[20] = new A[n][20];
150   }
151 
e(A * x)152   void e(A *x) {
153     // CHECK-LABEL: define{{.*}} void @_ZN5test31eEPNS_1AE(
154     // CHECK: icmp eq {{.*}}, null
155     // CHECK: getelementptr {{.*}}, i32 -8
156     // CHECK: getelementptr {{.*}}, i32 4
157     // CHECK: load
158     // CHECK98: invoke {{.*}} @_ZN5test31AD1Ev
159     // CHECK11: call {{.*}} @_ZN5test31AD1Ev
160     // CHECK: call void @_ZdaPv
161     delete [] x;
162   }
163 
f(A (* x)[20])164   void f(A (*x)[20]) {
165     // CHECK-LABEL: define{{.*}} void @_ZN5test31fEPA20_NS_1AE(
166     // CHECK: icmp eq {{.*}}, null
167     // CHECK: getelementptr {{.*}}, i32 -8
168     // CHECK: getelementptr {{.*}}, i32 4
169     // CHECK: load
170     // CHECK98: invoke {{.*}} @_ZN5test31AD1Ev
171     // CHECK11: call {{.*}} @_ZN5test31AD1Ev
172     // CHECK: call void @_ZdaPv
173     delete [] x;
174   }
175 }
176 
177 namespace test4 {
178   struct A {
179     int x;
180     void operator delete[](void *, size_t sz);
181   };
182 
a()183   void a() {
184     // CHECK-LABEL: define{{.*}} void @_ZN5test41aEv()
185     // CHECK: call noalias nonnull ptr @_Znam(i32 48)
186     // CHECK: store i32 4
187     // CHECK: store i32 10
188     A *x = new A[10];
189   }
190 
b(int n)191   void b(int n) {
192     // CHECK-LABEL: define{{.*}} void @_ZN5test41bEi(
193     // CHECK: [[N:%.*]] = load i32, ptr
194     // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
195     // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
196     // CHECK: [[SZ:%.*]] = select
197     // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])
198     // CHECK: store i32 4
199     // CHECK: store i32 [[N]]
200     A *x = new A[n];
201   }
202 
c()203   void c() {
204     // CHECK-LABEL: define{{.*}} void @_ZN5test41cEv()
205     // CHECK: call noalias nonnull ptr @_Znam(i32 808)
206     // CHECK: store i32 4
207     // CHECK: store i32 200
208     A (*x)[20] = new A[10][20];
209   }
210 
d(int n)211   void d(int n) {
212     // CHECK-LABEL: define{{.*}} void @_ZN5test41dEi(
213     // CHECK: [[N:%.*]] = load i32, ptr
214     // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
215     // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
216     // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
217     // CHECK: [[SZ:%.*]] = select
218     // CHECK: call noalias nonnull ptr @_Znam(i32 [[SZ]])
219     // CHECK: store i32 4
220     // CHECK: store i32 [[NE]]
221     A (*x)[20] = new A[n][20];
222   }
223 
e(A * x)224   void e(A *x) {
225     // CHECK-LABEL: define{{.*}} void @_ZN5test41eEPNS_1AE(
226     // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i32 -8
227     // CHECK: getelementptr inbounds {{.*}}, i32 4
228     // CHECK: [[T0:%.*]] = load i32, ptr
229     // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
230     // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
231     // CHECK: call void @_ZN5test41AdaEPvm(ptr [[ALLOC]], i32 [[T2]])
232     delete [] x;
233   }
234 
f(A (* x)[20])235   void f(A (*x)[20]) {
236     // CHECK-LABEL: define{{.*}} void @_ZN5test41fEPA20_NS_1AE(
237     // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i32 -8
238     // CHECK: getelementptr inbounds {{.*}}, i32 4
239     // CHECK: [[T0:%.*]] = load i32, ptr
240     // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
241     // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
242     // CHECK: call void @_ZN5test41AdaEPvm(ptr [[ALLOC]], i32 [[T2]])
243     delete [] x;
244   }
245 }
246 
247 namespace test5 {
248   struct A {
249     ~A();
250   };
251 
252   // CHECK-LABEL: define{{.*}} void @_ZN5test54testEPNS_1AE
test(A * a)253   void test(A *a) {
254     // CHECK:      [[PTR:%.*]] = alloca ptr, align 4
255     // CHECK-NEXT: store ptr {{.*}}, ptr [[PTR]], align 4
256     // CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr [[PTR]], align 4
257     // CHECK-NEXT: call ptr @_ZN5test51AD1Ev(ptr {{[^,]*}} [[TMP]])
258     // CHECK-NEXT: ret void
259     a->~A();
260   }
261 }
262 
263 namespace test6 {
264   struct A {
265     virtual ~A();
266   };
267 
268   // CHECK-LABEL: define{{.*}} void @_ZN5test64testEPNS_1AE
test(A * a)269   void test(A *a) {
270     // CHECK:      [[AVAR:%.*]] = alloca ptr, align 4
271     // CHECK-NEXT: store ptr {{.*}}, ptr [[AVAR]], align 4
272     // CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[AVAR]], align 4
273     // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[V]], null
274     // CHECK-NEXT: br i1 [[ISNULL]]
275     // CHECK: [[T1:%.*]] = load ptr, ptr [[V]]
276     // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64 1
277     // CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]
278     // CHECK-NEXT: call void [[T3]](ptr {{[^,]*}} [[V]])
279     // CHECK-NEXT: br label
280     // CHECK:      ret void
281     delete a;
282   }
283 }
284 
285 namespace test7 {
286   int foo();
287 
288   // Static and guard tested at top of file
289 
290   // CHECK-LABEL: define{{.*}} void @_ZN5test74testEv() {{.*}} personality ptr @__gxx_personality_v0
test()291   void test() {
292     // CHECK:      [[T0:%.*]] = load atomic i8, ptr @_ZGVZN5test74testEvE1x acquire, align 4
293     // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1
294     // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0
295     // CHECK-NEXT: br i1 [[T2]]
296     //   -> fallthrough, end
297     // CHECK:      [[T3:%.*]] = call i32 @__cxa_guard_acquire(ptr @_ZGVZN5test74testEvE1x)
298     // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
299     // CHECK-NEXT: br i1 [[T4]]
300     //   -> fallthrough, end
301     // CHECK:      [[INIT:%.*]] = invoke i32 @_ZN5test73fooEv()
302     // CHECK:      store i32 [[INIT]], ptr @_ZZN5test74testEvE1x, align 4
303     // CHECK-NEXT: call void @__cxa_guard_release(ptr @_ZGVZN5test74testEvE1x)
304     // CHECK-NEXT: br label
305     //   -> end
306     // end:
307     // CHECK:      ret void
308     static int x = foo();
309 
310     // CHECK:      landingpad { ptr, i32 }
311     // CHECK-NEXT:   cleanup
312     // CHECK:      call void @__cxa_guard_abort(ptr @_ZGVZN5test74testEvE1x)
313     // CHECK:      resume { ptr, i32 }
314   }
315 }
316 
317 namespace test8 {
318   struct A {
319     A();
320     ~A();
321   };
322 
323   // Static and guard tested at top of file
324 
325   // CHECK-LABEL: define{{.*}} void @_ZN5test84testEv() {{.*}} personality ptr @__gxx_personality_v0
test()326   void test() {
327     // CHECK:      [[T0:%.*]] = load atomic i8, ptr @_ZGVZN5test84testEvE1x acquire, align 4
328     // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1
329     // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0
330     // CHECK-NEXT: br i1 [[T2]]
331     //   -> fallthrough, end
332     // CHECK:      [[T3:%.*]] = call i32 @__cxa_guard_acquire(ptr @_ZGVZN5test84testEvE1x)
333     // CHECK-NEXT: [[T4:%.*]] = icmp ne i32 [[T3]], 0
334     // CHECK-NEXT: br i1 [[T4]]
335     //   -> fallthrough, end
336     // CHECK:      [[INIT:%.*]] = invoke ptr @_ZN5test81AC1Ev(ptr {{[^,]*}} @_ZZN5test84testEvE1x)
337 
338     // FIXME: Here we register a global destructor that
339     // unconditionally calls the destructor.  That's what we've always
340     // done for -fno-use-cxa-atexit here, but that's really not
341     // semantically correct at all.
342 
343     // CHECK:      call void @__cxa_guard_release(ptr @_ZGVZN5test84testEvE1x)
344     // CHECK-NEXT: br label
345     //   -> end
346     // end:
347     // CHECK:      ret void
348     static A x;
349 
350     // CHECK:      landingpad { ptr, i32 }
351     // CHECK-NEXT:   cleanup
352     // CHECK:      call void @__cxa_guard_abort(ptr @_ZGVZN5test84testEvE1x)
353     // CHECK:      resume { ptr, i32 }
354   }
355 }
356 
357 // Use a larger-than-mandated array cookie when allocating an
358 // array whose type is overaligned.
359 namespace test9 {
360   class __attribute__((aligned(16))) A {
361     float data[4];
362   public:
363     A();
364     ~A();
365   };
366 
testNew(unsigned n)367   A *testNew(unsigned n) {
368     return new A[n];
369   }
370 // CHECK:    define{{.*}} ptr @_ZN5test97testNewEj(i32
371 // CHECK:      [[N_VAR:%.*]] = alloca i32, align 4
372 // CHECK:      [[N:%.*]] = load i32, ptr [[N_VAR]], align 4
373 // CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 16)
374 // CHECK-NEXT: [[O0:%.*]] = extractvalue { i32, i1 } [[T0]], 1
375 // CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 0
376 // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 16)
377 // CHECK-NEXT: [[O1:%.*]] = extractvalue { i32, i1 } [[T2]], 1
378 // CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[O0]], [[O1]]
379 // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
380 // CHECK-NEXT: [[T4:%.*]] = select i1 [[OVERFLOW]], i32 -1, i32 [[T3]]
381 // CHECK-NEXT: [[ALLOC:%.*]] = call noalias nonnull ptr @_Znam(i32 [[T4]])
382 // CHECK-NEXT: store i32 16, ptr [[ALLOC]]
383 // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32, ptr [[ALLOC]], i32 1
384 // CHECK-NEXT: store i32 [[N]], ptr [[T1]]
385 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[ALLOC]], i32 16
386 //   Array allocation follows.
387 
testDelete(A * array)388   void testDelete(A *array) {
389     delete[] array;
390   }
391 // CHECK-LABEL:    define{{.*}} void @_ZN5test910testDeleteEPNS_1AE(
392 // CHECK:      [[BEGIN:%.*]] = load ptr, ptr
393 // CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[BEGIN]], null
394 // CHECK-NEXT: br i1 [[T0]],
395 // CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[BEGIN]], i32 -16
396 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[ALLOC]], i32 4
397 // CHECK-NEXT: [[N:%.*]] = load i32, ptr [[T0]]
398 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[TEST9:%.*]], ptr [[BEGIN]], i32 [[N]]
399 // CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[BEGIN]], [[END]]
400 // CHECK-NEXT: br i1 [[T0]],
401 //   Array deallocation follows.
402 }
403 
404   // CHECK: define linkonce_odr ptr @_ZTv0_n12_N5test21CD1Ev(
405   // CHECK:   call ptr @_ZN5test21CD1Ev(
406   // CHECK:   ret ptr undef
407 
408   // CHECK-LABEL: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
409   // CHECK:   call void @_ZN5test21CD0Ev(
410   // CHECK:   ret void
411