blob: 12e38ba434192c77ec3ecdc020df32138738afac [file] [log] [blame]
Manman Rend105e732012-10-16 19:01:37 +00001// RUN: %clang_cc1 -triple armv7-apple-darwin -target-abi aapcs -emit-llvm -o - %s | FileCheck %s
2// RUN: %clang_cc1 -triple armv7-apple-darwin -target-abi apcs-gnu -emit-llvm -o - %s | FileCheck -check-prefix=APCS-GNU %s
3
4#include <stdarg.h>
5
6typedef __attribute__(( ext_vector_type(2) )) int __int2;
Manman Ren97f81572012-10-16 19:18:39 +00007typedef __attribute__(( ext_vector_type(3) )) char __char3;
8typedef __attribute__(( ext_vector_type(5) )) char __char5;
9typedef __attribute__(( ext_vector_type(9) )) char __char9;
10typedef __attribute__(( ext_vector_type(19) )) char __char19;
11typedef __attribute__(( ext_vector_type(3) )) short __short3;
12typedef __attribute__(( ext_vector_type(5) )) short __short5;
Manman Rend105e732012-10-16 19:01:37 +000013
14// Passing legal vector types as varargs.
15double varargs_vec_2i(int fixed, ...) {
16// CHECK: varargs_vec_2i
Manman Ren2e2f9dc2012-10-16 22:40:48 +000017// CHECK: alloca <2 x i32>, align 8
18// CHECK: [[ALIGN:%.*]] = and i32 [[VAR:%.*]], -8
19// CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8*
20// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP_ALIGN]], i32 8
21// CHECK: bitcast i8* [[AP_ALIGN]] to <2 x i32>*
Manman Rend105e732012-10-16 19:01:37 +000022// APCS-GNU: varargs_vec_2i
Manman Ren2e2f9dc2012-10-16 22:40:48 +000023// APCS-GNU: alloca <2 x i32>, align 8
24// APCS-GNU: [[VAR_ALIGN:%.*]] = alloca <2 x i32>
25// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* {{%.*}}, i32 8
26// APCS-GNU: bitcast <2 x i32>* [[VAR_ALIGN]] to i8*
Manman Rend105e732012-10-16 19:01:37 +000027// APCS-GNU: call void @llvm.memcpy
Manman Ren2e2f9dc2012-10-16 22:40:48 +000028// APCS-GNU: load <2 x i32>* [[VAR_ALIGN]]
Manman Rend105e732012-10-16 19:01:37 +000029 va_list ap;
30 double sum = fixed;
31 va_start(ap, fixed);
32 __int2 c3 = va_arg(ap, __int2);
33 sum = sum + c3.x + c3.y;
34 va_end(ap);
35 return sum;
36}
37
38double test_2i(__int2 *in) {
39// CHECK: test_2i
Manman Ren2e2f9dc2012-10-16 22:40:48 +000040// CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_2i(i32 3, <2 x i32> {{%.*}})
Manman Rend105e732012-10-16 19:01:37 +000041// APCS-GNU: test_2i
Manman Ren2e2f9dc2012-10-16 22:40:48 +000042// APCS-GNU: call double (i32, ...)* @varargs_vec_2i(i32 3, <2 x i32> {{%.*}})
Manman Rend105e732012-10-16 19:01:37 +000043 return varargs_vec_2i(3, *in);
44}
Manman Ren97f81572012-10-16 19:18:39 +000045
46double varargs_vec_3c(int fixed, ...) {
47// CHECK: varargs_vec_3c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000048// CHECK: alloca <3 x i8>, align 4
49// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP:%.*]], i32 4
50// CHECK: bitcast i8* [[AP]] to <3 x i8>*
Manman Ren97f81572012-10-16 19:18:39 +000051// APCS-GNU: varargs_vec_3c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000052// APCS-GNU: alloca <3 x i8>, align 4
53// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* [[AP:%.*]], i32 4
54// APCS-GNU: bitcast i8* [[AP]] to <3 x i8>*
Manman Ren97f81572012-10-16 19:18:39 +000055 va_list ap;
56 double sum = fixed;
57 va_start(ap, fixed);
58 __char3 c3 = va_arg(ap, __char3);
59 sum = sum + c3.x + c3.y;
60 va_end(ap);
61 return sum;
62}
63
64double test_3c(__char3 *in) {
65// CHECK: test_3c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000066// CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_3c(i32 3, i32 {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +000067// APCS-GNU: test_3c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000068// APCS-GNU: call double (i32, ...)* @varargs_vec_3c(i32 3, i32 {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +000069 return varargs_vec_3c(3, *in);
70}
71
72double varargs_vec_5c(int fixed, ...) {
73// CHECK: varargs_vec_5c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000074// CHECK: alloca <5 x i8>, align 8
75// CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8
76// CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8*
77// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP_ALIGN]], i32 8
78// CHECK: bitcast i8* [[AP_ALIGN]] to <5 x i8>*
Manman Ren97f81572012-10-16 19:18:39 +000079// APCS-GNU: varargs_vec_5c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000080// APCS-GNU: alloca <5 x i8>, align 8
81// APCS-GNU: [[VAR_ALIGN:%.*]] = alloca <5 x i8>
82// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* {{%.*}}, i32 8
83// APCS-GNU: bitcast <5 x i8>* [[VAR_ALIGN]] to i8*
Manman Ren97f81572012-10-16 19:18:39 +000084// APCS-GNU: call void @llvm.memcpy
Manman Ren2e2f9dc2012-10-16 22:40:48 +000085// APCS-GNU: load <5 x i8>* [[VAR_ALIGN]]
Manman Ren97f81572012-10-16 19:18:39 +000086 va_list ap;
87 double sum = fixed;
88 va_start(ap, fixed);
89 __char5 c5 = va_arg(ap, __char5);
90 sum = sum + c5.x + c5.y;
91 va_end(ap);
92 return sum;
93}
94
95double test_5c(__char5 *in) {
96// CHECK: test_5c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000097// CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_5c(i32 5, <2 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +000098// APCS-GNU: test_5c
Manman Ren2e2f9dc2012-10-16 22:40:48 +000099// APCS-GNU: call double (i32, ...)* @varargs_vec_5c(i32 5, <2 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000100 return varargs_vec_5c(5, *in);
101}
102
103double varargs_vec_9c(int fixed, ...) {
104// CHECK: varargs_vec_9c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000105// CHECK: alloca <9 x i8>, align 16
106// CHECK: [[VAR_ALIGN:%.*]] = alloca <9 x i8>
107// CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8
108// CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8*
109// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP_ALIGN]], i32 16
110// CHECK: bitcast <9 x i8>* [[VAR_ALIGN]] to i8*
Manman Ren97f81572012-10-16 19:18:39 +0000111// CHECK: call void @llvm.memcpy
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000112// CHECK: load <9 x i8>* [[VAR_ALIGN]]
Manman Ren97f81572012-10-16 19:18:39 +0000113// APCS-GNU: varargs_vec_9c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000114// APCS-GNU: alloca <9 x i8>, align 16
115// APCS-GNU: [[VAR_ALIGN:%.*]] = alloca <9 x i8>
116// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* {{%.*}}, i32 16
117// APCS-GNU: bitcast <9 x i8>* [[VAR_ALIGN]] to i8*
Manman Ren97f81572012-10-16 19:18:39 +0000118// APCS-GNU: call void @llvm.memcpy
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000119// APCS-GNU: load <9 x i8>* [[VAR_ALIGN]]
Manman Ren97f81572012-10-16 19:18:39 +0000120 va_list ap;
121 double sum = fixed;
122 va_start(ap, fixed);
123 __char9 c9 = va_arg(ap, __char9);
124 sum = sum + c9.x + c9.y;
125 va_end(ap);
126 return sum;
127}
128
129double test_9c(__char9 *in) {
130// CHECK: test_9c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000131// CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_9c(i32 9, <4 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000132// APCS-GNU: test_9c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000133// APCS-GNU: call double (i32, ...)* @varargs_vec_9c(i32 9, <4 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000134 return varargs_vec_9c(9, *in);
135}
136
137double varargs_vec_19c(int fixed, ...) {
138// CHECK: varargs_vec_19c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000139// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP:%.*]], i32 4
140// CHECK: [[VAR:%.*]] = bitcast i8* [[AP]] to i8**
141// CHECK: [[VAR2:%.*]] = load i8** [[VAR]]
142// CHECK: bitcast i8* [[VAR2]] to <19 x i8>*
Manman Ren97f81572012-10-16 19:18:39 +0000143// APCS-GNU: varargs_vec_19c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000144// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* [[AP:%.*]], i32 4
145// APCS-GNU: [[VAR:%.*]] = bitcast i8* [[AP]] to i8**
146// APCS-GNU: [[VAR2:%.*]] = load i8** [[VAR]]
147// APCS-GNU: bitcast i8* [[VAR2]] to <19 x i8>*
Manman Ren97f81572012-10-16 19:18:39 +0000148 va_list ap;
149 double sum = fixed;
150 va_start(ap, fixed);
151 __char19 c19 = va_arg(ap, __char19);
152 sum = sum + c19.x + c19.y;
153 va_end(ap);
154 return sum;
155}
156
157double test_19c(__char19 *in) {
158// CHECK: test_19c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000159// CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000160// APCS-GNU: test_19c
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000161// APCS-GNU: call double (i32, ...)* @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000162 return varargs_vec_19c(19, *in);
163}
164
165double varargs_vec_3s(int fixed, ...) {
166// CHECK: varargs_vec_3s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000167// CHECK: alloca <3 x i16>, align 8
168// CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8
169// CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8*
170// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP_ALIGN]], i32 8
171// CHECK: bitcast i8* [[AP_ALIGN]] to <3 x i16>*
Manman Ren97f81572012-10-16 19:18:39 +0000172// APCS-GNU: varargs_vec_3s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000173// APCS-GNU: alloca <3 x i16>, align 8
174// APCS-GNU: [[VAR_ALIGN:%.*]] = alloca <3 x i16>
175// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* {{%.*}}, i32 8
176// APCS-GNU: bitcast <3 x i16>* [[VAR_ALIGN]] to i8*
Manman Ren97f81572012-10-16 19:18:39 +0000177// APCS-GNU: call void @llvm.memcpy
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000178// APCS-GNU: load <3 x i16>* [[VAR_ALIGN]]
Manman Ren97f81572012-10-16 19:18:39 +0000179 va_list ap;
180 double sum = fixed;
181 va_start(ap, fixed);
182 __short3 c3 = va_arg(ap, __short3);
183 sum = sum + c3.x + c3.y;
184 va_end(ap);
185 return sum;
186}
187
188double test_3s(__short3 *in) {
189// CHECK: test_3s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000190// CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_3s(i32 3, <2 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000191// APCS-GNU: test_3s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000192// APCS-GNU: call double (i32, ...)* @varargs_vec_3s(i32 3, <2 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000193 return varargs_vec_3s(3, *in);
194}
195
196double varargs_vec_5s(int fixed, ...) {
197// CHECK: varargs_vec_5s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000198// CHECK: alloca <5 x i16>, align 16
199// CHECK: [[VAR_ALIGN:%.*]] = alloca <5 x i16>
200// CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8
201// CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8*
202// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP_ALIGN]], i32 16
203// CHECK: bitcast <5 x i16>* [[VAR_ALIGN]] to i8*
Manman Ren97f81572012-10-16 19:18:39 +0000204// CHECK: call void @llvm.memcpy
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000205// CHECK: load <5 x i16>* [[VAR_ALIGN]]
Manman Ren97f81572012-10-16 19:18:39 +0000206// APCS-GNU: varargs_vec_5s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000207// APCS-GNU: alloca <5 x i16>, align 16
208// APCS-GNU: [[VAR_ALIGN:%.*]] = alloca <5 x i16>
209// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* {{%.*}}, i32 16
210// APCS-GNU: bitcast <5 x i16>* [[VAR_ALIGN]] to i8*
Manman Ren97f81572012-10-16 19:18:39 +0000211// APCS-GNU: call void @llvm.memcpy
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000212// APCS-GNU: load <5 x i16>* [[VAR_ALIGN]]
Manman Ren97f81572012-10-16 19:18:39 +0000213 va_list ap;
214 double sum = fixed;
215 va_start(ap, fixed);
216 __short5 c5 = va_arg(ap, __short5);
217 sum = sum + c5.x + c5.y;
218 va_end(ap);
219 return sum;
220}
221
222double test_5s(__short5 *in) {
223// CHECK: test_5s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000224// CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_5s(i32 5, <4 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000225// APCS-GNU: test_5s
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000226// APCS-GNU: call double (i32, ...)* @varargs_vec_5s(i32 5, <4 x i32> {{%.*}})
Manman Ren97f81572012-10-16 19:18:39 +0000227 return varargs_vec_5s(5, *in);
228}
Manman Ren93371022012-10-16 19:51:48 +0000229
230// Pass struct as varargs.
231typedef struct
232{
233 __int2 i2;
234 float f;
235} StructWithVec;
236
237double varargs_struct(int fixed, ...) {
238// CHECK: varargs_struct
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000239// CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8
240// CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8*
241// CHECK: [[AP_NEXT:%.*]] = getelementptr i8* [[AP_ALIGN]], i32 16
242// CHECK: bitcast i8* [[AP_ALIGN]] to %struct.StructWithVec*
Manman Ren93371022012-10-16 19:51:48 +0000243// APCS-GNU: varargs_struct
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000244// APCS-GNU: [[VAR_ALIGN:%.*]] = alloca %struct.StructWithVec
245// APCS-GNU: [[AP_NEXT:%.*]] = getelementptr i8* {{%.*}}, i32 16
246// APCS-GNU: bitcast %struct.StructWithVec* [[VAR_ALIGN]] to i8*
Manman Ren93371022012-10-16 19:51:48 +0000247// APCS-GNU: call void @llvm.memcpy
248 va_list ap;
249 double sum = fixed;
250 va_start(ap, fixed);
251 StructWithVec c3 = va_arg(ap, StructWithVec);
252 sum = sum + c3.i2.x + c3.i2.y + c3.f;
253 va_end(ap);
254 return sum;
255}
256
257double test_struct(StructWithVec* d) {
258// CHECK: test_struct
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000259// CHECK: call arm_aapcscc double (i32, ...)* @varargs_struct(i32 3, [2 x i64] {{%.*}})
Manman Ren93371022012-10-16 19:51:48 +0000260// APCS-GNU: test_struct
Manman Ren2e2f9dc2012-10-16 22:40:48 +0000261// APCS-GNU: call double (i32, ...)* @varargs_struct(i32 3, [2 x i64] {{%.*}})
Manman Ren93371022012-10-16 19:51:48 +0000262 return varargs_struct(3, *d);
263}