Home | History | Annotate | Download | only in CodeGen
      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