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