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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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