1 | // RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s |
2 | |
3 | // RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -I %S/Inputs -o %t %s |
4 | // RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s |
5 | |
6 | #ifndef HEADER |
7 | #define HEADER |
8 | #include "strong_in_union.h" |
9 | |
10 | typedef void (^BlockTy)(void); |
11 | |
12 | typedef struct { |
13 | int a[4]; |
14 | } Trivial; |
15 | |
16 | typedef struct { |
17 | Trivial f0; |
18 | id f1; |
19 | } Strong; |
20 | |
21 | typedef struct { |
22 | int i; |
23 | id f1; |
24 | } StrongSmall; |
25 | |
26 | typedef struct { |
27 | Strong f0; |
28 | id f1; |
29 | double d; |
30 | } StrongOuter; |
31 | |
32 | typedef struct { |
33 | id f0; |
34 | Strong f1; |
35 | } StrongOuter2; |
36 | |
37 | typedef struct { |
38 | int f0; |
39 | volatile id f1; |
40 | } StrongVolatile; |
41 | |
42 | typedef struct { |
43 | BlockTy f0; |
44 | } StrongBlock; |
45 | |
46 | typedef struct { |
47 | int i; |
48 | id f0[2][2]; |
49 | } IDArray; |
50 | |
51 | typedef struct { |
52 | double d; |
53 | Strong f0[2][2]; |
54 | } StructArray; |
55 | |
56 | typedef struct { |
57 | id f0; |
58 | int i : 9; |
59 | } Bitfield0; |
60 | |
61 | typedef struct { |
62 | char c; |
63 | int i0 : 2; |
64 | int i1 : 4; |
65 | id f0; |
66 | int i2 : 31; |
67 | int i3 : 1; |
68 | id f1; |
69 | int : 0; |
70 | int a[3]; |
71 | id f2; |
72 | double d; |
73 | int i4 : 1; |
74 | volatile int i5 : 2; |
75 | volatile char i6; |
76 | } Bitfield1; |
77 | |
78 | typedef struct { |
79 | id x; |
80 | volatile int a[16]; |
81 | } VolatileArray ; |
82 | |
83 | #endif |
84 | |
85 | #ifdef USESTRUCT |
86 | |
87 | StrongSmall getStrongSmall(void); |
88 | StrongOuter getStrongOuter(void); |
89 | StrongOuter2 getStrongOuter2(void); |
90 | void calleeStrongSmall(StrongSmall); |
91 | void func(Strong *); |
92 | |
93 | // CHECK: %[[STRUCT_BITFIELD1:.*]] = type { i8, i8, i8*, i32, i8*, [3 x i32], i8*, double, i8, i8 } |
94 | |
95 | // CHECK: define void @test_constructor_destructor_StrongOuter() |
96 | // CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER:.*]], align 8 |
97 | // CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8** |
98 | // CHECK: call void @__default_constructor_8_S_s16_s24(i8** %[[V0]]) |
99 | // CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8** |
100 | // CHECK: call void @__destructor_8_S_s16_s24(i8** %[[V1]]) |
101 | // CHECK: ret void |
102 | |
103 | // CHECK: define linkonce_odr hidden void @__default_constructor_8_S_s16_s24(i8** %[[DST:.*]]) |
104 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
105 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
106 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
107 | // CHECK: call void @__default_constructor_8_s16(i8** %[[V0]]) |
108 | // CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8* |
109 | // CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 24 |
110 | // CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** |
111 | // CHECK: %[[V4:.*]] = bitcast i8** %[[V3]] to i8* |
112 | // CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false) |
113 | // CHECK: ret void |
114 | |
115 | // CHECK: define linkonce_odr hidden void @__default_constructor_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: %[[V4:.*]] = bitcast i8** %[[V3]] to i8* |
123 | // CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false) |
124 | // CHECK: ret void |
125 | |
126 | // CHECK: define linkonce_odr hidden void @__destructor_8_S_s16_s24(i8** %[[DST:.*]]) |
127 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
128 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
129 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
130 | // CHECK: call void @__destructor_8_s16(i8** %[[V0]]) |
131 | // CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8* |
132 | // CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 24 |
133 | // CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** |
134 | // CHECK: call void @llvm.objc.storeStrong(i8** %[[V3]], i8* null) |
135 | // CHECK: ret void |
136 | |
137 | // CHECK: define linkonce_odr hidden void @__destructor_8_s16(i8** %[[DST:.*]]) |
138 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
139 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
140 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
141 | // CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8* |
142 | // CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 16 |
143 | // CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** |
144 | // CHECK: call void @llvm.objc.storeStrong(i8** %[[V3]], i8* null) |
145 | // CHECK: ret void |
146 | |
147 | void test_constructor_destructor_StrongOuter(void) { |
148 | StrongOuter t; |
149 | } |
150 | |
151 | // CHECK: define void @test_copy_constructor_StrongOuter(%[[STRUCT_STRONGOUTER:.*]]* %[[S:.*]]) |
152 | // CHECK: %[[S_ADDR:.*]] = alloca %[[STRUCT_STRONGOUTER]]*, align 8 |
153 | // CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER]], align 8 |
154 | // CHECK: store %[[STRUCT_STRONGOUTER]]* %[[S]], %[[STRUCT_STRONGOUTER]]** %[[S_ADDR]], align 8 |
155 | // CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGOUTER]]*, %[[STRUCT_STRONGOUTER]]** %[[S_ADDR]], align 8 |
156 | // CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8** |
157 | // CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[V0]] to i8** |
158 | // CHECK: call void @__copy_constructor_8_8_S_t0w16_s16_s24_t32w8(i8** %[[V1]], i8** %[[V2]]) |
159 | // CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T]] to i8** |
160 | // CHECK: call void @__destructor_8_S_s16_s24(i8** %[[V3]]) |
161 | // CHECK: ret void |
162 | |
163 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_S_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
164 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
165 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
166 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
167 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
168 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
169 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
170 | // CHECK: call void @__copy_constructor_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]]) |
171 | // CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8* |
172 | // CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24 |
173 | // CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8** |
174 | // CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8* |
175 | // CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24 |
176 | // CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** |
177 | // CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8 |
178 | // CHECK: %[[V9:.*]] = call i8* @llvm.objc.retain(i8* %[[V8]]) |
179 | // CHECK: store i8* %[[V9]], i8** %[[V4]], align 8 |
180 | // CHECK: %[[V10:.*]] = bitcast i8** %[[V0]] to i8* |
181 | // CHECK: %[[V11:.*]] = getelementptr inbounds i8, i8* %[[V10]], i64 32 |
182 | // CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to i8** |
183 | // CHECK: %[[V13:.*]] = bitcast i8** %[[V1]] to i8* |
184 | // CHECK: %[[V14:.*]] = getelementptr inbounds i8, i8* %[[V13]], i64 32 |
185 | // CHECK: %[[V15:.*]] = bitcast i8* %[[V14]] to i8** |
186 | // CHECK: %[[V16:.*]] = bitcast i8** %[[V12]] to i64* |
187 | // CHECK: %[[V17:.*]] = bitcast i8** %[[V15]] to i64* |
188 | // CHECK: %[[V18:.*]] = load i64, i64* %[[V17]], align 8 |
189 | // CHECK: store i64 %[[V18]], i64* %[[V16]], align 8 |
190 | // CHECK: ret void |
191 | |
192 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w16_s16(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
193 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
194 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
195 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
196 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
197 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
198 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
199 | // CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8* |
200 | // CHECK: %[[V3:.*]] = bitcast i8** %[[V1]] to i8* |
201 | // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[V2]], i8* align 8 %[[V3]], i64 16, i1 false) |
202 | // CHECK: %[[V4:.*]] = bitcast i8** %[[V0]] to i8* |
203 | // CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 16 |
204 | // CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8** |
205 | // CHECK: %[[V7:.*]] = bitcast i8** %[[V1]] to i8* |
206 | // CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 16 |
207 | // CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8** |
208 | // CHECK: %[[V10:.*]] = load i8*, i8** %[[V9]], align 8 |
209 | // CHECK: %[[V11:.*]] = call i8* @llvm.objc.retain(i8* %[[V10]]) |
210 | // CHECK: store i8* %[[V11]], i8** %[[V6]], align 8 |
211 | // CHECK: ret void |
212 | |
213 | void test_copy_constructor_StrongOuter(StrongOuter *s) { |
214 | StrongOuter t = *s; |
215 | } |
216 | |
217 | /// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_S_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
218 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
219 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
220 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
221 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
222 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
223 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
224 | // CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8* |
225 | // CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24 |
226 | // CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8** |
227 | // CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8* |
228 | // CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24 |
229 | // CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** |
230 | // CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8 |
231 | // CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* %[[V8]]) |
232 | |
233 | void test_copy_assignment_StrongOuter(StrongOuter *d, StrongOuter *s) { |
234 | *d = *s; |
235 | } |
236 | |
237 | // CHECK: define void @test_move_constructor_StrongOuter() |
238 | // CHECK: %[[T1:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T:.*]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7 |
239 | // CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T1]] to i8** |
240 | // CHECK: call void @__default_constructor_8_S_s16_s24(i8** %[[V1]]) |
241 | // CHECK: %[[T2:.*]] = getelementptr inbounds %[[STRUCT_BLOCK_BYREF_T]], %[[STRUCT_BLOCK_BYREF_T]]* %{{.*}}, i32 0, i32 7 |
242 | // CHECK: %[[V9:.*]] = bitcast %[[STRUCT_STRONGOUTER]]* %[[T2]] to i8** |
243 | // CHECK: call void @__destructor_8_S_s16_s24(i8** %[[V9]]) |
244 | |
245 | // CHECK: define internal void @__Block_byref_object_copy_(i8*, i8*) |
246 | // CHECK: call void @__move_constructor_8_8_S_t0w16_s16_s24_t32w8( |
247 | |
248 | // CHECK: define linkonce_odr hidden void @__move_constructor_8_8_S_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
249 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
250 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
251 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
252 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
253 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
254 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
255 | // CHECK: call void @__move_constructor_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]]) |
256 | // CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8* |
257 | // CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24 |
258 | // CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8** |
259 | // CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8* |
260 | // CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24 |
261 | // CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** |
262 | // CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8 |
263 | // CHECK: store i8* null, i8** %[[V7]], align 8 |
264 | // CHECK: store i8* %[[V8]], i8** %[[V4]], align 8 |
265 | |
266 | // CHECK: define internal void @__Block_byref_object_dispose_(i8*) |
267 | // CHECK: call void @__destructor_8_S_s16_s24( |
268 | |
269 | void test_move_constructor_StrongOuter(void) { |
270 | __block StrongOuter t; |
271 | BlockTy b = ^{ (void)t; }; |
272 | } |
273 | |
274 | // CHECK: define linkonce_odr hidden void @__move_assignment_8_8_S_t0w16_s16_s24_t32w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
275 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
276 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
277 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
278 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
279 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
280 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
281 | // CHECK: call void @__move_assignment_8_8_t0w16_s16(i8** %[[V0]], i8** %[[V1]]) |
282 | // CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8* |
283 | // CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 24 |
284 | // CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8** |
285 | // CHECK: %[[V5:.*]] = bitcast i8** %[[V1]] to i8* |
286 | // CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 24 |
287 | // CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** |
288 | // CHECK: %[[V8:.*]] = load i8*, i8** %[[V7]], align 8 |
289 | // CHECK: store i8* null, i8** %[[V7]], align 8 |
290 | // CHECK: %[[V9:.*]] = load i8*, i8** %[[V4]], align 8 |
291 | // CHECK: store i8* %[[V8]], i8** %[[V4]], align 8 |
292 | // CHECK: call void @llvm.objc.release(i8* %[[V9]]) |
293 | |
294 | void test_move_assignment_StrongOuter(StrongOuter *p) { |
295 | *p = getStrongOuter(); |
296 | } |
297 | |
298 | // CHECK: define linkonce_odr hidden void @__default_constructor_8_s0_S_s24(i8** %[[DST:.*]]) |
299 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
300 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
301 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
302 | // CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8* |
303 | // CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V1]], i8 0, i64 8, i1 false) |
304 | // CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i8* |
305 | // CHECK: %[[V3:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8 |
306 | // CHECK: %[[V4:.*]] = bitcast i8* %[[V3]] to i8** |
307 | // CHECK: call void @__default_constructor_8_s16(i8** %[[V4]]) |
308 | |
309 | // CHECK: define linkonce_odr hidden void @__destructor_8_s0_S_s24(i8** %[[DST:.*]]) |
310 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
311 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
312 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
313 | // CHECK: call void @llvm.objc.storeStrong(i8** %[[V0]], i8* null) |
314 | // CHECK: %[[V1:.*]] = bitcast i8** %[[V0]] to i8* |
315 | // CHECK: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8 |
316 | // CHECK: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** |
317 | // CHECK: call void @__destructor_8_s16(i8** %[[V3]]) |
318 | |
319 | void test_constructor_destructor_StrongOuter2(void) { |
320 | StrongOuter2 t; |
321 | } |
322 | |
323 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
324 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
325 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
326 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
327 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
328 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
329 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
330 | // CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8 |
331 | // CHECK: %[[V3:.*]] = call i8* @llvm.objc.retain(i8* %[[V2]]) |
332 | // CHECK: store i8* %[[V3]], i8** %[[V0]], align 8 |
333 | // CHECK: %[[V4:.*]] = bitcast i8** %[[V0]] to i8* |
334 | // CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8 |
335 | // CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8** |
336 | // CHECK: %[[V7:.*]] = bitcast i8** %[[V1]] to i8* |
337 | // CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 8 |
338 | // CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8** |
339 | // CHECK: call void @__copy_constructor_8_8_t0w16_s16(i8** %[[V6]], i8** %[[V9]]) |
340 | |
341 | void test_copy_constructor_StrongOuter2(StrongOuter2 *s) { |
342 | StrongOuter2 t = *s; |
343 | } |
344 | |
345 | // CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
346 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
347 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
348 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
349 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
350 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
351 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
352 | // CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8 |
353 | // CHECK: call void @llvm.objc.storeStrong(i8** %[[V0]], i8* %[[V2]]) |
354 | // CHECK: %[[V3:.*]] = bitcast i8** %[[V0]] to i8* |
355 | // CHECK: %[[V4:.*]] = getelementptr inbounds i8, i8* %[[V3]], i64 8 |
356 | // CHECK: %[[V5:.*]] = bitcast i8* %[[V4]] to i8** |
357 | // CHECK: %[[V6:.*]] = bitcast i8** %[[V1]] to i8* |
358 | // CHECK: %[[V7:.*]] = getelementptr inbounds i8, i8* %[[V6]], i64 8 |
359 | // CHECK: %[[V8:.*]] = bitcast i8* %[[V7]] to i8** |
360 | // CHECK: call void @__copy_assignment_8_8_t0w16_s16(i8** %[[V5]], i8** %[[V8]]) |
361 | |
362 | void test_copy_assignment_StrongOuter2(StrongOuter2 *d, StrongOuter2 *s) { |
363 | *d = *s; |
364 | } |
365 | |
366 | // CHECK: define linkonce_odr hidden void @__move_constructor_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
367 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
368 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
369 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
370 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
371 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
372 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
373 | // CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8 |
374 | // CHECK: store i8* null, i8** %[[V1]], align 8 |
375 | // CHECK: store i8* %[[V2]], i8** %[[V0]], align 8 |
376 | // CHECK: %[[V3:.*]] = bitcast i8** %[[V0]] to i8* |
377 | // CHECK: %[[V4:.*]] = getelementptr inbounds i8, i8* %[[V3]], i64 8 |
378 | // CHECK: %[[V5:.*]] = bitcast i8* %[[V4]] to i8** |
379 | // CHECK: %[[V6:.*]] = bitcast i8** %[[V1]] to i8* |
380 | // CHECK: %[[V7:.*]] = getelementptr inbounds i8, i8* %[[V6]], i64 8 |
381 | // CHECK: %[[V8:.*]] = bitcast i8* %[[V7]] to i8** |
382 | // CHECK: call void @__move_constructor_8_8_t0w16_s16(i8** %[[V5]], i8** %[[V8]]) |
383 | |
384 | void test_move_constructor_StrongOuter2(void) { |
385 | __block StrongOuter2 t; |
386 | BlockTy b = ^{ (void)t; }; |
387 | } |
388 | |
389 | // CHECK: define linkonce_odr hidden void @__move_assignment_8_8_s0_S_t8w16_s24(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
390 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
391 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
392 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
393 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
394 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
395 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
396 | // CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8 |
397 | // CHECK: store i8* null, i8** %[[V1]], align 8 |
398 | // CHECK: %[[V3:.*]] = load i8*, i8** %[[V0]], align 8 |
399 | // CHECK: store i8* %[[V2]], i8** %[[V0]], align 8 |
400 | // CHECK: call void @llvm.objc.release(i8* %[[V3]]) |
401 | // CHECK: %[[V4:.*]] = bitcast i8** %[[V0]] to i8* |
402 | // CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8 |
403 | // CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8** |
404 | // CHECK: %[[V7:.*]] = bitcast i8** %[[V1]] to i8* |
405 | // CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 8 |
406 | // CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8** |
407 | // CHECK: call void @__move_assignment_8_8_t0w16_s16(i8** %[[V6]], i8** %[[V9]]) |
408 | |
409 | void test_move_assignment_StrongOuter2(StrongOuter2 *p) { |
410 | *p = getStrongOuter2(); |
411 | } |
412 | |
413 | // CHECK: define void @test_parameter_StrongSmall([2 x i64] %[[A_COERCE:.*]]) |
414 | // CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG:.*]], align 8 |
415 | // CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[A]] to [2 x i64]* |
416 | // CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8 |
417 | // CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONG]]* %[[A]] to i8** |
418 | // CHECK: call void @__destructor_8_s8(i8** %[[V1]]) |
419 | // CHECK: ret void |
420 | |
421 | void test_parameter_StrongSmall(StrongSmall a) { |
422 | } |
423 | |
424 | // CHECK: define void @test_argument_StrongSmall([2 x i64] %[[A_COERCE:.*]]) |
425 | // CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8 |
426 | // CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 |
427 | // CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to [2 x i64]* |
428 | // CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8 |
429 | // CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TEMP_LVALUE]] to i8** |
430 | // CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8** |
431 | // CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V1]], i8** %[[V2]]) |
432 | // CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TEMP_LVALUE]] to [2 x i64]* |
433 | // CHECK: %[[V4:.*]] = load [2 x i64], [2 x i64]* %[[V3]], align 8 |
434 | // CHECK: call void @calleeStrongSmall([2 x i64] %[[V4]]) |
435 | // CHECK: %[[V5:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8** |
436 | // CHECK: call void @__destructor_8_s8(i8** %[[V5]]) |
437 | // CHECK: ret void |
438 | |
439 | void test_argument_StrongSmall(StrongSmall a) { |
440 | calleeStrongSmall(a); |
441 | } |
442 | |
443 | // CHECK: define [2 x i64] @test_return_StrongSmall([2 x i64] %[[A_COERCE:.*]]) |
444 | // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8 |
445 | // CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 |
446 | // CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to [2 x i64]* |
447 | // CHECK: store [2 x i64] %[[A_COERCE]], [2 x i64]* %[[V0]], align 8 |
448 | // CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[RETVAL]] to i8** |
449 | // CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8** |
450 | // CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V1]], i8** %[[V2]]) |
451 | // CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[A]] to i8** |
452 | // CHECK: call void @__destructor_8_s8(i8** %[[V3]]) |
453 | // CHECK: %[[V4:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[RETVAL]] to [2 x i64]* |
454 | // CHECK: %[[V5:.*]] = load [2 x i64], [2 x i64]* %[[V4]], align 8 |
455 | // CHECK: ret [2 x i64] %[[V5]] |
456 | |
457 | StrongSmall test_return_StrongSmall(StrongSmall a) { |
458 | return a; |
459 | } |
460 | |
461 | // CHECK: define void @test_destructor_ignored_result() |
462 | // CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_STRONGSMALL:.*]], align 8 |
463 | // CHECK: %[[CALL:.*]] = call [2 x i64] @getStrongSmall() |
464 | // CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[COERCE]] to [2 x i64]* |
465 | // CHECK: store [2 x i64] %[[CALL]], [2 x i64]* %[[V0]], align 8 |
466 | // CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[COERCE]] to i8** |
467 | // CHECK: call void @__destructor_8_s8(i8** %[[V1]]) |
468 | // CHECK: ret void |
469 | |
470 | void test_destructor_ignored_result(void) { |
471 | getStrongSmall(); |
472 | } |
473 | |
474 | // CHECK: define void @test_copy_constructor_StrongBlock( |
475 | // CHECK: call void @__copy_constructor_8_8_sb0( |
476 | // CHECK: call void @__destructor_8_sb0( |
477 | // CHECK: ret void |
478 | |
479 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_sb0(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
480 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
481 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
482 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
483 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
484 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
485 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
486 | // CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8 |
487 | // CHECK: %[[V3:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V2]]) |
488 | // CHECK: store i8* %[[V3]], i8** %[[V0]], align 8 |
489 | // CHECK: ret void |
490 | |
491 | void test_copy_constructor_StrongBlock(StrongBlock *s) { |
492 | StrongBlock t = *s; |
493 | } |
494 | |
495 | // CHECK: define void @test_copy_assignment_StrongBlock(%[[STRUCT_STRONGBLOCK:.*]]* %[[D:.*]], %[[STRUCT_STRONGBLOCK]]* %[[S:.*]]) |
496 | // CHECK: call void @__copy_assignment_8_8_sb0( |
497 | |
498 | // CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_sb0(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
499 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
500 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
501 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
502 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
503 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
504 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
505 | // CHECK: %[[V2:.*]] = load i8*, i8** %[[V1]], align 8 |
506 | // CHECK: %[[V3:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V2]]) |
507 | // CHECK: %[[V4:.*]] = load i8*, i8** %[[V0]], align 8 |
508 | // CHECK: store i8* %[[V3]], i8** %[[V0]], align 8 |
509 | // CHECK: call void @llvm.objc.release(i8* %[[V4]]) |
510 | // CHECK: ret void |
511 | |
512 | void test_copy_assignment_StrongBlock(StrongBlock *d, StrongBlock *s) { |
513 | *d = *s; |
514 | } |
515 | |
516 | // CHECK: define void @test_copy_constructor_StrongVolatile0( |
517 | // CHECK: call void @__copy_constructor_8_8_t0w4_sv8( |
518 | // CHECK: call void @__destructor_8_sv8( |
519 | |
520 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_sv8( |
521 | // CHECK: %[[V8:.*]] = load volatile i8*, i8** %{{.*}}, align 8 |
522 | // CHECK: %[[V9:.*]] = call i8* @llvm.objc.retain(i8* %[[V8]]) |
523 | // CHECK: store volatile i8* %[[V9]], i8** %{{.*}}, align 8 |
524 | |
525 | void test_copy_constructor_StrongVolatile0(StrongVolatile *s) { |
526 | StrongVolatile t = *s; |
527 | } |
528 | |
529 | // CHECK: define void @test_copy_constructor_StrongVolatile1( |
530 | // CHECK: call void @__copy_constructor_8_8_tv0w128_sv16( |
531 | |
532 | void test_copy_constructor_StrongVolatile1(Strong *s) { |
533 | volatile Strong t = *s; |
534 | } |
535 | |
536 | // CHECK: define void @test_block_capture_Strong() |
537 | // CHECK: call void @__default_constructor_8_s16( |
538 | // CHECK: call void @__copy_constructor_8_8_t0w16_s16( |
539 | // CHECK: call void @__destructor_8_s16( |
540 | // CHECK: call void @__destructor_8_s16( |
541 | // CHECK: ret void |
542 | |
543 | // CHECK: define linkonce_odr hidden void @__copy_helper_block_8_32n13_8_8_t0w16_s16(i8*, i8*) |
544 | // CHECK: call void @__copy_constructor_8_8_t0w16_s16( |
545 | // CHECK: ret void |
546 | |
547 | // CHECK: define linkonce_odr hidden void @__destroy_helper_block_8_32n5_8_s16( |
548 | // CHECK: call void @__destructor_8_s16( |
549 | // CHECK: ret void |
550 | |
551 | void test_block_capture_Strong(void) { |
552 | Strong t; |
553 | BlockTy b = ^(){ (void)t; }; |
554 | } |
555 | |
556 | // CHECK: define void @test_variable_length_array(i32 %[[N:.*]]) |
557 | // CHECK: %[[N_ADDR:.*]] = alloca i32, align 4 |
558 | // CHECK: store i32 %[[N]], i32* %[[N_ADDR]], align 4 |
559 | // CHECK: %[[V0:.*]] = load i32, i32* %[[N_ADDR]], align 4 |
560 | // CHECK: %[[V1:.*]] = zext i32 %[[V0]] to i64 |
561 | // CHECK: %[[VLA:.*]] = alloca %[[STRUCT_STRONG:.*]], i64 %[[V1]], align 8 |
562 | // CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONG]]* %[[VLA]] to i8** |
563 | // CHECK: %[[V4:.*]] = mul nuw i64 24, %[[V1]] |
564 | // CHECK: %[[V5:.*]] = bitcast i8** %[[V3]] to i8* |
565 | // CHECK: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 %[[V4]] |
566 | // CHECK: %[[DSTARRAY_END:.*]] = bitcast i8* %[[V6]] to i8** |
567 | // CHECK: br label |
568 | |
569 | // CHECK: %[[DSTADDR_CUR:.*]] = phi i8** [ %[[V3]], {{.*}} ], [ %[[V7:.*]], {{.*}} ] |
570 | // CHECK: %[[DONE:.*]] = icmp eq i8** %[[DSTADDR_CUR]], %[[DSTARRAY_END]] |
571 | // CHECK: br i1 %[[DONE]], label |
572 | |
573 | // CHECK: call void @__default_constructor_8_s16(i8** %[[DSTADDR_CUR]]) |
574 | // CHECK: %[[V8:.*]] = bitcast i8** %[[DSTADDR_CUR]] to i8* |
575 | // CHECK: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 24 |
576 | // CHECK: %[[V7]] = bitcast i8* %[[V9]] to i8** |
577 | // CHECK: br label |
578 | |
579 | // CHECK: call void @func(%[[STRUCT_STRONG]]* %[[VLA]]) |
580 | // CHECK: %[[V10:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[VLA]], i64 %[[V1]] |
581 | // CHECK: %[[ARRAYDESTROY_ISEMPTY:.*]] = icmp eq %[[STRUCT_STRONG]]* %[[VLA]], %[[V10]] |
582 | // CHECK: br i1 %[[ARRAYDESTROY_ISEMPTY]], label |
583 | |
584 | // CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi %[[STRUCT_STRONG]]* [ %[[V10]], {{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], {{.*}} ] |
585 | // CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENTPAST]], i64 -1 |
586 | // CHECK: %[[V11:.*]] = bitcast %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENT]] to i8** |
587 | // CHECK: call void @__destructor_8_s16(i8** %[[V11]]) |
588 | // CHECK: %[[ARRAYDESTROY_DONE:.*]] = icmp eq %[[STRUCT_STRONG]]* %[[ARRAYDESTROY_ELEMENT]], %[[VLA]] |
589 | // CHECK: br i1 %[[ARRAYDESTROY_DONE]], label |
590 | |
591 | // CHECK: ret void |
592 | |
593 | void test_variable_length_array(int n) { |
594 | Strong a[n]; |
595 | func(a); |
596 | } |
597 | |
598 | // CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s8n4_s8_AE( |
599 | // CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %{{.*}}, i8 0, i64 32, i1 false) |
600 | void test_constructor_destructor_IDArray(void) { |
601 | IDArray t; |
602 | } |
603 | |
604 | // CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s24n4_S_s24_AE( |
605 | void test_constructor_destructor_StructArray(void) { |
606 | StructArray t; |
607 | } |
608 | |
609 | // Test that StructArray's field 'd' is copied before entering the loop. |
610 | |
611 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w8_AB8s24n4_S_t8w16_s24_AE(i8** %[[DST:.*]], i8** %[[SRC:.*]]) |
612 | // CHECK: entry: |
613 | // CHECK: %[[DST_ADDR:.*]] = alloca i8**, align 8 |
614 | // CHECK: %[[SRC_ADDR:.*]] = alloca i8**, align 8 |
615 | // CHECK: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 |
616 | // CHECK: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 |
617 | // CHECK: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 |
618 | // CHECK: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 |
619 | // CHECK: %[[V2:.*]] = bitcast i8** %[[V0]] to i64* |
620 | // CHECK: %[[V3:.*]] = bitcast i8** %[[V1]] to i64* |
621 | // CHECK: %[[V4:.*]] = load i64, i64* %[[V3]], align 8 |
622 | // CHECK: store i64 %[[V4]], i64* %[[V2]], align 8 |
623 | |
624 | // CHECK: phi i8** |
625 | // CHECK: phi i8** |
626 | |
627 | // CHECK: phi i8** |
628 | // CHECK: phi i8** |
629 | |
630 | // CHECK-NOT: load i64, i64* % |
631 | // CHECK-NOT: store i64 % |
632 | // CHECK: call void @__copy_constructor_8_8_t0w16_s16( |
633 | |
634 | void test_copy_constructor_StructArray(StructArray a) { |
635 | StructArray t = a; |
636 | } |
637 | |
638 | // Check that IRGen copies the 9-bit bitfield emitting i16 load and store. |
639 | |
640 | // CHECK: define void @test_copy_constructor_Bitfield0( |
641 | |
642 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_t8w2( |
643 | // CHECK: %[[V4:.*]] = bitcast i8** %{{.*}} to i8* |
644 | // CHECK: %[[V5:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 8 |
645 | // CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to i8** |
646 | // CHECK: %[[V7:.*]] = bitcast i8** %{{.*}} to i8* |
647 | // CHECK: %[[V8:.*]] = getelementptr inbounds i8, i8* %[[V7]], i64 8 |
648 | // CHECK: %[[V9:.*]] = bitcast i8* %[[V8]] to i8** |
649 | // CHECK: %[[V10:.*]] = bitcast i8** %[[V6]] to i16* |
650 | // CHECK: %[[V11:.*]] = bitcast i8** %[[V9]] to i16* |
651 | // CHECK: %[[V12:.*]] = load i16, i16* %[[V11]], align 8 |
652 | // CHECK: store i16 %[[V12]], i16* %[[V10]], align 8 |
653 | // CHECK: ret void |
654 | |
655 | void test_copy_constructor_Bitfield0(Bitfield0 *a) { |
656 | Bitfield0 t = *a; |
657 | } |
658 | |
659 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w2_s8_t16w4_s24_t32w12_s48_t56w9_tv513w2_tv520w8 |
660 | // CHECK: %[[V4:.*]] = load i16, i16* %{{.*}}, align 8 |
661 | // CHECK: store i16 %[[V4]], i16* %{{.*}}, align 8 |
662 | // CHECK: %[[V21:.*]] = load i32, i32* %{{.*}}, align 8 |
663 | // CHECK: store i32 %[[V21]], i32* %{{.*}}, align 8 |
664 | // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 12, i1 false) |
665 | // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 9, i1 false) |
666 | // CHECK: %[[V54:.*]] = bitcast i8** %[[V0:.*]] to %[[STRUCT_BITFIELD1]]* |
667 | // CHECK: %[[I5:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V54]], i32 0, i32 8 |
668 | // CHECK: %[[V55:.*]] = bitcast i8** %[[V1:.*]] to %[[STRUCT_BITFIELD1]]* |
669 | // CHECK: %[[I51:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V55]], i32 0, i32 8 |
670 | // CHECK: %[[BF_LOAD:.*]] = load volatile i8, i8* %[[I51]], align 8 |
671 | // CHECK: %[[BF_SHL:.*]] = shl i8 %[[BF_LOAD]], 5 |
672 | // CHECK: %[[BF_ASHR:.*]] = ashr i8 %[[BF_SHL]], 6 |
673 | // CHECK: %[[BF_CAST:.*]] = sext i8 %[[BF_ASHR]] to i32 |
674 | // CHECK: %[[V56:.*]] = trunc i32 %[[BF_CAST]] to i8 |
675 | // CHECK: %[[BF_LOAD2:.*]] = load volatile i8, i8* %[[I5]], align 8 |
676 | // CHECK: %[[BF_VALUE:.*]] = and i8 %[[V56]], 3 |
677 | // CHECK: %[[BF_SHL3:.*]] = shl i8 %[[BF_VALUE]], 1 |
678 | // CHECK: %[[BF_CLEAR:.*]] = and i8 %[[BF_LOAD2]], -7 |
679 | // CHECK: %[[BF_SET:.*]] = or i8 %[[BF_CLEAR]], %[[BF_SHL3]] |
680 | // CHECK: store volatile i8 %[[BF_SET]], i8* %[[I5]], align 8 |
681 | // CHECK: %[[V57:.*]] = bitcast i8** %[[V0]] to %[[STRUCT_BITFIELD1]]* |
682 | // CHECK: %[[I6:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V57]], i32 0, i32 9 |
683 | // CHECK: %[[V58:.*]] = bitcast i8** %[[V1]] to %[[STRUCT_BITFIELD1]]* |
684 | // CHECK: %[[I64:.*]] = getelementptr inbounds %[[STRUCT_BITFIELD1]], %[[STRUCT_BITFIELD1]]* %[[V58]], i32 0, i32 9 |
685 | // CHECK: %[[V59:.*]] = load volatile i8, i8* %[[I64]], align 1 |
686 | // CHECK: store volatile i8 %[[V59]], i8* %[[I6]], align 1 |
687 | |
688 | void test_copy_constructor_Bitfield1(Bitfield1 *a) { |
689 | Bitfield1 t = *a; |
690 | } |
691 | |
692 | // CHECK: define void @test_strong_in_union() |
693 | // CHECK: alloca %{{.*}} |
694 | // CHECK-NEXT: ret void |
695 | |
696 | void test_strong_in_union() { |
697 | U t; |
698 | } |
699 | |
700 | // CHECK: define void @test_copy_constructor_VolatileArray( |
701 | // CHECK: call void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE( |
702 | |
703 | // CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE( |
704 | // CHECK: %[[ADDR_CUR:.*]] = phi i8** |
705 | // CHECK: %[[ADDR_CUR1:.*]] = phi i8** |
706 | // CHECK: %[[V12:.*]] = bitcast i8** %[[ADDR_CUR]] to i32* |
707 | // CHECK: %[[V13:.*]] = bitcast i8** %[[ADDR_CUR1]] to i32* |
708 | // CHECK: %[[V14:.*]] = load volatile i32, i32* %[[V13]], align 4 |
709 | // CHECK: store volatile i32 %[[V14]], i32* %[[V12]], align 4 |
710 | |
711 | void test_copy_constructor_VolatileArray(VolatileArray *a) { |
712 | VolatileArray t = *a; |
713 | } |
714 | |
715 | #endif /* USESTRUCT */ |
716 | |