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 7typedef __attribute__(( ext_vector_type(2) )) int __int2; 8typedef __attribute__(( ext_vector_type(3) )) char __char3; 9typedef __attribute__(( ext_vector_type(5) )) char __char5; 10typedef __attribute__(( ext_vector_type(9) )) char __char9; 11typedef __attribute__(( ext_vector_type(19) )) char __char19; 12typedef __attribute__(( ext_vector_type(3) )) short __short3; 13typedef __attribute__(( ext_vector_type(5) )) short __short5; 14 15// Passing legal vector types as varargs. 16double 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 49double 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 59double 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 81double 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 91double 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 124double 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 134double 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 167double 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 177double 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 199double 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 209double 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 237double 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 247double 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 279double 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. 290typedef struct 291{ 292 __int2 i2; 293 float f; 294} StructWithVec; 295 296double 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 321double 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