1 // 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
6 typedef __attribute__(( ext_vector_type(2) )) int __int2;
7 typedef __attribute__(( ext_vector_type(3) )) char __char3;
8 typedef __attribute__(( ext_vector_type(5) )) char __char5;
9 typedef __attribute__(( ext_vector_type(9) )) char __char9;
10 typedef __attribute__(( ext_vector_type(19) )) char __char19;
11 typedef __attribute__(( ext_vector_type(3) )) short __short3;
12 typedef __attribute__(( ext_vector_type(5) )) short __short5;
13
14 // Passing legal vector types as varargs.
varargs_vec_2i(int fixed,...)15 double varargs_vec_2i(int fixed, ...) {
16 // CHECK: varargs_vec_2i
17 // 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>*
22 // APCS-GNU: varargs_vec_2i
23 // 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*
27 // APCS-GNU: call void @llvm.memcpy
28 // APCS-GNU: load <2 x i32>* [[VAR_ALIGN]]
29 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
test_2i(__int2 * in)38 double test_2i(__int2 *in) {
39 // CHECK: test_2i
40 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_2i(i32 3, <2 x i32> {{%.*}})
41 // APCS-GNU: test_2i
42 // APCS-GNU: call double (i32, ...)* @varargs_vec_2i(i32 3, <2 x i32> {{%.*}})
43 return varargs_vec_2i(3, *in);
44 }
45
varargs_vec_3c(int fixed,...)46 double varargs_vec_3c(int fixed, ...) {
47 // CHECK: varargs_vec_3c
48 // 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>*
51 // APCS-GNU: varargs_vec_3c
52 // 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>*
55 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
test_3c(__char3 * in)64 double test_3c(__char3 *in) {
65 // CHECK: test_3c
66 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_3c(i32 3, i32 {{%.*}})
67 // APCS-GNU: test_3c
68 // APCS-GNU: call double (i32, ...)* @varargs_vec_3c(i32 3, i32 {{%.*}})
69 return varargs_vec_3c(3, *in);
70 }
71
varargs_vec_5c(int fixed,...)72 double varargs_vec_5c(int fixed, ...) {
73 // CHECK: varargs_vec_5c
74 // 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>*
79 // APCS-GNU: varargs_vec_5c
80 // 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*
84 // APCS-GNU: call void @llvm.memcpy
85 // APCS-GNU: load <5 x i8>* [[VAR_ALIGN]]
86 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
test_5c(__char5 * in)95 double test_5c(__char5 *in) {
96 // CHECK: test_5c
97 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_5c(i32 5, <2 x i32> {{%.*}})
98 // APCS-GNU: test_5c
99 // APCS-GNU: call double (i32, ...)* @varargs_vec_5c(i32 5, <2 x i32> {{%.*}})
100 return varargs_vec_5c(5, *in);
101 }
102
varargs_vec_9c(int fixed,...)103 double varargs_vec_9c(int fixed, ...) {
104 // CHECK: varargs_vec_9c
105 // 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*
111 // CHECK: call void @llvm.memcpy
112 // CHECK: load <9 x i8>* [[VAR_ALIGN]]
113 // APCS-GNU: varargs_vec_9c
114 // 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*
118 // APCS-GNU: call void @llvm.memcpy
119 // APCS-GNU: load <9 x i8>* [[VAR_ALIGN]]
120 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
test_9c(__char9 * in)129 double test_9c(__char9 *in) {
130 // CHECK: test_9c
131 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_9c(i32 9, <4 x i32> {{%.*}})
132 // APCS-GNU: test_9c
133 // APCS-GNU: call double (i32, ...)* @varargs_vec_9c(i32 9, <4 x i32> {{%.*}})
134 return varargs_vec_9c(9, *in);
135 }
136
varargs_vec_19c(int fixed,...)137 double varargs_vec_19c(int fixed, ...) {
138 // CHECK: varargs_vec_19c
139 // 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>*
143 // APCS-GNU: varargs_vec_19c
144 // 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>*
148 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
test_19c(__char19 * in)157 double test_19c(__char19 *in) {
158 // CHECK: test_19c
159 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}})
160 // APCS-GNU: test_19c
161 // APCS-GNU: call double (i32, ...)* @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}})
162 return varargs_vec_19c(19, *in);
163 }
164
varargs_vec_3s(int fixed,...)165 double varargs_vec_3s(int fixed, ...) {
166 // CHECK: varargs_vec_3s
167 // 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>*
172 // APCS-GNU: varargs_vec_3s
173 // 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*
177 // APCS-GNU: call void @llvm.memcpy
178 // APCS-GNU: load <3 x i16>* [[VAR_ALIGN]]
179 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
test_3s(__short3 * in)188 double test_3s(__short3 *in) {
189 // CHECK: test_3s
190 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_3s(i32 3, <2 x i32> {{%.*}})
191 // APCS-GNU: test_3s
192 // APCS-GNU: call double (i32, ...)* @varargs_vec_3s(i32 3, <2 x i32> {{%.*}})
193 return varargs_vec_3s(3, *in);
194 }
195
varargs_vec_5s(int fixed,...)196 double varargs_vec_5s(int fixed, ...) {
197 // CHECK: varargs_vec_5s
198 // 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*
204 // CHECK: call void @llvm.memcpy
205 // CHECK: load <5 x i16>* [[VAR_ALIGN]]
206 // APCS-GNU: varargs_vec_5s
207 // 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*
211 // APCS-GNU: call void @llvm.memcpy
212 // APCS-GNU: load <5 x i16>* [[VAR_ALIGN]]
213 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
test_5s(__short5 * in)222 double test_5s(__short5 *in) {
223 // CHECK: test_5s
224 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_vec_5s(i32 5, <4 x i32> {{%.*}})
225 // APCS-GNU: test_5s
226 // APCS-GNU: call double (i32, ...)* @varargs_vec_5s(i32 5, <4 x i32> {{%.*}})
227 return varargs_vec_5s(5, *in);
228 }
229
230 // Pass struct as varargs.
231 typedef struct
232 {
233 __int2 i2;
234 float f;
235 } StructWithVec;
236
varargs_struct(int fixed,...)237 double varargs_struct(int fixed, ...) {
238 // CHECK: varargs_struct
239 // 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*
243 // APCS-GNU: varargs_struct
244 // 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*
247 // 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
test_struct(StructWithVec * d)257 double test_struct(StructWithVec* d) {
258 // CHECK: test_struct
259 // CHECK: call arm_aapcscc double (i32, ...)* @varargs_struct(i32 3, [2 x i64] {{%.*}})
260 // APCS-GNU: test_struct
261 // APCS-GNU: call double (i32, ...)* @varargs_struct(i32 3, [2 x i64] {{%.*}})
262 return varargs_struct(3, *d);
263 }
264