blob: c48c66316d7b8eb26270f467bbb2b83d2f955dd1 [file] [log] [blame]
Akira Hatanaka7275da02018-02-28 07:15:55 +00001// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck %s
2
3typedef void (^BlockTy)(void);
4
5typedef struct {
6 int a[4];
7} Trivial;
8
9typedef struct {
10 Trivial f0;
11 id f1;
12} Strong;
13
14typedef struct {
15 int i;
16 id f1;
17} StrongSmall;
18
19typedef struct {
20 Strong f0;
21 id f1;
22 double d;
23} StrongOuter;
24
25typedef struct {
26 int f0;
27 volatile id f1;
28} StrongVolatile;
29
30typedef struct {
31 BlockTy f0;
32} StrongBlock;
33
34typedef struct {
35 int i;
36 id f0[2][2];
37} IDArray;
38
39typedef struct {
40 double d;
41 Strong f0[2][2];
42} StructArray;
43
44typedef struct {
45 id f0;
46 int i : 9;
47} Bitfield0;
48
49typedef struct {
50 char c;
51 int i0 : 2;
52 int i1 : 4;
53 id f0;
54 int i2 : 31;
55 int i3 : 1;
56 id f1;
57 int : 0;
58 int a[3];
59 id f2;
60 double d;
61 int i4 : 1;
62 volatile int i5 : 2;
63 volatile char i6;
64} Bitfield1;
65
66StrongSmall getStrongSmall(void);
67StrongOuter getStrongOuter(void);
68void calleeStrongSmall(StrongSmall);
69void func(Strong *);
70
71// CHECK: %[[STRUCT_BITFIELD1:.*]] = type { i8, i8, i8*, i32, i8*, [3 x i32], i8*, double, i8, i8 }
72
73// CHECK: define void @test_constructor_destructor_StrongOuter()
74// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER:.*]], align 8
75// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
76// CHECK: call void @__default_constructor_8_s16_s24(i8** %[[V0]])
77// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
78// CHECK: call void @__destructor_8_s16_s24(i8** %[[V1]])
79// CHECK: ret void
80
81// CHECK: define linkonce_odr hidden void @__default_constructor_8_s16_s24(i8** %[[DST:.*]])
82// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
83// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
84// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
85// CHECK: call void @__default_constructor_8_s16(i8** %[[V0]])
86// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
87// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 24
88// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
89// CHECK: %[[V4:.*]] = bitcast i8** %[[V3]] to i8*
90// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)
91// CHECK: ret void
92
93// CHECK: define linkonce_odr hidden void @__default_constructor_8_s16(i8** %[[DST:.*]])
94// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
95// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
96// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
97// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
98// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 16
99// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
100// CHECK: %[[V4:.*]] = bitcast i8** %[[V3]] to i8*
101// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)
102// CHECK: ret void
103
104// CHECK: define linkonce_odr hidden void @__destructor_8_s16_s24(i8** %[[DST:.*]])
105// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
106// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
107// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
108// CHECK: call void @__destructor_8_s16(i8** %[[V0]])
109// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
110// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 24
111// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
112// CHECK: call void @objc_storeStrong(i8** %[[V3]], i8* null)
113// CHECK: ret void
114
115// CHECK: define linkonce_odr hidden void @__destructor_8_s16(i8** %[[DST:.*]])
116// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
117// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
118// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
119// CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*
120// CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 16
121// CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**
122// CHECK: call void @objc_storeStrong(i8** %[[V3]], i8* null)
123// CHECK: ret void
124
125void test_constructor_destructor_StrongOuter(void) {
126 StrongOuter t;
127}
128
129// CHECK: define void @test_copy_constructor_StrongOuter(%[[STRUCT_STRONGOUTER:.*]]* %[[S:.*]])
130// CHECK: %[[S_ADDR:.*]] = alloca %[[STRUCT_STRONGOUTER]]*, align 8
131// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER]], align 8
132// CHECK: store %[[STRUCT_STRONGOUTER]]* %[[S]], %[[STRUCT_STRONGOUTER]]** %[[S_ADDR]], align 8
133// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGOUTER]]*, %[[STRUCT_STRONGOUTER]]** %[[S_ADDR]], align 8
134// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
135// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[V0]] to i8**
136// CHECK: call void @__copy_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[V1]], i8** %[[V2]])
137// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8**
138// CHECK: call void @__destructor_8_s16_s24(i8** %[[V3]])
139// CHECK: ret void
140
141// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
142// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
143// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
144// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
145// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
146// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
147// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
148// CHECK: call void @__copy_constructor_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]])
149// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
150// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
151// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
152// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
153// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
154// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
155// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
156// CHECK: %[[V9:.*]] = call i8* @objc_retain(i8* %[[V8]])
157// CHECK: store i8* %[[V9]], i8** %[[V4]], align 8
158// CHECK: %[[V10:.*]] = bitcast i8** %[[V0]] to i8*
159// CHECK: %[[V11:.*]] = getelementptr inbounds i8, i8* %[[V10]], i64 32
160// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to i8**
161// CHECK: %[[V13:.*]] = bitcast i8** %[[V1]] to i8*
162// CHECK: %[[V14:.*]] = getelementptr inbounds i8, i8* %[[V13]], i64 32
163// CHECK: %[[V15:.*]] = bitcast i8* %[[V14]] to i8**
164// CHECK: %[[V16:.*]] = bitcast i8** %[[V12]] to i64*
165// CHECK: %[[V17:.*]] = bitcast i8** %[[V15]] to i64*
166// CHECK: %[[V18:.*]] = load i64, i64* %[[V17]], align 8
167// CHECK: store i64 %[[V18]], i64* %[[V16]], align 8
168// CHECK: ret void
169
170// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w16_s16(i8** %[[DST:.*]], i8** %[[SRC:.*]])
171// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
172// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
173// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
174// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
175// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
176// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
177// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
178// CHECK: %[[V3:.*]] = bitcast i8** %[[V1]] to i8*
179// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[V2]], i8* align 8 %[[V3]], i64 16, i1 false)
180// CHECK: %[[V4:.*]] = bitcast i8** %[[V0]] to i8*
181// CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 16
182// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8**
183// CHECK: %[[V7:.*]] = bitcast i8** %[[V1]] to i8*
184// CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 16
185// CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8**
186// CHECK: %[[V10:.*]] = load i8*, i8** %[[V9]], align 8
187// CHECK: %[[V11:.*]] = call i8* @objc_retain(i8* %[[V10]])
188// CHECK: store i8* %[[V11]], i8** %[[V6]], align 8
189// CHECK: ret void
190
191void test_copy_constructor_StrongOuter(StrongOuter *s) {
192 StrongOuter t = *s;
193}
194
195/// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
196// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
197// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
198// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
199// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
200// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
201// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
202// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
203// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
204// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
205// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
206// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
207// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
208// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
209// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* %[[V8]])
210
211void test_copy_assignment_StrongOuter(StrongOuter *d, StrongOuter *s) {
212 *d = *s;
213}
214
215// CHECK: define void @test_move_constructor_StrongOuter()
216// CHECK: %[[T1:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T:.*]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7
217// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T1]] to i8**
218// CHECK: call void @__default_constructor_8_s16_s24(i8** %[[V1]])
219// CHECK: %[[T2:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7
220// CHECK: %[[V9:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T2]] to i8**
221// CHECK: call void @__destructor_8_s16_s24(i8** %[[V9]])
222
223// CHECK: define internal void @__Block_byref_object_copy_(i8*, i8*)
224// CHECK: call void @__move_constructor_8_8_t0w16_s16_s24_t32w8(
225
226// CHECK: define linkonce_odr hidden void @__move_constructor_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
227// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
228// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
229// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
230// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
231// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
232// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
233// CHECK: call void @__move_constructor_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]])
234// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
235// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
236// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
237// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
238// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
239// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
240// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
241// CHECK: store i8* null, i8** %[[V7]], align 8
242// CHECK: store i8* %[[V8]], i8** %[[V4]], align 8
243
244// CHECK: define internal void @__Block_byref_object_dispose_(i8*)
245// CHECK: call void @__destructor_8_s16_s24(
246
247void test_move_constructor_StrongOuter(void) {
248 __block StrongOuter t;
249 BlockTy b = ^{ (void)t; };
250}
251
252// CHECK: define linkonce_odr hidden void @__move_assignment_8_8_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])
253// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
254// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
255// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
256// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
257// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
258// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
259// CHECK: call void @__move_assignment_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]])
260// CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8*
261// CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24
262// CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8**
263// CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8*
264// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24
265// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**
266// CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8
267// CHECK: store i8* null, i8** %[[V7]], align 8
268// CHECK: %[[V9:.*]] = load i8*, i8** %[[V4]], align 8
269// CHECK: store i8* %[[V8]], i8** %[[V4]], align 8
270// CHECK: call void @objc_release(i8* %[[V9]])
271
272void test_move_assignment_StrongOuter(StrongOuter *p) {
273 *p = getStrongOuter();
274}
275
276// CHECK: define void @test_parameter_StrongSmall([2 x i64] %[[A_COERCE:.*]])
277// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG:.*]], align 8
278// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[A]] to [2 x i64]*
279// CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8
280// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONG]]* %[[A]] to i8**
281// CHECK: call void @__destructor_8_s8(i8** %[[V1]])
282// CHECK: ret void
283
284void test_parameter_StrongSmall(StrongSmall a) {
285}
286
287// CHECK: define void @test_argument_StrongSmall([2 x i64] %[[A_COERCE:.*]])
288// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8
289// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8
290// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to [2 x i64]*
291// CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8
292// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TEMP_LVALUE]] to i8**
293// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
294// CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V1]], i8** %[[V2]])
295// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TEMP_LVALUE]] to [2 x i64]*
296// CHECK: %[[V4:.*]] = load [2 x i64], [2 x i64]* %[[V3]], align 8
297// CHECK: call void @calleeStrongSmall([2 x i64] %[[V4]])
298// CHECK: %[[V5:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
299// CHECK: call void @__destructor_8_s8(i8** %[[V5]])
300// CHECK: ret void
301
302void test_argument_StrongSmall(StrongSmall a) {
303 calleeStrongSmall(a);
304}
305
306// CHECK: define [2 x i64] @test_return_StrongSmall([2 x i64] %[[A_COERCE:.*]])
307// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8
308// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8
309// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to [2 x i64]*
310// CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8
311// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[RETVAL]] to i8**
312// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
313// CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V1]], i8** %[[V2]])
314// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8**
315// CHECK: call void @__destructor_8_s8(i8** %[[V3]])
316// CHECK: %[[V4:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[RETVAL]] to [2 x i64]*
317// CHECK: %[[V5:.*]] = load [2 x i64], [2 x i64]* %[[V4]], align 8
318// CHECK: ret [2 x i64] %[[V5]]
319
320StrongSmall test_return_StrongSmall(StrongSmall a) {
321 return a;
322}
323
324// CHECK: define void @test_destructor_ignored_result()
325// CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8
326// CHECK: %[[CALL:.*]] = call [2 x i64] @getStrongSmall()
327// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[COERCE]] to [2 x i64]*
328// CHECK: store [2 x i64] %[[CALL]], [2 x i64]* %[[V0]], align 8
329// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[COERCE]] to i8**
330// CHECK: call void @__destructor_8_s8(i8** %[[V1]])
331// CHECK: ret void
332
333void test_destructor_ignored_result(void) {
334 getStrongSmall();
335}
336
337// CHECK: define void @test_copy_constructor_StrongBlock(
338// CHECK: call void @__copy_constructor_8_8_sb0(
339// CHECK: call void @__destructor_8_sb0(
340// CHECK: ret void
341
342// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_sb0(i8** %[[DST:.*]], i8** %[[SRC:.*]])
343// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
344// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
345// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
346// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
347// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
348// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
349// CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8
350// CHECK: %[[V3:.*]] = call i8* @objc_retainBlock(i8* %[[V2]])
351// CHECK: store i8* %[[V3]], i8** %[[V0]], align 8
352// CHECK: ret void
353
354void test_copy_constructor_StrongBlock(StrongBlock *s) {
355 StrongBlock t = *s;
356}
357
358// CHECK: define void @test_copy_assignment_StrongBlock(%[[STRUCT_STRONGBLOCK:.*]]* %[[D:.*]], %[[STRUCT_STRONGBLOCK]]* %[[S:.*]])
359// CHECK: call void @__copy_assignment_8_8_sb0(
360
361// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_sb0(i8** %[[DST:.*]], i8** %[[SRC:.*]])
362// CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8
363// CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8
364// CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8
365// CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8
366// CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8
367// CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8
368// CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8
369// CHECK: %[[V3:.*]] = call i8* @objc_retainBlock(i8* %[[V2]])
370// CHECK: %[[V4:.*]] = load i8*, i8** %[[V0]], align 8
371// CHECK: store i8* %[[V3]], i8** %[[V0]], align 8
372// CHECK: call void @objc_release(i8* %[[V4]])
373// CHECK: ret void
374
375void test_copy_assignment_StrongBlock(StrongBlock *d, StrongBlock *s) {
376 *d = *s;
377}
378
379// CHECK: define void @test_copy_constructor_StrongVolatile0(
380// CHECK: call void @__copy_constructor_8_8_t0w4_sv8(
381// CHECK: call void @__destructor_8_sv8(
382
383// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_sv8(
384// CHECK: %[[V8:.*]] = load volatile i8*, i8** %{{.*}}, align 8
385// CHECK: %[[V9:.*]] = call i8* @objc_retain(i8* %[[V8]])
386// CHECK: store volatile i8* %[[V9]], i8** %{{.*}}, align 8
387
388void test_copy_constructor_StrongVolatile0(StrongVolatile *s) {
389 StrongVolatile t = *s;
390}
391
392// CHECK: define void @test_copy_constructor_StrongVolatile1(
393// CHECK: call void @__copy_constructor_8_8_tv0w128_sv16(
394
395void test_copy_constructor_StrongVolatile1(Strong *s) {
396 volatile Strong t = *s;
397}
398
399// CHECK: define void @test_block_capture_Strong()
400// CHECK: call void @__default_constructor_8_s16(
401// CHECK: call void @__copy_constructor_8_8_t0w16_s16(
402// CHECK: call void @__destructor_8_s16(
403// CHECK: call void @__destructor_8_s16(
404// CHECK: ret void
405
406// CHECK: define internal void @__copy_helper_block_.1(i8*, i8*)
407// CHECK: call void @__copy_constructor_8_8_t0w16_s16(
408// CHECK: ret void
409
410// CHECK: define internal void @__destroy_helper_block_.2(
411// CHECK: call void @__destructor_8_s16(
412// CHECK: ret void
413
414void test_block_capture_Strong(void) {
415 Strong t;
416 BlockTy b = ^(){ (void)t; };
417}
418
419// CHECK: define void @test_variable_length_array(i32 %[[N:.*]])
420// CHECK: %[[N_ADDR:.*]] = alloca i32, align 4
421// CHECK: store i32 %[[N]], i32* %[[N_ADDR]], align 4
422// CHECK: %[[V0:.*]] = load i32, i32* %[[N_ADDR]], align 4
423// CHECK: %[[V1:.*]] = zext i32 %[[V0]] to i64
424// CHECK: %[[VLA:.*]] = alloca %[[STRUCT_STRONG:.*]], i64 %[[V1]], align 8
425// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONG]]* %[[VLA]] to i8**
426// CHECK: %[[V4:.*]] = mul nuw i64 24, %[[V1]]
427// CHECK: %[[V5:.*]] = bitcast i8** %[[V3]] to i8*
428// CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 %[[V4]]
429// CHECK: %[[DSTARRAY_END:.*]] = bitcast i8* %[[V6]] to i8**
430// CHECK: br label
431
432// CHECK: %[[DSTADDR_CUR:.*]] = phi i8** [ %[[V3]], {{.*}} ], [ %[[V7:.*]], {{.*}} ]
433// CHECK: %[[DONE:.*]] = icmp eq i8** %[[DSTADDR_CUR]], %[[DSTARRAY_END]]
434// CHECK: br i1 %[[DONE]], label
435
436// CHECK: call void @__default_constructor_8_s16(i8** %[[DSTADDR_CUR]])
437// CHECK: %[[V8:.*]] = bitcast i8** %[[DSTADDR_CUR]] to i8*
438// CHECK: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 24
439// CHECK: %[[V7]] = bitcast i8* %[[V9]] to i8**
440// CHECK: br label
441
442// CHECK: call void @func(%[[STRUCT_STRONG]]* %[[VLA]])
443// CHECK: %[[V10:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[VLA]], i64 %[[V1]]
444// CHECK: %[[ARRAYDESTROY_ISEMPTY:.*]] = icmp eq %[[STRUCT_STRONG]]* %[[VLA]], %[[V10]]
445// CHECK: br i1 %[[ARRAYDESTROY_ISEMPTY]], label
446
447// CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi %[[STRUCT_STRONG]]* [ %[[V10]], {{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], {{.*}} ]
448// CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENTPAST]], i64 -1
449// CHECK: %[[V11:.*]] = bitcast %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENT]] to i8**
450// CHECK: call void @__destructor_8_s16(i8** %[[V11]])
451// CHECK: %[[ARRAYDESTROY_DONE:.*]] = icmp eq %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENT]], %[[VLA]]
452// CHECK: br i1 %[[ARRAYDESTROY_DONE]], label
453
454// CHECK: ret void
455
456void test_variable_length_array(int n) {
457 Strong a[n];
458 func(a);
459}
460
461// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s8n4_s8_AE(
462// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %{{.*}}, i8 0, i64 32, i1 false)
463void test_constructor_destructor_IDArray(void) {
464 IDArray t;
465}
466
467// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s24n4_s24_AE(
468void test_constructor_destructor_StructArray(void) {
469 StructArray t;
470}
471
472// Check that IRGen copies the 9-bit bitfield emitting i16 load and store.
473
474// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_t8w2(
475// CHECK: %[[V4:.*]] = bitcast i8** %{{.*}} to i8*
476// CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8
477// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8**
478// CHECK: %[[V7:.*]] = bitcast i8** %{{.*}} to i8*
479// CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 8
480// CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8**
481// CHECK: %[[V10:.*]] = bitcast i8** %[[V6]] to i16*
482// CHECK: %[[V11:.*]] = bitcast i8** %[[V9]] to i16*
483// CHECK: %[[V12:.*]] = load i16, i16* %[[V11]], align 8
484// CHECK: store i16 %[[V12]], i16* %[[V10]], align 8
485// CHECK: ret void
486
487void test_copy_constructor_Bitfield0(Bitfield0 *a) {
488 Bitfield0 t = *a;
489}
490
491// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w2_s8_t16w4_s24_t32w12_s48_t56w9_tv513w2_tv520w8
492// CHECK: %[[V4:.*]] = load i16, i16* %{{.*}}, align 8
493// CHECK: store i16 %[[V4]], i16* %{{.*}}, align 8
494// CHECK: %[[V21:.*]] = load i32, i32* %{{.*}}, align 8
495// CHECK: store i32 %[[V21]], i32* %{{.*}}, align 8
496// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 12, i1 false)
497// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 9, i1 false)
498// CHECK: %[[V54:.*]] = bitcast i8** %[[V0:.*]] to %[[STRUCT_BITFIELD1]]*
499// CHECK: %[[I5:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V54]], i32 0, i32 8
500// CHECK: %[[V55:.*]] = bitcast i8** %[[V1:.*]] to %[[STRUCT_BITFIELD1]]*
501// CHECK: %[[I51:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V55]], i32 0, i32 8
502// CHECK: %[[BF_LOAD:.*]] = load volatile i8, i8* %[[I51]], align 8
503// CHECK: %[[BF_SHL:.*]] = shl i8 %[[BF_LOAD]], 5
504// CHECK: %[[BF_ASHR:.*]] = ashr i8 %[[BF_SHL]], 6
505// CHECK: %[[BF_CAST:.*]] = sext i8 %[[BF_ASHR]] to i32
506// CHECK: %[[V56:.*]] = trunc i32 %[[BF_CAST]] to i8
507// CHECK: %[[BF_LOAD2:.*]] = load volatile i8, i8* %[[I5]], align 8
508// CHECK: %[[BF_VALUE:.*]] = and i8 %[[V56]], 3
509// CHECK: %[[BF_SHL3:.*]] = shl i8 %[[BF_VALUE]], 1
510// CHECK: %[[BF_CLEAR:.*]] = and i8 %[[BF_LOAD2]], -7
511// CHECK: %[[BF_SET:.*]] = or i8 %[[BF_CLEAR]], %[[BF_SHL3]]
512// CHECK: store volatile i8 %[[BF_SET]], i8* %[[I5]], align 8
513// CHECK: %[[V57:.*]] = bitcast i8** %[[V0]] to %[[STRUCT_BITFIELD1]]*
514// CHECK: %[[I6:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V57]], i32 0, i32 9
515// CHECK: %[[V58:.*]] = bitcast i8** %[[V1]] to %[[STRUCT_BITFIELD1]]*
516// CHECK: %[[I64:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V58]], i32 0, i32 9
517// CHECK: %[[V59:.*]] = load volatile i8, i8* %[[I64]], align 1
518// CHECK: store volatile i8 %[[V59]], i8* %[[I6]], align 1
519
520void test_copy_constructor_Bitfield1(Bitfield1 *a) {
521 Bitfield1 t = *a;
522}