| //@ add-minicore | |
| //@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 | |
| // | |
| //@ revisions: linux eabi watchos | |
| //@[linux] compile-flags: --target armv7-unknown-linux-gnueabihf | |
| //@[eabi] compile-flags: --target armv7r-none-eabi | |
| //@[watchos] compile-flags: --target armv7k-apple-watchos | |
| // | |
| //@ needs-llvm-components: arm | |
| // Test that structs are passed with the correct register alignment. | |
| #![feature(no_core, lang_items)] | |
| #![crate_type = "lib"] | |
| #![no_core] | |
| extern crate minicore; | |
| use minicore::*; | |
| #[repr(C)] | |
| pub struct Natural { | |
| pub a: u32, | |
| pub b: u32, | |
| } | |
| // linux: define void @test_natural([2 x i32] %0) | |
| // eabi: define dso_local void @test_natural([2 x i32] %0) | |
| // watchos: define void @test_natural([2 x i32] %0) | |
| #[unsafe(no_mangle)] | |
| pub extern "C" fn test_natural(a: Natural) { | |
| hint::black_box(a); | |
| } | |
| #[repr(C)] | |
| pub struct HasU64 { | |
| pub a: u64, | |
| } | |
| // linux: define void @test_has_u64(i64 %0) | |
| // eabi: define dso_local void @test_has_u64(i64 %0) | |
| // watchos: define void @test_has_u64(i64 %0) | |
| #[unsafe(no_mangle)] | |
| pub extern "C" fn test_has_u64(a: HasU64) { | |
| hint::black_box(a); | |
| } | |
| #[repr(C)] | |
| #[repr(align(8))] | |
| pub struct Align8 { | |
| pub a: u32, | |
| pub b: u32, | |
| } | |
| #[repr(transparent)] | |
| pub struct Transparent8 { | |
| a: Align8, | |
| } | |
| // Here watchOS deviates from the others. On linux and eabi, the natural alignment of the struct | |
| // contents is used, and the alignment modifier of the struct is not considered for ABI purposes. | |
| // watchOS does respect the alignment annotation for register allocation. | |
| // | |
| // linux: define void @test_8([2 x i32] %0, [2 x i32] %1) | |
| // eabi: define dso_local void @test_8([2 x i32] %0, [2 x i32] %1) | |
| // watchos: define void @test_8(i64 %0, i64 %1) | |
| #[unsafe(no_mangle)] | |
| pub extern "C" fn test_8(a: Align8, b: Transparent8) { | |
| hint::black_box(a); | |
| hint::black_box(b); | |
| } | |
| #[repr(C)] | |
| #[repr(align(16))] | |
| pub struct Align16 { | |
| pub a: u32, | |
| pub b: u32, | |
| } | |
| #[repr(transparent)] | |
| pub struct Transparent16 { | |
| a: Align16, | |
| } | |
| #[repr(C)] | |
| pub struct Wrapped16 { | |
| pub a: Align16, | |
| } | |
| // Wrapping resets the unadjusted alignment. | |
| // | |
| // linux: define void @test_16([4 x i32] %0, [4 x i32] %1, [2 x i64] %2) | |
| // eabi: define dso_local void @test_16([4 x i32] %0, [4 x i32] %1, [2 x i64] %2) | |
| // watchos: define void @test_16([2 x i64] %0, [2 x i64] %1, [2 x i64] %2) | |
| #[unsafe(no_mangle)] | |
| pub extern "C" fn test_16(a: Align16, b: Transparent16, c: Wrapped16) { | |
| hint::black_box(a); | |
| hint::black_box(b); | |
| hint::black_box(c); | |
| } | |
| // Packing is different, the alignment is 1 across targets. | |
| #[repr(C)] | |
| #[repr(packed)] | |
| pub struct Packed { | |
| pub a: u8, | |
| pub b: u64, | |
| } | |
| // linux: define void @test_packed([3 x i32] %0) | |
| // eabi: define dso_local void @test_packed([3 x i32] %0) | |
| // watchos: define void @test_packed([3 x i32] %0) | |
| #[unsafe(no_mangle)] | |
| pub extern "C" fn test_packed(a: Packed) { | |
| hint::black_box(a); | |
| } |