summaryrefslogtreecommitdiffstats
path: root/tests/codegen/align-byval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen/align-byval.rs')
-rw-r--r--tests/codegen/align-byval.rs342
1 files changed, 342 insertions, 0 deletions
diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs
new file mode 100644
index 000000000..e2446e02e
--- /dev/null
+++ b/tests/codegen/align-byval.rs
@@ -0,0 +1,342 @@
+// ignore-tidy-linelength
+// revisions:m68k wasm x86_64-linux x86_64-windows i686-linux i686-windows
+
+//[m68k] compile-flags: --target m68k-unknown-linux-gnu
+//[m68k] needs-llvm-components: m68k
+//[wasm] compile-flags: --target wasm32-unknown-emscripten
+//[wasm] needs-llvm-components: webassembly
+//[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64-linux] needs-llvm-components: x86
+//[x86_64-windows] compile-flags: --target x86_64-pc-windows-msvc
+//[x86_64-windows] needs-llvm-components: x86
+//[i686-linux] compile-flags: --target i686-unknown-linux-gnu
+//[i686-linux] needs-llvm-components: x86
+//[i686-windows] compile-flags: --target i686-pc-windows-msvc
+//[i686-windows] needs-llvm-components: x86
+
+// Tests that `byval` alignment is properly specified (#80127).
+// The only targets that use `byval` are m68k, wasm, x86-64, and x86.
+// Note also that Windows mandates a by-ref ABI here, so it does not use byval.
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
+
+impl Copy for i32 {}
+impl Copy for i64 {}
+
+// This struct can be represented as a pair, so it exercises the OperandValue::Pair
+// codepath in `codegen_argument`.
+#[repr(C)]
+pub struct NaturalAlign1 {
+ a: i8,
+ b: i8,
+}
+
+// This struct cannot be represented as an immediate, so it exercises the OperandValue::Ref
+// codepath in `codegen_argument`.
+#[repr(C)]
+pub struct NaturalAlign2 {
+ a: [i16; 16],
+ b: i16,
+}
+
+#[repr(C)]
+#[repr(align(4))]
+pub struct ForceAlign4 {
+ a: [i8; 16],
+ b: i8,
+}
+
+// On i686-windows, this is passed on stack using `byval`
+#[repr(C)]
+pub struct NaturalAlign8 {
+ a: i64,
+ b: i64,
+ c: i64
+}
+
+// On i686-windows, this is passed by reference (because alignment is >4 and requested/forced),
+// even though it has the exact same layout as `NaturalAlign8`!
+#[repr(C)]
+#[repr(align(8))]
+pub struct ForceAlign8 {
+ a: i64,
+ b: i64,
+ c: i64
+}
+
+// On i686-windows, this is passed on stack, because requested alignment is <=4.
+#[repr(C)]
+#[repr(align(4))]
+pub struct LowerFA8 {
+ a: i64,
+ b: i64,
+ c: i64
+}
+
+// On i686-windows, this is passed by reference, because it contains a field with
+// requested/forced alignment.
+#[repr(C)]
+pub struct WrappedFA8 {
+ a: ForceAlign8
+}
+
+// On i686-windows, this has the same ABI as ForceAlign8, i.e. passed by reference.
+#[repr(transparent)]
+pub struct TransparentFA8 {
+ _0: (),
+ a: ForceAlign8
+}
+
+#[repr(C)]
+#[repr(align(16))]
+pub struct ForceAlign16 {
+ a: [i32; 16],
+ b: i8
+}
+
+// CHECK-LABEL: @call_na1
+#[no_mangle]
+pub unsafe fn call_na1(x: NaturalAlign1) {
+ // CHECK: start:
+
+ // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1
+ // m68k: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]])
+
+ // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1
+ // wasm: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]])
+
+ // x86_64-linux: call void @natural_align_1(i16
+
+ // x86_64-windows: call void @natural_align_1(i16
+
+ // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4
+ // i686-linux: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]])
+
+ // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4
+ // i686-windows: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]])
+ natural_align_1(x);
+}
+
+// CHECK-LABEL: @call_na2
+#[no_mangle]
+pub unsafe fn call_na2(x: NaturalAlign2) {
+ // CHECK: start:
+
+ // m68k-NEXT: call void @natural_align_2
+ // wasm-NEXT: call void @natural_align_2
+ // x86_64-linux-NEXT: call void @natural_align_2
+ // x86_64-windows-NEXT: call void @natural_align_2
+
+ // i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
+ // i686-linux: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
+
+ // i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
+ // i686-windows: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
+ natural_align_2(x);
+}
+
+// CHECK-LABEL: @call_fa4
+#[no_mangle]
+pub unsafe fn call_fa4(x: ForceAlign4) {
+ // CHECK: start:
+ // CHECK-NEXT: call void @force_align_4
+ force_align_4(x);
+}
+
+// CHECK-LABEL: @call_na8
+#[no_mangle]
+pub unsafe fn call_na8(x: NaturalAlign8) {
+ // CHECK: start:
+ // CHECK-NEXT: call void @natural_align_8
+ natural_align_8(x);
+}
+
+// CHECK-LABEL: @call_fa8
+#[no_mangle]
+pub unsafe fn call_fa8(x: ForceAlign8) {
+ // CHECK: start:
+ // CHECK-NEXT: call void @force_align_8
+ force_align_8(x);
+}
+
+// CHECK-LABEL: @call_lfa8
+#[no_mangle]
+pub unsafe fn call_lfa8(x: LowerFA8) {
+ // CHECK: start:
+ // CHECK-NEXT: call void @lower_fa8
+ lower_fa8(x);
+}
+
+// CHECK-LABEL: @call_wfa8
+#[no_mangle]
+pub unsafe fn call_wfa8(x: WrappedFA8) {
+ // CHECK: start:
+ // CHECK-NEXT: call void @wrapped_fa8
+ wrapped_fa8(x);
+}
+
+// CHECK-LABEL: @call_tfa8
+#[no_mangle]
+pub unsafe fn call_tfa8(x: TransparentFA8) {
+ // CHECK: start:
+ // CHECK-NEXT: call void @transparent_fa8
+ transparent_fa8(x);
+}
+
+// CHECK-LABEL: @call_fa16
+#[no_mangle]
+pub unsafe fn call_fa16(x: ForceAlign16) {
+ // CHECK: start:
+ // CHECK-NEXT: call void @force_align_16
+ force_align_16(x);
+}
+
+extern "C" {
+ // m68k: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}})
+
+ // wasm: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}})
+
+ // x86_64-linux: declare void @natural_align_1(i16)
+
+ // x86_64-windows: declare void @natural_align_1(i16)
+
+ // i686-linux: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}})
+
+ // i686-windows: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}})
+ fn natural_align_1(x: NaturalAlign1);
+
+ // m68k: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+
+ // wasm: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+
+ // x86_64-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+
+ // x86_64-windows: declare void @natural_align_2(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 2{{.*}})
+
+ // i686-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
+
+ // i686-windows: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
+ fn natural_align_2(x: NaturalAlign2);
+
+ // m68k: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+ // wasm: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+ // x86_64-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+ // x86_64-windows: declare void @force_align_4(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 4{{.*}})
+
+ // i686-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+
+ // i686-windows: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+ fn force_align_4(x: ForceAlign4);
+
+ // m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+
+ // wasm: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
+
+ // x86_64-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
+
+ // x86_64-windows: declare void @natural_align_8(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 8{{.*}})
+
+ // i686-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+
+ // i686-windows: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+ fn natural_align_8(x: NaturalAlign8);
+
+ // m68k: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+
+ // wasm: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+
+ // x86_64-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+
+ // x86_64-windows: declare void @force_align_8(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 8{{.*}})
+
+ // i686-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 4{{.*}})
+
+ // i686-windows: declare void @force_align_8(
+ // i686-windows-NOT: byval
+ // i686-windows-SAME: align 8{{.*}})
+ fn force_align_8(x: ForceAlign8);
+
+ // m68k: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+
+ // wasm: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
+
+ // x86_64-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
+
+ // x86_64-windows: declare void @lower_fa8(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 8{{.*}})
+
+ // i686-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+
+ // i686-windows: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+ fn lower_fa8(x: LowerFA8);
+
+ // m68k: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+
+ // wasm: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+
+ // x86_64-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+
+ // x86_64-windows: declare void @wrapped_fa8(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 8{{.*}})
+
+ // i686-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}})
+
+ // i686-windows: declare void @wrapped_fa8(
+ // i686-windows-NOT: byval
+ // i686-windows-SAME: align 8{{.*}})
+ fn wrapped_fa8(x: WrappedFA8);
+
+ // m68k: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+
+ // wasm: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+
+ // x86_64-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+
+ // x86_64-windows: declare void @transparent_fa8(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 8{{.*}})
+
+ // i686-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 4{{.*}})
+
+ // i686-windows: declare void @transparent_fa8(
+ // i686-windows-NOT: byval
+ // i686-windows-SAME: align 8{{.*}})
+ fn transparent_fa8(x: TransparentFA8);
+
+ // m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+
+ // wasm: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+
+ // x86_64-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+
+ // x86_64-windows: declare void @force_align_16(
+ // x86_64-windows-NOT: byval
+ // x86_64-windows-SAME: align 16{{.*}})
+
+ // i686-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 4{{.*}})
+
+ // i686-windows: declare void @force_align_16(
+ // i686-windows-NOT: byval
+ // i686-windows-SAME: align 16{{.*}})
+ fn force_align_16(x: ForceAlign16);
+}