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