// Test that structs aligned to 128 bits are passed with the correct ABI on aarch64. // revisions:linux darwin windows //[linux] compile-flags: --target aarch64-unknown-linux-gnu //[darwin] compile-flags: --target aarch64-apple-darwin //[windows] compile-flags: --target aarch64-pc-windows-msvc //[linux] needs-llvm-components: aarch64 //[darwin] needs-llvm-components: aarch64 //[windows] needs-llvm-components: aarch64 #![feature(no_core, lang_items)] #![crate_type = "lib"] #![no_core] #[lang="sized"] trait Sized { } #[lang="freeze"] trait Freeze { } #[lang="copy"] trait Copy { } // Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. #[repr(C)] pub struct Align8 { pub a: u64, pub b: u64, } // repr(transparent), so same as above. #[repr(transparent)] pub struct Transparent8 { a: Align8 } // Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. #[repr(C)] pub struct Wrapped8 { a: Align8, } extern "C" { // linux: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) // darwin: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) // windows: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) fn test_8(a: Align8, b: Transparent8, c: Wrapped8); } // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. // EXCEPT on Linux, where there's a special case to use its unadjusted alignment, // making it the same as `Align8`, so it's be passed as `[i64 x 2]`. #[repr(C)] #[repr(align(16))] pub struct Align16 { pub a: u64, pub b: u64, } // repr(transparent), so same as above. #[repr(transparent)] pub struct Transparent16 { a: Align16 } // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. // On Linux, the "unadjustedness" doesn't recurse into fields, so this is passed as `i128`. #[repr(C)] pub struct Wrapped16 { pub a: Align16, } extern "C" { // linux: declare void @test_16([2 x i64], [2 x i64], i128) // darwin: declare void @test_16(i128, i128, i128) // windows: declare void @test_16(i128, i128, i128) fn test_16(a: Align16, b: Transparent16, c: Wrapped16); } // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. #[repr(C)] pub struct I128 { pub a: i128, } // repr(transparent), so same as above. #[repr(transparent)] pub struct TransparentI128 { a: I128 } // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. #[repr(C)] pub struct WrappedI128 { pub a: I128 } extern "C" { // linux: declare void @test_i128(i128, i128, i128) // darwin: declare void @test_i128(i128, i128, i128) // windows: declare void @test_i128(i128, i128, i128) fn test_i128(a: I128, b: TransparentI128, c: WrappedI128); } // Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. // Note that the Linux special case does not apply, because packing is not considered "adjustment". #[repr(C)] #[repr(packed)] pub struct Packed { pub a: i128, } // repr(transparent), so same as above. #[repr(transparent)] pub struct TransparentPacked { a: Packed } // Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. #[repr(C)] pub struct WrappedPacked { pub a: Packed } extern "C" { // linux: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) // darwin: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) // windows: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) fn test_packed(a: Packed, b: TransparentPacked, c: WrappedPacked); } pub unsafe fn main( a1: Align8, a2: Transparent8, a3: Wrapped8, b1: Align16, b2: Transparent16, b3: Wrapped16, c1: I128, c2: TransparentI128, c3: WrappedI128, d1: Packed, d2: TransparentPacked, d3: WrappedPacked, ) { test_8(a1, a2, a3); test_16(b1, b2, b3); test_i128(c1, c2, c3); test_packed(d1, d2, d3); }