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
test_union_with_first_floats(void)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
test_return_union_with_first_floats(void)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
test_union_with_non_first_floats(void)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
test_return_union_with_non_first_floats(void)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
test_struct_with_union_with_first_floats(void)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
test_return_struct_with_union_with_first_floats(void)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
test_struct_with_union_with_non_first_floats(void)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
test_return_struct_with_union_with_non_first_floats(void)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]);
test_array_of_floats(void)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
test_struct_with_fundamental_elems(void)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
test_return_struct_with_fundamental_elems(void)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
test_struct_with_array(void)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
test_return_struct_with_array(void)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
test_union_with_struct_with_fundamental_elems(void)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
test_return_union_with_struct_with_fundamental_elems(void)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
test_struct_of_four_doubles(void)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);
test_struct_with_backfill(void)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
test_struct_of_vecs(void)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