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 6typedef __attribute__(( ext_vector_type(2) )) int __int2; 7typedef __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; 13 14// Passing legal vector types as varargs. 15double 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 38double 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 46double 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 64double 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 72double 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 95double 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 103double 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 129double 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 137double 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 157double 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 165double 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 188double 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 196double 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 222double 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. 231typedef struct 232{ 233 __int2 i2; 234 float f; 235} StructWithVec; 236 237double 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 257double 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