• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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