| // Test that structs aligned to 128 bits are passed with the correct ABI on aarch64. | |
| //@ add-minicore | |
| //@ revisions: linux darwin win | |
| //@[linux] compile-flags: --target aarch64-unknown-linux-gnu | |
| //@[darwin] compile-flags: --target aarch64-apple-darwin | |
| //@[win] compile-flags: --target aarch64-pc-windows-msvc | |
| //@[linux] needs-llvm-components: aarch64 | |
| //@[darwin] needs-llvm-components: aarch64 | |
| //@[win] needs-llvm-components: aarch64 | |
| #![feature(no_core, lang_items)] | |
| #![crate_type = "lib"] | |
| #![no_core] | |
| extern crate minicore; | |
| use minicore::*; | |
| // 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]) | |
| // win: 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) | |
| // win: 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) | |
| // win: 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]) | |
| // win: 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); | |
| } |