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