1 // RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s
2
3 // This isn't really testing anything ARM-specific; it's just a convenient
4 // 32-bit platform.
5
6 #define SWIFTCALL __attribute__((swiftcall))
7 #define OUT __attribute__((swift_indirect_result))
8 #define ERROR __attribute__((swift_error_result))
9 #define CONTEXT __attribute__((swift_context))
10
11 /*****************************************************************************/
12 /****************************** PARAMETER ABIS *******************************/
13 /*****************************************************************************/
14
indirect_result_1(OUT int * arg0,OUT float * arg1)15 SWIFTCALL void indirect_result_1(OUT int *arg0, OUT float *arg1) {}
16 // CHECK-LABEL: define {{.*}} void @indirect_result_1(i32* noalias sret align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
17
18 // TODO: maybe this shouldn't suppress sret.
indirect_result_2(OUT int * arg0,OUT float * arg1)19 SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); }
20 // CHECK-LABEL: define {{.*}} i32 @indirect_result_2(i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
21
22 typedef struct { char array[1024]; } struct_reallybig;
indirect_result_3(OUT int * arg0,OUT float * arg1)23 SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); }
24 // CHECK-LABEL: define {{.*}} void @indirect_result_3({{.*}}* noalias sret {{.*}}, i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
25
context_1(CONTEXT void * self)26 SWIFTCALL void context_1(CONTEXT void *self) {}
27 // CHECK-LABEL: define {{.*}} void @context_1(i8* swiftself
28
context_2(void * arg0,CONTEXT void * self)29 SWIFTCALL void context_2(void *arg0, CONTEXT void *self) {}
30 // CHECK-LABEL: define {{.*}} void @context_2(i8*{{.*}}, i8* swiftself
31
context_error_1(CONTEXT int * self,ERROR float ** error)32 SWIFTCALL void context_error_1(CONTEXT int *self, ERROR float **error) {}
33 // CHECK-LABEL: define {{.*}} void @context_error_1(i32* swiftself{{.*}}, float** swifterror)
34 // CHECK: [[TEMP:%.*]] = alloca float*, align 4
35 // CHECK: [[T0:%.*]] = load float*, float** [[ERRORARG:%.*]], align 4
36 // CHECK: store float* [[T0]], float** [[TEMP]], align 4
37 // CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 4
38 // CHECK: store float* [[T0]], float** [[ERRORARG]], align 4
test_context_error_1()39 void test_context_error_1() {
40 int x;
41 float *error;
42 context_error_1(&x, &error);
43 }
44 // CHECK-LABEL: define void @test_context_error_1()
45 // CHECK: [[X:%.*]] = alloca i32, align 4
46 // CHECK: [[ERROR:%.*]] = alloca float*, align 4
47 // CHECK: [[TEMP:%.*]] = alloca swifterror float*, align 4
48 // CHECK: [[T0:%.*]] = load float*, float** [[ERROR]], align 4
49 // CHECK: store float* [[T0]], float** [[TEMP]], align 4
50 // CHECK: call [[SWIFTCC:swiftcc]] void @context_error_1(i32* swiftself [[X]], float** swifterror [[TEMP]])
51 // CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 4
52 // CHECK: store float* [[T0]], float** [[ERROR]], align 4
53
context_error_2(short s,CONTEXT int * self,ERROR float ** error)54 SWIFTCALL void context_error_2(short s, CONTEXT int *self, ERROR float **error) {}
55 // CHECK-LABEL: define {{.*}} void @context_error_2(i16{{.*}}, i32* swiftself{{.*}}, float** swifterror)
56
57 /*****************************************************************************/
58 /********************************** LOWERING *********************************/
59 /*****************************************************************************/
60
61 typedef float float4 __attribute__((ext_vector_type(4)));
62 typedef float float8 __attribute__((ext_vector_type(8)));
63 typedef double double2 __attribute__((ext_vector_type(2)));
64 typedef double double4 __attribute__((ext_vector_type(4)));
65 typedef int int3 __attribute__((ext_vector_type(3)));
66 typedef int int4 __attribute__((ext_vector_type(4)));
67 typedef int int5 __attribute__((ext_vector_type(5)));
68 typedef int int8 __attribute__((ext_vector_type(8)));
69
70 #define TEST(TYPE) \
71 SWIFTCALL TYPE return_##TYPE(void) { \
72 TYPE result = {}; \
73 return result; \
74 } \
75 SWIFTCALL void take_##TYPE(TYPE v) { \
76 } \
77 void test_##TYPE() { \
78 take_##TYPE(return_##TYPE()); \
79 }
80
81 /*****************************************************************************/
82 /*********************************** STRUCTS *********************************/
83 /*****************************************************************************/
84
85 typedef struct {
86 } struct_empty;
87 TEST(struct_empty);
88 // CHECK-LABEL: define {{.*}} @return_struct_empty()
89 // CHECK: ret void
90 // CHECK-LABEL: define {{.*}} @take_struct_empty()
91 // CHECK: ret void
92
93 typedef struct {
94 int x;
95 char c0;
96 char c1;
97 float f0;
98 float f1;
99 } struct_1;
100 TEST(struct_1);
101 // CHECK-LABEL: define {{.*}} @return_struct_1()
102 // CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
103 // CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
104 // CHECK: @llvm.memset
105 // CHECK: @llvm.memcpy
106 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i16, \[2 x i8\], float, float }]]*
107 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
108 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
109 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
110 // CHECK: [[SECOND:%.*]] = load i16, i16* [[T0]], align 4
111 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
112 // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align
113 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4
114 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align
115 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i16, float, float }]] undef, i32 [[FIRST]], 0
116 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i16 [[SECOND]], 1
117 // CHECK: [[T2:%.*]] = insertvalue [[UAGG]] [[T1]], float [[THIRD]], 2
118 // CHECK: [[T3:%.*]] = insertvalue [[UAGG]] [[T2]], float [[FOURTH]], 3
119 // CHECK: ret [[UAGG]] [[T3]]
120 // CHECK-LABEL: define {{.*}} @take_struct_1(i32, i16, float, float)
121 // CHECK: [[V:%.*]] = alloca [[REC]], align 4
122 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
123 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
124 // CHECK: store i32 %0, i32* [[T0]], align 4
125 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
126 // CHECK: store i16 %1, i16* [[T0]], align 4
127 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
128 // CHECK: store float %2, float* [[T0]], align 4
129 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4
130 // CHECK: store float %3, float* [[T0]], align 4
131 // CHECK: ret void
132 // CHECK-LABEL: define void @test_struct_1()
133 // CHECK: [[TMP:%.*]] = alloca [[REC]], align 4
134 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_struct_1()
135 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
136 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
137 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
138 // CHECK: store i32 [[T1]], i32* [[T0]], align 4
139 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
140 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
141 // CHECK: store i16 [[T1]], i16* [[T0]], align 4
142 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
143 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 2
144 // CHECK: store float [[T1]], float* [[T0]], align 4
145 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4
146 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 3
147 // CHECK: store float [[T1]], float* [[T0]], align 4
148 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
149 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
150 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
151 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
152 // CHECK: [[SECOND:%.*]] = load i16, i16* [[T0]], align 4
153 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
154 // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align 4
155 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 4
156 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align 4
157 // CHECK: call [[SWIFTCC]] void @take_struct_1(i32 [[FIRST]], i16 [[SECOND]], float [[THIRD]], float [[FOURTH]])
158 // CHECK: ret void
159
160 typedef struct {
161 int x;
162 char c0;
163 __attribute__((aligned(2))) char c1;
164 float f0;
165 float f1;
166 } struct_2;
167 TEST(struct_2);
168 // CHECK-LABEL: define {{.*}} @return_struct_2()
169 // CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
170 // CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
171 // CHECK: @llvm.memcpy
172 // CHECK: @llvm.memcpy
173 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i32, float, float }]]*
174 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
175 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
176 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
177 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 4
178 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
179 // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align
180 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
181 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align
182 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i32, float, float }]] undef, i32 [[FIRST]], 0
183 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
184 // CHECK: [[T2:%.*]] = insertvalue [[UAGG]] [[T1]], float [[THIRD]], 2
185 // CHECK: [[T3:%.*]] = insertvalue [[UAGG]] [[T2]], float [[FOURTH]], 3
186 // CHECK: ret [[UAGG]] [[T3]]
187 // CHECK-LABEL: define {{.*}} @take_struct_2(i32, i32, float, float)
188 // CHECK: [[V:%.*]] = alloca [[REC]], align 4
189 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
190 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
191 // CHECK: store i32 %0, i32* [[T0]], align 4
192 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
193 // CHECK: store i32 %1, i32* [[T0]], align 4
194 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
195 // CHECK: store float %2, float* [[T0]], align 4
196 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
197 // CHECK: store float %3, float* [[T0]], align 4
198 // CHECK: ret void
199 // CHECK-LABEL: define void @test_struct_2()
200 // CHECK: [[TMP:%.*]] = alloca [[REC]], align 4
201 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_struct_2()
202 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
203 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
204 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
205 // CHECK: store i32 [[T1]], i32* [[T0]], align 4
206 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
207 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
208 // CHECK: store i32 [[T1]], i32* [[T0]], align 4
209 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
210 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 2
211 // CHECK: store float [[T1]], float* [[T0]], align 4
212 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
213 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 3
214 // CHECK: store float [[T1]], float* [[T0]], align 4
215 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
216 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
217 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
218 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
219 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 4
220 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
221 // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align 4
222 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
223 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align 4
224 // CHECK: call [[SWIFTCC]] void @take_struct_2(i32 [[FIRST]], i32 [[SECOND]], float [[THIRD]], float [[FOURTH]])
225 // CHECK: ret void
226
227 // There's no way to put a field randomly in the middle of an otherwise
228 // empty storage unit in C, so that case has to be tested in C++, which
229 // can use empty structs to introduce arbitrary padding. (In C, they end up
230 // with size 0 and so don't affect layout.)
231
232 // Misaligned data rule.
233 typedef struct {
234 char c0;
235 __attribute__((packed)) float f;
236 } struct_misaligned_1;
237 TEST(struct_misaligned_1)
238 // CHECK-LABEL: define {{.*}} @return_struct_misaligned_1()
239 // CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align
240 // CHECK: [[VAR:%.*]] = alloca [[REC]], align
241 // CHECK: @llvm.memset
242 // CHECK: @llvm.memcpy
243 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i8 }]]*
244 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
245 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align
246 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
247 // CHECK: [[SECOND:%.*]] = load i8, i8* [[T0]], align
248 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i8 }]] undef, i32 [[FIRST]], 0
249 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i8 [[SECOND]], 1
250 // CHECK: ret [[UAGG]] [[T1]]
251 // CHECK-LABEL: define {{.*}} @take_struct_misaligned_1(i32, i8)
252 // CHECK: [[V:%.*]] = alloca [[REC]], align
253 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
254 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
255 // CHECK: store i32 %0, i32* [[T0]], align
256 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
257 // CHECK: store i8 %1, i8* [[T0]], align
258 // CHECK: ret void
259
260 // Too many scalars.
261 typedef struct {
262 int x[5];
263 } struct_big_1;
264 TEST(struct_big_1)
265
266 // CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret
267
268 // Should not be byval.
269 // CHECK-LABEL: define {{.*}} void @take_struct_big_1({{.*}}*{{( %.*)?}})
270
271 /*****************************************************************************/
272 /********************************* TYPE MERGING ******************************/
273 /*****************************************************************************/
274
275 typedef union {
276 float f;
277 double d;
278 } union_het_fp;
279 TEST(union_het_fp)
280 // CHECK-LABEL: define {{.*}} @return_union_het_fp()
281 // CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
282 // CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
283 // CHECK: @llvm.memcpy
284 // CHECK: @llvm.memcpy
285 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i32 }]]*
286 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
287 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
288 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
289 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 4
290 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i32 }]] undef, i32 [[FIRST]], 0
291 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
292 // CHECK: ret [[UAGG]] [[T1]]
293 // CHECK-LABEL: define {{.*}} @take_union_het_fp(i32, i32)
294 // CHECK: [[V:%.*]] = alloca [[REC]], align 4
295 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
296 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
297 // CHECK: store i32 %0, i32* [[T0]], align 4
298 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
299 // CHECK: store i32 %1, i32* [[T0]], align 4
300 // CHECK: ret void
301 // CHECK-LABEL: define void @test_union_het_fp()
302 // CHECK: [[TMP:%.*]] = alloca [[REC]], align 4
303 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_union_het_fp()
304 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
305 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
306 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
307 // CHECK: store i32 [[T1]], i32* [[T0]], align 4
308 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
309 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
310 // CHECK: store i32 [[T1]], i32* [[T0]], align 4
311 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
312 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
313 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
314 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
315 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 4
316 // CHECK: call [[SWIFTCC]] void @take_union_het_fp(i32 [[FIRST]], i32 [[SECOND]])
317 // CHECK: ret void
318
319
320 typedef union {
321 float f1;
322 float f2;
323 } union_hom_fp;
324 TEST(union_hom_fp)
325 // CHECK-LABEL: define void @test_union_hom_fp()
326 // CHECK: [[TMP:%.*]] = alloca [[REC:%.*]], align 4
327 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] float @return_union_hom_fp()
328 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG:{ float }]]*
329 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
330 // CHECK: store float [[CALL]], float* [[T0]], align 4
331 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
332 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
333 // CHECK: [[FIRST:%.*]] = load float, float* [[T0]], align 4
334 // CHECK: call [[SWIFTCC]] void @take_union_hom_fp(float [[FIRST]])
335 // CHECK: ret void
336
337 typedef union {
338 float f1;
339 float4 fv2;
340 } union_hom_fp_partial;
341 TEST(union_hom_fp_partial)
342 // CHECK-LABEL: define void @test_union_hom_fp_partial()
343 // CHECK: [[TMP:%.*]] = alloca [[REC:%.*]], align 16
344 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG:{ float, float, float, float }]] @return_union_hom_fp_partial()
345 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG:{ float, float, float, float }]]*
346 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
347 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
348 // CHECK: store float [[T1]], float* [[T0]], align
349 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
350 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
351 // CHECK: store float [[T1]], float* [[T0]], align
352 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
353 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 2
354 // CHECK: store float [[T1]], float* [[T0]], align
355 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
356 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 3
357 // CHECK: store float [[T1]], float* [[T0]], align
358 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
359 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
360 // CHECK: [[FIRST:%.*]] = load float, float* [[T0]], align
361 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
362 // CHECK: [[SECOND:%.*]] = load float, float* [[T0]], align
363 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
364 // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align
365 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
366 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align
367 // CHECK: call [[SWIFTCC]] void @take_union_hom_fp_partial(float [[FIRST]], float [[SECOND]], float [[THIRD]], float [[FOURTH]])
368 // CHECK: ret void
369
370 typedef union {
371 struct { int x, y; } f1;
372 float4 fv2;
373 } union_het_fpv_partial;
374 TEST(union_het_fpv_partial)
375 // CHECK-LABEL: define void @test_union_het_fpv_partial()
376 // CHECK: [[TMP:%.*]] = alloca [[REC:%.*]], align 16
377 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG:{ i32, i32, float, float }]] @return_union_het_fpv_partial()
378 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG:{ i32, i32, float, float }]]*
379 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
380 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
381 // CHECK: store i32 [[T1]], i32* [[T0]], align
382 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
383 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
384 // CHECK: store i32 [[T1]], i32* [[T0]], align
385 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
386 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 2
387 // CHECK: store float [[T1]], float* [[T0]], align
388 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
389 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 3
390 // CHECK: store float [[T1]], float* [[T0]], align
391 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
392 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
393 // CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align
394 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
395 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align
396 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 2
397 // CHECK: [[THIRD:%.*]] = load float, float* [[T0]], align
398 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 3
399 // CHECK: [[FOURTH:%.*]] = load float, float* [[T0]], align
400 // CHECK: call [[SWIFTCC]] void @take_union_het_fpv_partial(i32 [[FIRST]], i32 [[SECOND]], float [[THIRD]], float [[FOURTH]])
401 // CHECK: ret void
402
403 /*****************************************************************************/
404 /****************************** VECTOR LEGALIZATION **************************/
405 /*****************************************************************************/
406
407 TEST(int4)
408 // CHECK-LABEL: define {{.*}} <4 x i32> @return_int4()
409 // CHECK-LABEL: define {{.*}} @take_int4(<4 x i32>
410
411 TEST(int8)
412 // CHECK-LABEL: define {{.*}} @return_int8()
413 // CHECK: [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 32
414 // CHECK: [[VAR:%.*]] = alloca [[REC]], align
415 // CHECK: store
416 // CHECK: load
417 // CHECK: store
418 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]*
419 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
420 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
421 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
422 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
423 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0
424 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1
425 // CHECK: ret [[UAGG]] [[T1]]
426 // CHECK-LABEL: define {{.*}} @take_int8(<4 x i32>, <4 x i32>)
427 // CHECK: [[V:%.*]] = alloca [[REC]], align
428 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
429 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
430 // CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align
431 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
432 // CHECK: store <4 x i32> %1, <4 x i32>* [[T0]], align
433 // CHECK: ret void
434 // CHECK-LABEL: define void @test_int8()
435 // CHECK: [[TMP1:%.*]] = alloca [[REC]], align
436 // CHECK: [[TMP2:%.*]] = alloca [[REC]], align
437 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int8()
438 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
439 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
440 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
441 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
442 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
443 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
444 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
445 // CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
446 // CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align
447 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
448 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
449 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
450 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
451 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
452 // CHECK: call [[SWIFTCC]] void @take_int8(<4 x i32> [[FIRST]], <4 x i32> [[SECOND]])
453 // CHECK: ret void
454
455 TEST(int5)
456 // CHECK-LABEL: define {{.*}} @return_int5()
457 // CHECK: [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 32
458 // CHECK: [[VAR:%.*]] = alloca [[REC]], align
459 // CHECK: store
460 // CHECK: load
461 // CHECK: store
462 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]*
463 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
464 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
465 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
466 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align
467 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0
468 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
469 // CHECK: ret [[UAGG]] [[T1]]
470 // CHECK-LABEL: define {{.*}} @take_int5(<4 x i32>, i32)
471 // CHECK: [[V:%.*]] = alloca [[REC]], align
472 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
473 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
474 // CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align
475 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
476 // CHECK: store i32 %1, i32* [[T0]], align
477 // CHECK: ret void
478 // CHECK-LABEL: define void @test_int5()
479 // CHECK: [[TMP1:%.*]] = alloca [[REC]], align
480 // CHECK: [[TMP2:%.*]] = alloca [[REC]], align
481 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5()
482 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
483 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
484 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
485 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
486 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
487 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
488 // CHECK: store i32 [[T1]], i32* [[T0]], align
489 // CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
490 // CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align
491 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
492 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
493 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
494 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
495 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align
496 // CHECK: call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]])
497 // CHECK: ret void
498
499 typedef struct {
500 int x;
501 int3 v __attribute__((packed));
502 } misaligned_int3;
503 TEST(misaligned_int3)
504 // CHECK-LABEL: define {{.*}} @take_misaligned_int3(i32, i32, i32, i32)
505