Home | History | Annotate | Download | only in CodeGen
      1 // REQUIRES: arm-registered-target
      2 // RUN: %clang_cc1 -triple armv7---eabi -target-abi aapcs -mfloat-abi hard -emit-llvm %s -o - | FileCheck %s
      3 
      4 // RUN: %clang_cc1 -triple arm64-apple-darwin9 -target-abi darwinpcs \
      5 // RUN:  -ffreestanding -emit-llvm -w -o - %s | FileCheck -check-prefix=CHECK64 %s
      6 
      7 // RUN: %clang_cc1 -triple arm64-linux-gnu -ffreestanding -emit-llvm -w -o - %s \
      8 // RUN:   | FileCheck --check-prefix=CHECK64-AAPCS %s
      9 typedef long long int64_t;
     10 typedef unsigned int uint32_t;
     11 
     12 /* This is not a homogenous aggregate - fundamental types are different */
     13 typedef union {
     14   float       f[4];
     15   uint32_t    i[4];
     16 } union_with_first_floats;
     17 union_with_first_floats g_u_f;
     18 
     19 extern void takes_union_with_first_floats(union_with_first_floats a);
     20 extern union_with_first_floats returns_union_with_first_floats(void);
     21 
     22 void test_union_with_first_floats(void) {
     23   takes_union_with_first_floats(g_u_f);
     24 }
     25 // CHECK: declare arm_aapcs_vfpcc void @takes_union_with_first_floats({ [4 x i32] })
     26 
     27 void test_return_union_with_first_floats(void) {
     28   g_u_f = returns_union_with_first_floats();
     29 }
     30 // CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(%union.union_with_first_floats* sret)
     31 
     32 /* This is not a homogenous aggregate - fundamental types are different */
     33 typedef union {
     34     uint32_t    i[4];
     35     float       f[4];
     36 } union_with_non_first_floats;
     37 union_with_non_first_floats g_u_nf_f;
     38 
     39 extern void takes_union_with_non_first_floats(union_with_non_first_floats a);
     40 extern union_with_non_first_floats returns_union_with_non_first_floats(void);
     41 
     42 void test_union_with_non_first_floats(void) {
     43   takes_union_with_non_first_floats(g_u_nf_f);
     44 }
     45 // CHECK: declare arm_aapcs_vfpcc void @takes_union_with_non_first_floats({ [4 x i32] })
     46 
     47 void test_return_union_with_non_first_floats(void) {
     48   g_u_nf_f = returns_union_with_non_first_floats();
     49 }
     50 // CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(%union.union_with_non_first_floats* sret)
     51 
     52 /* This is not a homogenous aggregate - fundamental types are different */
     53 typedef struct {
     54   float a;
     55   union_with_first_floats b;
     56 } struct_with_union_with_first_floats;
     57 struct_with_union_with_first_floats g_s_f;
     58 
     59 extern void takes_struct_with_union_with_first_floats(struct_with_union_with_first_floats a);
     60 extern struct_with_union_with_first_floats returns_struct_with_union_with_first_floats(void);
     61 
     62 void test_struct_with_union_with_first_floats(void) {
     63   takes_struct_with_union_with_first_floats(g_s_f);
     64 }
     65 // CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_first_floats({ [5 x i32] })
     66 
     67 void test_return_struct_with_union_with_first_floats(void) {
     68   g_s_f = returns_struct_with_union_with_first_floats();
     69 }
     70 // CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(%struct.struct_with_union_with_first_floats* sret)
     71 
     72 /* This is not a homogenous aggregate - fundamental types are different */
     73 typedef struct {
     74   float a;
     75   union_with_non_first_floats b;
     76 } struct_with_union_with_non_first_floats;
     77 struct_with_union_with_non_first_floats g_s_nf_f;
     78 
     79 extern void takes_struct_with_union_with_non_first_floats(struct_with_union_with_non_first_floats a);
     80 extern struct_with_union_with_non_first_floats returns_struct_with_union_with_non_first_floats(void);
     81 
     82 void test_struct_with_union_with_non_first_floats(void) {
     83   takes_struct_with_union_with_non_first_floats(g_s_nf_f);
     84 }
     85 // CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_non_first_floats({ [5 x i32] })
     86 
     87 void test_return_struct_with_union_with_non_first_floats(void) {
     88   g_s_nf_f = returns_struct_with_union_with_non_first_floats();
     89 }
     90 // CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(%struct.struct_with_union_with_non_first_floats* sret)
     91 
     92 /* Plain array is not a homogenous aggregate */
     93 extern void takes_array_of_floats(float a[4]);
     94 void test_array_of_floats(void) {
     95   float a[4] = {1.0, 2.0, 3.0, 4.0};
     96   takes_array_of_floats(a);
     97 }
     98 // CHECK: declare arm_aapcs_vfpcc void @takes_array_of_floats(float*)
     99 
    100 /* Struct-type homogenous aggregate */
    101 typedef struct {
    102   float x, y, z, w;
    103 } struct_with_fundamental_elems;
    104 struct_with_fundamental_elems g_s;
    105 
    106 extern void takes_struct_with_fundamental_elems(struct_with_fundamental_elems a);
    107 extern struct_with_fundamental_elems returns_struct_with_fundamental_elems(void);
    108 
    109 void test_struct_with_fundamental_elems(void) {
    110   takes_struct_with_fundamental_elems(g_s);
    111 // CHECK:  call arm_aapcs_vfpcc  void @takes_struct_with_fundamental_elems(%struct.struct_with_fundamental_elems {{.*}})
    112 }
    113 // CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_fundamental_elems(%struct.struct_with_fundamental_elems)
    114 
    115 void test_return_struct_with_fundamental_elems(void) {
    116   g_s = returns_struct_with_fundamental_elems();
    117 // CHECK: call arm_aapcs_vfpcc  %struct.struct_with_fundamental_elems @returns_struct_with_fundamental_elems()
    118 }
    119 // CHECK: declare arm_aapcs_vfpcc %struct.struct_with_fundamental_elems @returns_struct_with_fundamental_elems()
    120 
    121 /* Array-type homogenous aggregate */
    122 typedef struct {
    123   float xyzw[4];
    124 } struct_with_array;
    125 struct_with_array g_s_a;
    126 
    127 extern void takes_struct_with_array(struct_with_array a);
    128 extern struct_with_array returns_struct_with_array(void);
    129 
    130 void test_struct_with_array(void) {
    131   takes_struct_with_array(g_s_a);
    132 // CHECK:   call arm_aapcs_vfpcc  void @takes_struct_with_array(%struct.struct_with_array {{.*}})
    133 }
    134 // CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_array(%struct.struct_with_array)
    135 
    136 void test_return_struct_with_array(void) {
    137   g_s_a = returns_struct_with_array();
    138 // CHECK:   call arm_aapcs_vfpcc  %struct.struct_with_array @returns_struct_with_array()
    139 }
    140 // CHECK: declare arm_aapcs_vfpcc %struct.struct_with_array @returns_struct_with_array()
    141 
    142 /* This union is a homogenous aggregate. Check that it's passed properly */
    143 typedef union {
    144   struct_with_fundamental_elems xyzw;
    145   float a[3];
    146 } union_with_struct_with_fundamental_elems;
    147 union_with_struct_with_fundamental_elems g_u_s_fe;
    148 
    149 extern void takes_union_with_struct_with_fundamental_elems(union_with_struct_with_fundamental_elems a);
    150 extern union_with_struct_with_fundamental_elems returns_union_with_struct_with_fundamental_elems(void);
    151 
    152 void test_union_with_struct_with_fundamental_elems(void) {
    153   takes_union_with_struct_with_fundamental_elems(g_u_s_fe);
    154 // CHECK: call arm_aapcs_vfpcc  void @takes_union_with_struct_with_fundamental_elems(%union.union_with_struct_with_fundamental_elems {{.*}})
    155 }
    156 // CHECK: declare arm_aapcs_vfpcc void @takes_union_with_struct_with_fundamental_elems(%union.union_with_struct_with_fundamental_elems)
    157 
    158 void test_return_union_with_struct_with_fundamental_elems(void) {
    159   g_u_s_fe = returns_union_with_struct_with_fundamental_elems();
    160 // CHECK: call arm_aapcs_vfpcc  %union.union_with_struct_with_fundamental_elems @returns_union_with_struct_with_fundamental_elems()
    161 }
    162 // CHECK: declare arm_aapcs_vfpcc %union.union_with_struct_with_fundamental_elems @returns_union_with_struct_with_fundamental_elems()
    163 
    164 // Make sure HAs that can be partially fit into VFP registers will be allocated
    165 // on stack and that later VFP candidates will go on stack as well.
    166 typedef struct {
    167   double x;
    168   double a2;
    169   double a3;
    170   double a4;
    171 } struct_of_four_doubles;
    172 extern void takes_struct_of_four_doubles(double a, struct_of_four_doubles b, struct_of_four_doubles c, double d);
    173 struct_of_four_doubles g_s4d;
    174 
    175 void test_struct_of_four_doubles(void) {
    176 // CHECK: test_struct_of_four_doubles
    177 // CHECK: call arm_aapcs_vfpcc void @takes_struct_of_four_doubles(double {{.*}}, %struct.struct_of_four_doubles {{.*}}, %struct.struct_of_four_doubles {{.*}}, double {{.*}})
    178 // CHECK64: test_struct_of_four_doubles
    179 // CHECK64: call void @takes_struct_of_four_doubles(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [3 x float] undef, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}})
    180 // CHECK64-AAPCS: test_struct_of_four_doubles
    181 // CHECK64-AAPCS: call void @takes_struct_of_four_doubles(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [3 x float] undef, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}})
    182   takes_struct_of_four_doubles(3.0, g_s4d, g_s4d, 4.0);
    183 }
    184 
    185 extern void takes_struct_of_four_doubles_variadic(double a, struct_of_four_doubles b, struct_of_four_doubles c, double d, ...);
    186 
    187 void test_struct_of_four_doubles_variadic(void) {
    188 // CHECK: test_struct_of_four_doubles_variadic
    189 // CHECK: call arm_aapcs_vfpcc void (double, { [4 x i64] }, { [4 x i64] }, double, ...)* @takes_struct_of_four_doubles_variadic(double {{.*}}, { [4 x i64] } {{.*}}, { [4 x i64] } {{.*}}, double {{.*}})
    190   takes_struct_of_four_doubles_variadic(3.0, g_s4d, g_s4d, 4.0);
    191 }
    192 
    193 extern void takes_struct_with_backfill(float f1, double a, float f2, struct_of_four_doubles b, struct_of_four_doubles c, double d);
    194 void test_struct_with_backfill(void) {
    195 // CHECK: test_struct_with_backfill
    196 // CHECK: call arm_aapcs_vfpcc void @takes_struct_with_backfill(float {{.*}}, double {{.*}}, float {{.*}}, %struct.struct_of_four_doubles {{.*}}, %struct.struct_of_four_doubles {{.*}}, double {{.*}})
    197   takes_struct_with_backfill(3.0, 3.1, 3.2, g_s4d, g_s4d, 4.0);
    198 }
    199 
    200 typedef __attribute__(( ext_vector_type(8) )) char __char8;
    201 typedef __attribute__(( ext_vector_type(4) ))  short __short4;
    202 typedef struct {
    203   __char8  a1;
    204   __short4 a2;
    205   __char8  a3;
    206   __short4 a4;
    207 } struct_of_vecs;
    208 extern void takes_struct_of_vecs(double a, struct_of_vecs b, struct_of_vecs c, double d);
    209 struct_of_vecs g_vec;
    210 
    211 void test_struct_of_vecs(void) {
    212 // CHECK: test_struct_of_vecs
    213 // CHECK: call arm_aapcs_vfpcc void @takes_struct_of_vecs(double {{.*}}, %struct.struct_of_vecs {{.*}}, %struct.struct_of_vecs {{.*}}, double {{.*}})
    214 // CHECK64: test_struct_of_vecs
    215 // CHECK64: call void @takes_struct_of_vecs(double {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, [3 x float] undef, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, double {{.*}})
    216 // CHECK64-AAPCS: test_struct_of_vecs
    217 // CHECK64-AAPCS: call void @takes_struct_of_vecs(double {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, [3 x float] undef, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, double {{.*}})
    218   takes_struct_of_vecs(3.0, g_vec, g_vec, 4.0);
    219 }
    220 
    221 typedef struct {
    222   double a;
    223   long double b;
    224 } struct_of_double_and_long_double;
    225 struct_of_double_and_long_double g_dld;
    226 
    227 struct_of_double_and_long_double test_struct_of_double_and_long_double(void) {
    228   return g_dld;
    229 }
    230 // CHECK: define arm_aapcs_vfpcc %struct.struct_of_double_and_long_double @test_struct_of_double_and_long_double()
    231 
    232 // FIXME: Tests necessary:
    233 //         - Vectors
    234 //         - C++ stuff
    235