xref: /llvm-project/clang/test/CodeGen/AArch64/ABI-align-packed-assembly.c (revision 207e5ccceec8d3cc3f32723e78f2a142bc61b07d)
1*207e5cccSFangrui Song // REQUIRES: aarch64-registered-target
2*207e5cccSFangrui Song // RUN: %clang_cc1 -triple aarch64 -target-feature +neon -S -O2 -o - %s | FileCheck %s
3*207e5cccSFangrui Song #include <stdarg.h>
4*207e5cccSFangrui Song #include <arm_neon.h>
5*207e5cccSFangrui Song 
6*207e5cccSFangrui Song // natural alignment 16, adjusted alignment 16
7*207e5cccSFangrui Song // expected alignment of copy on callee stack: 16
8*207e5cccSFangrui Song struct non_packed_struct {
9*207e5cccSFangrui Song   uint16x8_t M0; // member alignment 16
10*207e5cccSFangrui Song };
11*207e5cccSFangrui Song 
12*207e5cccSFangrui Song // natural alignment 1, adjusted alignment 1
13*207e5cccSFangrui Song // expected alignment of copy on callee stack: 8
14*207e5cccSFangrui Song struct __attribute((packed)) packed_struct {
15*207e5cccSFangrui Song   uint16x8_t M0; // member alignment 1, because the field is packed when the struct is packed
16*207e5cccSFangrui Song };
17*207e5cccSFangrui Song 
18*207e5cccSFangrui Song // natural alignment 1, adjusted alignment 1
19*207e5cccSFangrui Song // expected alignment of copy on callee stack: 8
20*207e5cccSFangrui Song struct packed_member {
21*207e5cccSFangrui Song   uint16x8_t M0 __attribute((packed)); // member alignment 1
22*207e5cccSFangrui Song };
23*207e5cccSFangrui Song 
24*207e5cccSFangrui Song // natural alignment 16, adjusted alignment 16 since __attribute((aligned (n))) sets the minimum alignment
25*207e5cccSFangrui Song // expected alignment of copy on callee stack: 16
26*207e5cccSFangrui Song struct __attribute((aligned (8))) aligned_struct_8 {
27*207e5cccSFangrui Song   uint16x8_t M0; // member alignment 16
28*207e5cccSFangrui Song };
29*207e5cccSFangrui Song 
30*207e5cccSFangrui Song // natural alignment 16, adjusted alignment 16
31*207e5cccSFangrui Song // expected alignment of copy on callee stack: 16
32*207e5cccSFangrui Song struct aligned_member_8 {
33*207e5cccSFangrui Song   uint16x8_t M0 __attribute((aligned (8))); // member alignment 16 since __attribute((aligned (n))) sets the minimum alignment
34*207e5cccSFangrui Song };
35*207e5cccSFangrui Song 
36*207e5cccSFangrui Song // natural alignment 8, adjusted alignment 8
37*207e5cccSFangrui Song // expected alignment of copy on callee stack: 8
38*207e5cccSFangrui Song #pragma pack(8)
39*207e5cccSFangrui Song struct pragma_packed_struct_8 {
40*207e5cccSFangrui Song   uint16x8_t M0; // member alignment 8 because the struct is subject to packed(8)
41*207e5cccSFangrui Song };
42*207e5cccSFangrui Song 
43*207e5cccSFangrui Song // natural alignment 4, adjusted alignment 4
44*207e5cccSFangrui Song // expected alignment of copy on callee stack: 8
45*207e5cccSFangrui Song #pragma pack(4)
46*207e5cccSFangrui Song struct pragma_packed_struct_4 {
47*207e5cccSFangrui Song   uint16x8_t M0; // member alignment 4 because the struct is subject to packed(4)
48*207e5cccSFangrui Song };
49*207e5cccSFangrui Song 
50*207e5cccSFangrui Song double gd;
51*207e5cccSFangrui Song void init(int, ...);
52*207e5cccSFangrui Song 
53*207e5cccSFangrui Song struct non_packed_struct gs_non_packed_struct;
54*207e5cccSFangrui Song 
55*207e5cccSFangrui Song __attribute__((noinline)) void named_arg_non_packed_struct(double d0, double d1, double d2, double d3,
56*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
57*207e5cccSFangrui Song                                  double d8, struct non_packed_struct s_non_packed_struct) {
58*207e5cccSFangrui Song // CHECK: ldr q1, [sp, #16]
59*207e5cccSFangrui Song     gd = d8;
60*207e5cccSFangrui Song     gs_non_packed_struct = s_non_packed_struct;
61*207e5cccSFangrui Song }
62*207e5cccSFangrui Song 
63*207e5cccSFangrui Song void variadic_non_packed_struct(double d0, double d1, double d2, double d3,
64*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
65*207e5cccSFangrui Song                                  double d8, ...) {
66*207e5cccSFangrui Song   va_list vl;
67*207e5cccSFangrui Song   va_start(vl, d8);
68*207e5cccSFangrui Song   struct non_packed_struct on_callee_stack;
69*207e5cccSFangrui Song   on_callee_stack = va_arg(vl, struct non_packed_struct);
70*207e5cccSFangrui Song }
71*207e5cccSFangrui Song 
72*207e5cccSFangrui Song void test_non_packed_struct() {
73*207e5cccSFangrui Song     struct non_packed_struct s_non_packed_struct;
74*207e5cccSFangrui Song     init(1, &s_non_packed_struct);
75*207e5cccSFangrui Song 
76*207e5cccSFangrui Song // CHECK: mov x8, #4611686018427387904        // =0x4000000000000000
77*207e5cccSFangrui Song // CHECK: str x8, [sp]
78*207e5cccSFangrui Song // CHECK: str q0, [sp, #16]
79*207e5cccSFangrui Song     named_arg_non_packed_struct(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_non_packed_struct);
80*207e5cccSFangrui Song // CHECK: str q0, [sp, #16]
81*207e5cccSFangrui Song     variadic_non_packed_struct(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_non_packed_struct);
82*207e5cccSFangrui Song }
83*207e5cccSFangrui Song 
84*207e5cccSFangrui Song struct packed_struct gs_packed_struct;
85*207e5cccSFangrui Song 
86*207e5cccSFangrui Song __attribute__((noinline)) void named_arg_packed_struct(double d0, double d1, double d2, double d3,
87*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
88*207e5cccSFangrui Song                                  double d8, struct packed_struct s_packed_struct) {
89*207e5cccSFangrui Song // CHECK: ldur q1, [sp, #8]
90*207e5cccSFangrui Song     gd = d8;
91*207e5cccSFangrui Song     gs_packed_struct = s_packed_struct;
92*207e5cccSFangrui Song }
93*207e5cccSFangrui Song 
94*207e5cccSFangrui Song void variadic_packed_struct(double d0, double d1, double d2, double d3,
95*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
96*207e5cccSFangrui Song                                  double d8, ...) {
97*207e5cccSFangrui Song   va_list vl;
98*207e5cccSFangrui Song   va_start(vl, d8);
99*207e5cccSFangrui Song   struct packed_struct on_callee_stack;
100*207e5cccSFangrui Song   on_callee_stack = va_arg(vl, struct packed_struct);
101*207e5cccSFangrui Song }
102*207e5cccSFangrui Song 
103*207e5cccSFangrui Song void test_packed_struct() {
104*207e5cccSFangrui Song     struct packed_struct s_packed_struct;
105*207e5cccSFangrui Song     init(1, &s_packed_struct);
106*207e5cccSFangrui Song 
107*207e5cccSFangrui Song // CHECK: mov x8, #4611686018427387904        // =0x4000000000000000
108*207e5cccSFangrui Song // CHECK: str x8, [sp]
109*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
110*207e5cccSFangrui Song     named_arg_packed_struct(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_packed_struct);
111*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
112*207e5cccSFangrui Song     variadic_packed_struct(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_packed_struct);
113*207e5cccSFangrui Song }
114*207e5cccSFangrui Song 
115*207e5cccSFangrui Song struct packed_member gs_packed_member;
116*207e5cccSFangrui Song 
117*207e5cccSFangrui Song __attribute__((noinline)) void named_arg_packed_member(double d0, double d1, double d2, double d3,
118*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
119*207e5cccSFangrui Song                                  double d8, struct packed_member s_packed_member) {
120*207e5cccSFangrui Song // CHECK: ldur q1, [sp, #8]
121*207e5cccSFangrui Song     gd = d8;
122*207e5cccSFangrui Song     gs_packed_member = s_packed_member;
123*207e5cccSFangrui Song }
124*207e5cccSFangrui Song 
125*207e5cccSFangrui Song void variadic_packed_member(double d0, double d1, double d2, double d3,
126*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
127*207e5cccSFangrui Song                                  double d8, ...) {
128*207e5cccSFangrui Song   va_list vl;
129*207e5cccSFangrui Song   va_start(vl, d8);
130*207e5cccSFangrui Song   struct packed_member on_callee_stack;
131*207e5cccSFangrui Song   on_callee_stack = va_arg(vl, struct packed_member);
132*207e5cccSFangrui Song }
133*207e5cccSFangrui Song 
134*207e5cccSFangrui Song void test_packed_member() {
135*207e5cccSFangrui Song     struct packed_member s_packed_member;
136*207e5cccSFangrui Song     init(1, &s_packed_member);
137*207e5cccSFangrui Song 
138*207e5cccSFangrui Song // CHECK: mov x8, #4611686018427387904        // =0x4000000000000000
139*207e5cccSFangrui Song // CHECK: str x8, [sp]
140*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
141*207e5cccSFangrui Song     named_arg_packed_member(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_packed_member);
142*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
143*207e5cccSFangrui Song     variadic_packed_member(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_packed_member);
144*207e5cccSFangrui Song }
145*207e5cccSFangrui Song 
146*207e5cccSFangrui Song struct aligned_struct_8 gs_aligned_struct_8;
147*207e5cccSFangrui Song 
148*207e5cccSFangrui Song __attribute__((noinline)) void named_arg_aligned_struct_8(double d0, double d1, double d2, double d3,
149*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
150*207e5cccSFangrui Song                                  double d8, struct aligned_struct_8 s_aligned_struct_8) {
151*207e5cccSFangrui Song // CHECK: ldr q1, [sp, #16]
152*207e5cccSFangrui Song     gd = d8;
153*207e5cccSFangrui Song     gs_aligned_struct_8 = s_aligned_struct_8;
154*207e5cccSFangrui Song }
155*207e5cccSFangrui Song 
156*207e5cccSFangrui Song void variadic_aligned_struct_8(double d0, double d1, double d2, double d3,
157*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
158*207e5cccSFangrui Song                                  double d8, ...) {
159*207e5cccSFangrui Song   va_list vl;
160*207e5cccSFangrui Song   va_start(vl, d8);
161*207e5cccSFangrui Song   struct aligned_struct_8 on_callee_stack;
162*207e5cccSFangrui Song   on_callee_stack = va_arg(vl, struct aligned_struct_8);
163*207e5cccSFangrui Song }
164*207e5cccSFangrui Song 
165*207e5cccSFangrui Song void test_aligned_struct_8() {
166*207e5cccSFangrui Song     struct aligned_struct_8 s_aligned_struct_8;
167*207e5cccSFangrui Song     init(1, &s_aligned_struct_8);
168*207e5cccSFangrui Song 
169*207e5cccSFangrui Song // CHECK: mov x8, #4611686018427387904        // =0x4000000000000000
170*207e5cccSFangrui Song // CHECK: str x8, [sp]
171*207e5cccSFangrui Song // CHECK: str q0, [sp, #16]
172*207e5cccSFangrui Song     named_arg_aligned_struct_8(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_aligned_struct_8);
173*207e5cccSFangrui Song // CHECK: str q0, [sp, #16]
174*207e5cccSFangrui Song     variadic_aligned_struct_8(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_aligned_struct_8);
175*207e5cccSFangrui Song }
176*207e5cccSFangrui Song 
177*207e5cccSFangrui Song struct aligned_member_8 gs_aligned_member_8;
178*207e5cccSFangrui Song 
179*207e5cccSFangrui Song __attribute__((noinline)) void named_arg_aligned_member_8(double d0, double d1, double d2, double d3,
180*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
181*207e5cccSFangrui Song                                  double d8, struct aligned_member_8 s_aligned_member_8) {
182*207e5cccSFangrui Song // CHECK: ldr q1, [sp, #16]
183*207e5cccSFangrui Song     gd = d8;
184*207e5cccSFangrui Song     gs_aligned_member_8 = s_aligned_member_8;
185*207e5cccSFangrui Song }
186*207e5cccSFangrui Song 
187*207e5cccSFangrui Song void variadic_aligned_member_8(double d0, double d1, double d2, double d3,
188*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
189*207e5cccSFangrui Song                                  double d8, ...) {
190*207e5cccSFangrui Song   va_list vl;
191*207e5cccSFangrui Song   va_start(vl, d8);
192*207e5cccSFangrui Song   struct aligned_member_8 on_callee_stack;
193*207e5cccSFangrui Song   on_callee_stack = va_arg(vl, struct aligned_member_8);
194*207e5cccSFangrui Song }
195*207e5cccSFangrui Song 
196*207e5cccSFangrui Song void test_aligned_member_8() {
197*207e5cccSFangrui Song     struct aligned_member_8 s_aligned_member_8;
198*207e5cccSFangrui Song     init(1, &s_aligned_member_8);
199*207e5cccSFangrui Song 
200*207e5cccSFangrui Song // CHECK: mov x8, #4611686018427387904        // =0x4000000000000000
201*207e5cccSFangrui Song // CHECK: str x8, [sp]
202*207e5cccSFangrui Song // CHECK: str q0, [sp, #16]
203*207e5cccSFangrui Song     named_arg_aligned_member_8(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_aligned_member_8);
204*207e5cccSFangrui Song // CHECK: str q0, [sp, #16]
205*207e5cccSFangrui Song     variadic_aligned_member_8(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_aligned_member_8);
206*207e5cccSFangrui Song }
207*207e5cccSFangrui Song 
208*207e5cccSFangrui Song struct pragma_packed_struct_8 gs_pragma_packed_struct_8;
209*207e5cccSFangrui Song 
210*207e5cccSFangrui Song __attribute__((noinline)) void named_arg_pragma_packed_struct_8(double d0, double d1, double d2, double d3,
211*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
212*207e5cccSFangrui Song                                  double d8, struct pragma_packed_struct_8 s_pragma_packed_struct_8) {
213*207e5cccSFangrui Song // CHECK: ldur q1, [sp, #8]
214*207e5cccSFangrui Song     gd = d8;
215*207e5cccSFangrui Song     gs_pragma_packed_struct_8 = s_pragma_packed_struct_8;
216*207e5cccSFangrui Song }
217*207e5cccSFangrui Song 
218*207e5cccSFangrui Song void variadic_pragma_packed_struct_8(double d0, double d1, double d2, double d3,
219*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
220*207e5cccSFangrui Song                                  double d8, ...) {
221*207e5cccSFangrui Song   va_list vl;
222*207e5cccSFangrui Song   va_start(vl, d8);
223*207e5cccSFangrui Song   struct pragma_packed_struct_8 on_callee_stack;
224*207e5cccSFangrui Song   on_callee_stack = va_arg(vl, struct pragma_packed_struct_8);
225*207e5cccSFangrui Song }
226*207e5cccSFangrui Song 
227*207e5cccSFangrui Song void test_pragma_packed_struct_8() {
228*207e5cccSFangrui Song     struct pragma_packed_struct_8 s_pragma_packed_struct_8;
229*207e5cccSFangrui Song     init(1, &s_pragma_packed_struct_8);
230*207e5cccSFangrui Song 
231*207e5cccSFangrui Song // CHECK: mov x8, #4611686018427387904        // =0x4000000000000000
232*207e5cccSFangrui Song // CHECK: str x8, [sp]
233*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
234*207e5cccSFangrui Song     named_arg_pragma_packed_struct_8(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_pragma_packed_struct_8);
235*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
236*207e5cccSFangrui Song     variadic_pragma_packed_struct_8(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_pragma_packed_struct_8);
237*207e5cccSFangrui Song }
238*207e5cccSFangrui Song 
239*207e5cccSFangrui Song struct pragma_packed_struct_4 gs_pragma_packed_struct_4;
240*207e5cccSFangrui Song 
241*207e5cccSFangrui Song __attribute__((noinline)) void named_arg_pragma_packed_struct_4(double d0, double d1, double d2, double d3,
242*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
243*207e5cccSFangrui Song                                  double d8, struct pragma_packed_struct_4 s_pragma_packed_struct_4) {
244*207e5cccSFangrui Song // CHECK: ldur q1, [sp, #8]
245*207e5cccSFangrui Song     gd = d8;
246*207e5cccSFangrui Song     gs_pragma_packed_struct_4 = s_pragma_packed_struct_4;
247*207e5cccSFangrui Song }
248*207e5cccSFangrui Song 
249*207e5cccSFangrui Song void variadic_pragma_packed_struct_4(double d0, double d1, double d2, double d3,
250*207e5cccSFangrui Song                                  double d4, double d5, double d6, double d7,
251*207e5cccSFangrui Song                                  double d8, ...) {
252*207e5cccSFangrui Song   va_list vl;
253*207e5cccSFangrui Song   va_start(vl, d8);
254*207e5cccSFangrui Song   struct pragma_packed_struct_4 on_callee_stack;
255*207e5cccSFangrui Song   on_callee_stack = va_arg(vl, struct pragma_packed_struct_4);
256*207e5cccSFangrui Song }
257*207e5cccSFangrui Song 
258*207e5cccSFangrui Song void test_pragma_packed_struct_4() {
259*207e5cccSFangrui Song     struct pragma_packed_struct_4 s_pragma_packed_struct_4;
260*207e5cccSFangrui Song     init(1, &s_pragma_packed_struct_4);
261*207e5cccSFangrui Song 
262*207e5cccSFangrui Song // CHECK: mov x8, #4611686018427387904        // =0x4000000000000000
263*207e5cccSFangrui Song // CHECK: str x8, [sp]
264*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
265*207e5cccSFangrui Song     named_arg_pragma_packed_struct_4(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_pragma_packed_struct_4);
266*207e5cccSFangrui Song // CHECK: stur q0, [sp, #8]
267*207e5cccSFangrui Song     variadic_pragma_packed_struct_4(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, s_pragma_packed_struct_4);
268*207e5cccSFangrui Song }
269