150
|
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 %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 }
|
207
|
30 // CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(%union.union_with_first_floats* sret(%union.union_with_first_floats) align 4)
|
150
|
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 }
|
207
|
50 // CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(%union.union_with_non_first_floats* sret(%union.union_with_non_first_floats) align 4)
|
150
|
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 }
|
207
|
70 // CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(%struct.struct_with_union_with_first_floats* sret(%struct.struct_with_union_with_first_floats) align 4)
|
150
|
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 }
|
207
|
90 // CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(%struct.struct_with_union_with_non_first_floats* sret(%struct.struct_with_union_with_non_first_floats) align 4)
|
150
|
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 {{.*}}, [4 x double] {{.*}}, [4 x double] {{.*}}, double {{.*}})
|
|
180 takes_struct_of_four_doubles(3.0, g_s4d, g_s4d, 4.0);
|
|
181 }
|
|
182
|
|
183 extern void takes_struct_of_four_doubles_variadic(double a, struct_of_four_doubles b, struct_of_four_doubles c, double d, ...);
|
|
184
|
|
185 void test_struct_of_four_doubles_variadic(void) {
|
|
186 // CHECK: test_struct_of_four_doubles_variadic
|
|
187 // 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 takes_struct_of_four_doubles_variadic(3.0, g_s4d, g_s4d, 4.0);
|
|
189 }
|
|
190
|
|
191 extern void takes_struct_with_backfill(float f1, double a, float f2, struct_of_four_doubles b, struct_of_four_doubles c, double d);
|
|
192 void test_struct_with_backfill(void) {
|
|
193 // CHECK: test_struct_with_backfill
|
|
194 // 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 takes_struct_with_backfill(3.0, 3.1, 3.2, g_s4d, g_s4d, 4.0);
|
|
196 }
|
|
197
|
|
198 typedef __attribute__(( ext_vector_type(8) )) char __char8;
|
|
199 typedef __attribute__(( ext_vector_type(4) )) short __short4;
|
|
200 typedef struct {
|
|
201 __char8 a1;
|
|
202 __short4 a2;
|
|
203 __char8 a3;
|
|
204 __short4 a4;
|
|
205 } struct_of_vecs;
|
|
206 extern void takes_struct_of_vecs(double a, struct_of_vecs b, struct_of_vecs c, double d);
|
|
207 struct_of_vecs g_vec;
|
|
208
|
|
209 void test_struct_of_vecs(void) {
|
|
210 // CHECK: test_struct_of_vecs
|
|
211 // CHECK: call arm_aapcs_vfpcc void @takes_struct_of_vecs(double {{.*}}, %struct.struct_of_vecs {{.*}}, %struct.struct_of_vecs {{.*}}, double {{.*}})
|
|
212 // CHECK64: test_struct_of_vecs
|
|
213 // CHECK64: call void @takes_struct_of_vecs(double {{.*}}, [4 x <8 x i8>] {{.*}}, [4 x <8 x i8>] {{.*}}, double {{.*}})
|
|
214 takes_struct_of_vecs(3.0, g_vec, g_vec, 4.0);
|
|
215 }
|
|
216
|
|
217 typedef struct {
|
|
218 double a;
|
|
219 long double b;
|
|
220 } struct_of_double_and_long_double;
|
|
221 struct_of_double_and_long_double g_dld;
|
|
222
|
|
223 struct_of_double_and_long_double test_struct_of_double_and_long_double(void) {
|
|
224 return g_dld;
|
|
225 }
|
207
|
226 // CHECK: define{{.*}} arm_aapcs_vfpcc %struct.struct_of_double_and_long_double @test_struct_of_double_and_long_double()
|
150
|
227
|
|
228 // FIXME: Tests necessary:
|
|
229 // - Vectors
|
|
230 // - C++ stuff
|