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 // RUN: %clang_cc1 -triple arm-linux-androideabi -emit-llvm -o - %s | FileCheck -check-prefix=ANDROID %s 4 5 #include <stdarg.h> 6 7 typedef __attribute__(( ext_vector_type(2) )) int __int2; 8 typedef __attribute__(( ext_vector_type(3) )) char __char3; 9 typedef __attribute__(( ext_vector_type(5) )) char __char5; 10 typedef __attribute__(( ext_vector_type(9) )) char __char9; 11 typedef __attribute__(( ext_vector_type(19) )) char __char19; 12 typedef __attribute__(( ext_vector_type(3) )) short __short3; 13 typedef __attribute__(( ext_vector_type(5) )) short __short5; 14 15 // Passing legal vector types as varargs. 16 double varargs_vec_2i(int fixed, ...) { 17 // CHECK: varargs_vec_2i 18 // CHECK: [[VAR:%.*]] = alloca <2 x i32>, align 8 19 // CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 20 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 21 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 8 22 // CHECK: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <2 x i32>* 23 // CHECK: [[VEC:%.*]] = load <2 x i32>, <2 x i32>* [[AP_CAST]], align 8 24 // CHECK: store <2 x i32> [[VEC]], <2 x i32>* [[VAR]], align 8 25 // APCS-GNU: varargs_vec_2i 26 // APCS-GNU: [[VAR:%.*]] = alloca <2 x i32>, align 8 27 // APCS-GNU: [[AP:%.*]] = load i8*, 28 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP]], i32 8 29 // APCS-GNU: [[AP_CAST:%.*]] = bitcast i8* [[AP]] to <2 x i32>* 30 // APCS-GNU: [[VEC:%.*]] = load <2 x i32>, <2 x i32>* [[AP_CAST]], align 4 31 // APCS-GNU: store <2 x i32> [[VEC]], <2 x i32>* [[VAR]], align 8 32 // ANDROID: varargs_vec_2i 33 // ANDROID: [[VAR:%.*]] = alloca <2 x i32>, align 8 34 // ANDROID: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 35 // ANDROID: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 36 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 8 37 // ANDROID: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <2 x i32>* 38 // ANDROID: [[VEC:%.*]] = load <2 x i32>, <2 x i32>* [[AP_CAST]], align 8 39 // ANDROID: store <2 x i32> [[VEC]], <2 x i32>* [[VAR]], align 8 40 va_list ap; 41 double sum = fixed; 42 va_start(ap, fixed); 43 __int2 c3 = va_arg(ap, __int2); 44 sum = sum + c3.x + c3.y; 45 va_end(ap); 46 return sum; 47 } 48 49 double test_2i(__int2 *in) { 50 // CHECK: test_2i 51 // CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_2i(i32 3, <2 x i32> {{%.*}}) 52 // APCS-GNU: test_2i 53 // APCS-GNU: call double (i32, ...) @varargs_vec_2i(i32 3, <2 x i32> {{%.*}}) 54 // ANDROID: test_2i 55 // ANDROID: call double (i32, ...) @varargs_vec_2i(i32 3, <2 x i32> {{%.*}}) 56 return varargs_vec_2i(3, *in); 57 } 58 59 double varargs_vec_3c(int fixed, ...) { 60 // CHECK: varargs_vec_3c 61 // CHECK: alloca <3 x i8>, align 4 62 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP:%.*]], i32 4 63 // CHECK: bitcast i8* [[AP]] to <3 x i8>* 64 // APCS-GNU: varargs_vec_3c 65 // APCS-GNU: alloca <3 x i8>, align 4 66 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP:%.*]], i32 4 67 // APCS-GNU: bitcast i8* [[AP]] to <3 x i8>* 68 // ANDROID: varargs_vec_3c 69 // ANDROID: alloca <3 x i8>, align 4 70 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP:%.*]], i32 4 71 // ANDROID: bitcast i8* [[AP]] to <3 x i8>* 72 va_list ap; 73 double sum = fixed; 74 va_start(ap, fixed); 75 __char3 c3 = va_arg(ap, __char3); 76 sum = sum + c3.x + c3.y; 77 va_end(ap); 78 return sum; 79 } 80 81 double test_3c(__char3 *in) { 82 // CHECK: test_3c 83 // CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_3c(i32 3, i32 {{%.*}}) 84 // APCS-GNU: test_3c 85 // APCS-GNU: call double (i32, ...) @varargs_vec_3c(i32 3, i32 {{%.*}}) 86 // ANDROID: test_3c 87 // ANDROID: call double (i32, ...) @varargs_vec_3c(i32 3, <3 x i8> {{%.*}}) 88 return varargs_vec_3c(3, *in); 89 } 90 91 double varargs_vec_5c(int fixed, ...) { 92 // CHECK: varargs_vec_5c 93 // CHECK: [[VAR:%.*]] = alloca <5 x i8>, align 8 94 // CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 95 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 96 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 8 97 // CHECK: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <5 x i8>* 98 // CHECK: [[VEC:%.*]] = load <5 x i8>, <5 x i8>* [[AP_CAST]], align 8 99 // CHECK: store <5 x i8> [[VEC]], <5 x i8>* [[VAR]], align 8 100 // APCS-GNU: varargs_vec_5c 101 // APCS-GNU: [[VAR:%.*]] = alloca <5 x i8>, align 8 102 // APCS-GNU: [[AP:%.*]] = load i8*, 103 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP]], i32 8 104 // APCS-GNU: [[AP_CAST:%.*]] = bitcast i8* [[AP]] to <5 x i8>* 105 // APCS-GNU: [[VEC:%.*]] = load <5 x i8>, <5 x i8>* [[AP_CAST]], align 4 106 // APCS-GNU: store <5 x i8> [[VEC]], <5 x i8>* [[VAR]], align 8 107 // ANDROID: varargs_vec_5c 108 // ANDROID: [[VAR:%.*]] = alloca <5 x i8>, align 8 109 // ANDROID: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 110 // ANDROID: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 111 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 8 112 // ANDROID: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <5 x i8>* 113 // ANDROID: [[VEC:%.*]] = load <5 x i8>, <5 x i8>* [[AP_CAST]], align 8 114 // ANDROID: store <5 x i8> [[VEC]], <5 x i8>* [[VAR]], align 8 115 va_list ap; 116 double sum = fixed; 117 va_start(ap, fixed); 118 __char5 c5 = va_arg(ap, __char5); 119 sum = sum + c5.x + c5.y; 120 va_end(ap); 121 return sum; 122 } 123 124 double test_5c(__char5 *in) { 125 // CHECK: test_5c 126 // CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_5c(i32 5, <2 x i32> {{%.*}}) 127 // APCS-GNU: test_5c 128 // APCS-GNU: call double (i32, ...) @varargs_vec_5c(i32 5, <2 x i32> {{%.*}}) 129 // ANDROID: test_5c 130 // ANDROID: call double (i32, ...) @varargs_vec_5c(i32 5, <2 x i32> {{%.*}}) 131 return varargs_vec_5c(5, *in); 132 } 133 134 double varargs_vec_9c(int fixed, ...) { 135 // CHECK: varargs_vec_9c 136 // CHECK: [[VAR:%.*]] = alloca <9 x i8>, align 16 137 // CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 138 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 139 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 16 140 // CHECK: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <9 x i8>* 141 // CHECK: [[T0:%.*]] = load <9 x i8>, <9 x i8>* [[AP_CAST]], align 8 142 // CHECK: store <9 x i8> [[T0]], <9 x i8>* [[VAR]], align 16 143 // APCS-GNU: varargs_vec_9c 144 // APCS-GNU: [[VAR:%.*]] = alloca <9 x i8>, align 16 145 // APCS-GNU: [[AP:%.*]] = load i8*, 146 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP]], i32 16 147 // APCS-GNU: [[AP_CAST:%.*]] = bitcast i8* [[AP]] to <9 x i8>* 148 // APCS-GNU: [[VEC:%.*]] = load <9 x i8>, <9 x i8>* [[AP_CAST]], align 4 149 // APCS-GNU: store <9 x i8> [[VEC]], <9 x i8>* [[VAR]], align 16 150 // ANDROID: varargs_vec_9c 151 // ANDROID: [[VAR:%.*]] = alloca <9 x i8>, align 16 152 // ANDROID: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 153 // ANDROID: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 154 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 16 155 // ANDROID: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <9 x i8>* 156 // ANDROID: [[T0:%.*]] = load <9 x i8>, <9 x i8>* [[AP_CAST]], align 8 157 // ANDROID: store <9 x i8> [[T0]], <9 x i8>* [[VAR]], align 16 158 va_list ap; 159 double sum = fixed; 160 va_start(ap, fixed); 161 __char9 c9 = va_arg(ap, __char9); 162 sum = sum + c9.x + c9.y; 163 va_end(ap); 164 return sum; 165 } 166 167 double test_9c(__char9 *in) { 168 // CHECK: test_9c 169 // CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_9c(i32 9, <4 x i32> {{%.*}}) 170 // APCS-GNU: test_9c 171 // APCS-GNU: call double (i32, ...) @varargs_vec_9c(i32 9, <4 x i32> {{%.*}}) 172 // ANDROID: test_9c 173 // ANDROID: call double (i32, ...) @varargs_vec_9c(i32 9, <4 x i32> {{%.*}}) 174 return varargs_vec_9c(9, *in); 175 } 176 177 double varargs_vec_19c(int fixed, ...) { 178 // CHECK: varargs_vec_19c 179 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP:%.*]], i32 4 180 // CHECK: [[VAR:%.*]] = bitcast i8* [[AP]] to <19 x i8>** 181 // CHECK: [[VAR2:%.*]] = load <19 x i8>*, <19 x i8>** [[VAR]] 182 // APCS-GNU: varargs_vec_19c 183 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP:%.*]], i32 4 184 // APCS-GNU: [[VAR:%.*]] = bitcast i8* [[AP]] to <19 x i8>** 185 // APCS-GNU: [[VAR2:%.*]] = load <19 x i8>*, <19 x i8>** [[VAR]] 186 // ANDROID: varargs_vec_19c 187 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP:%.*]], i32 4 188 // ANDROID: [[VAR:%.*]] = bitcast i8* [[AP]] to <19 x i8>** 189 // ANDROID: [[VAR2:%.*]] = load <19 x i8>*, <19 x i8>** [[VAR]] 190 va_list ap; 191 double sum = fixed; 192 va_start(ap, fixed); 193 __char19 c19 = va_arg(ap, __char19); 194 sum = sum + c19.x + c19.y; 195 va_end(ap); 196 return sum; 197 } 198 199 double test_19c(__char19 *in) { 200 // CHECK: test_19c 201 // CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}}) 202 // APCS-GNU: test_19c 203 // APCS-GNU: call double (i32, ...) @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}}) 204 // ANDROID: test_19c 205 // ANDROID: call double (i32, ...) @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}}) 206 return varargs_vec_19c(19, *in); 207 } 208 209 double varargs_vec_3s(int fixed, ...) { 210 // CHECK: varargs_vec_3s 211 // CHECK: alloca <3 x i16>, align 8 212 // CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 213 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 214 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 8 215 // CHECK: bitcast i8* [[AP_ALIGN]] to <3 x i16>* 216 // APCS-GNU: varargs_vec_3s 217 // APCS-GNU: [[VAR:%.*]] = alloca <3 x i16>, align 8 218 // APCS-GNU: [[AP:%.*]] = load i8*, 219 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP]], i32 8 220 // APCS-GNU: [[AP_CAST:%.*]] = bitcast i8* [[AP]] to <3 x i16>* 221 // APCS-GNU: [[VEC:%.*]] = load <3 x i16>, <3 x i16>* [[AP_CAST]], align 4 222 // ANDROID: varargs_vec_3s 223 // ANDROID: alloca <3 x i16>, align 8 224 // ANDROID: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 225 // ANDROID: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 226 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 8 227 // ANDROID: bitcast i8* [[AP_ALIGN]] to <3 x i16>* 228 va_list ap; 229 double sum = fixed; 230 va_start(ap, fixed); 231 __short3 c3 = va_arg(ap, __short3); 232 sum = sum + c3.x + c3.y; 233 va_end(ap); 234 return sum; 235 } 236 237 double test_3s(__short3 *in) { 238 // CHECK: test_3s 239 // CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_3s(i32 3, <2 x i32> {{%.*}}) 240 // APCS-GNU: test_3s 241 // APCS-GNU: call double (i32, ...) @varargs_vec_3s(i32 3, <2 x i32> {{%.*}}) 242 // ANDROID: test_3s 243 // ANDROID: call double (i32, ...) @varargs_vec_3s(i32 3, <3 x i16> {{%.*}}) 244 return varargs_vec_3s(3, *in); 245 } 246 247 double varargs_vec_5s(int fixed, ...) { 248 // CHECK: varargs_vec_5s 249 // CHECK: [[VAR_ALIGN:%.*]] = alloca <5 x i16>, align 16 250 // CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 251 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 252 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 16 253 // CHECK: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <5 x i16>* 254 // CHECK: [[VEC:%.*]] = load <5 x i16>, <5 x i16>* [[AP_CAST]], align 8 255 // CHECK: store <5 x i16> [[VEC]], <5 x i16>* [[VAR_ALIGN]], align 16 256 // APCS-GNU: varargs_vec_5s 257 // APCS-GNU: [[VAR:%.*]] = alloca <5 x i16>, align 16 258 // APCS-GNU: [[AP:%.*]] = load i8*, 259 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP]], i32 16 260 // APCS-GNU: [[AP_CAST:%.*]] = bitcast i8* [[AP]] to <5 x i16>* 261 // APCS-GNU: [[VEC:%.*]] = load <5 x i16>, <5 x i16>* [[AP_CAST]], align 4 262 // ANDROID: varargs_vec_5s 263 // ANDROID: [[VAR_ALIGN:%.*]] = alloca <5 x i16>, align 16 264 // ANDROID: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 265 // ANDROID: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 266 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 16 267 // ANDROID: [[AP_CAST:%.*]] = bitcast i8* [[AP_ALIGN]] to <5 x i16>* 268 // ANDROID: [[VEC:%.*]] = load <5 x i16>, <5 x i16>* [[AP_CAST]], align 8 269 // ANDROID: store <5 x i16> [[VEC]], <5 x i16>* [[VAR_ALIGN]], align 16 270 va_list ap; 271 double sum = fixed; 272 va_start(ap, fixed); 273 __short5 c5 = va_arg(ap, __short5); 274 sum = sum + c5.x + c5.y; 275 va_end(ap); 276 return sum; 277 } 278 279 double test_5s(__short5 *in) { 280 // CHECK: test_5s 281 // CHECK: call arm_aapcscc double (i32, ...) @varargs_vec_5s(i32 5, <4 x i32> {{%.*}}) 282 // APCS-GNU: test_5s 283 // APCS-GNU: call double (i32, ...) @varargs_vec_5s(i32 5, <4 x i32> {{%.*}}) 284 // ANDROID: test_5s 285 // ANDROID: call double (i32, ...) @varargs_vec_5s(i32 5, <4 x i32> {{%.*}}) 286 return varargs_vec_5s(5, *in); 287 } 288 289 // Pass struct as varargs. 290 typedef struct 291 { 292 __int2 i2; 293 float f; 294 } StructWithVec; 295 296 double varargs_struct(int fixed, ...) { 297 // CHECK: varargs_struct 298 // CHECK: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 299 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 300 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 16 301 // CHECK: bitcast i8* [[AP_ALIGN]] to %struct.StructWithVec* 302 // APCS-GNU: varargs_struct 303 // APCS-GNU: [[VAR_ALIGN:%.*]] = alloca %struct.StructWithVec 304 // APCS-GNU: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* {{%.*}}, i32 16 305 // APCS-GNU: bitcast %struct.StructWithVec* [[VAR_ALIGN]] to i8* 306 // APCS-GNU: call void @llvm.memcpy 307 // ANDROID: varargs_struct 308 // ANDROID: [[ALIGN:%.*]] = and i32 {{%.*}}, -8 309 // ANDROID: [[AP_ALIGN:%.*]] = inttoptr i32 [[ALIGN]] to i8* 310 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i32 16 311 // ANDROID: bitcast i8* [[AP_ALIGN]] to %struct.StructWithVec* 312 va_list ap; 313 double sum = fixed; 314 va_start(ap, fixed); 315 StructWithVec c3 = va_arg(ap, StructWithVec); 316 sum = sum + c3.i2.x + c3.i2.y + c3.f; 317 va_end(ap); 318 return sum; 319 } 320 321 double test_struct(StructWithVec* d) { 322 // CHECK: test_struct 323 // CHECK: call arm_aapcscc double (i32, ...) @varargs_struct(i32 3, [2 x i64] {{%.*}}) 324 // APCS-GNU: test_struct 325 // APCS-GNU: call double (i32, ...) @varargs_struct(i32 3, [2 x i64] {{%.*}}) 326 // ANDROID: test_struct 327 // ANDROID: call double (i32, ...) @varargs_struct(i32 3, [2 x i64] {{%.*}}) 328 return varargs_struct(3, *d); 329 } 330