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