2024-03-08 22:11:27 +00:00
|
|
|
// ignore-tidy-linelength
|
|
|
|
//@ revisions:i686-linux x86_64-linux
|
|
|
|
|
2023-08-25 12:52:51 +00:00
|
|
|
//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu -C panic=abort
|
2024-03-08 22:11:27 +00:00
|
|
|
//@[i686-linux] needs-llvm-components: x86
|
2023-08-25 12:52:51 +00:00
|
|
|
//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu -C panic=abort
|
2024-03-08 22:11:27 +00:00
|
|
|
//@[x86_64-linux] needs-llvm-components: x86
|
|
|
|
|
|
|
|
// Tests that we correctly copy arguments into allocas when the alignment of the byval argument
|
|
|
|
// is different from the alignment of the Rust type.
|
|
|
|
|
|
|
|
// For the following test cases:
|
|
|
|
// All of the `*_decreases_alignment` functions should codegen to a direct call, since the
|
|
|
|
// alignment is already sufficient.
|
|
|
|
// All off the `*_increases_alignment` functions should copy the argument to an alloca
|
|
|
|
// on i686-unknown-linux-gnu, since the alignment needs to be increased, and should codegen
|
|
|
|
// to a direct call on x86_64-unknown-linux-gnu, where byval alignment matches Rust alignment.
|
|
|
|
|
|
|
|
#![feature(no_core, lang_items)]
|
|
|
|
#![crate_type = "lib"]
|
|
|
|
#![no_std]
|
|
|
|
#![no_core]
|
|
|
|
#![allow(non_camel_case_types)]
|
|
|
|
|
|
|
|
#[lang = "sized"]
|
|
|
|
trait Sized {}
|
|
|
|
#[lang = "freeze"]
|
|
|
|
trait Freeze {}
|
|
|
|
#[lang = "copy"]
|
|
|
|
trait Copy {}
|
|
|
|
|
|
|
|
// This type has align 1 in Rust, but as a byval argument on i686-linux, it will have align 4.
|
|
|
|
#[repr(C)]
|
|
|
|
#[repr(packed)]
|
|
|
|
struct Align1 {
|
|
|
|
x: u128,
|
|
|
|
y: u128,
|
|
|
|
z: u128,
|
|
|
|
}
|
|
|
|
|
|
|
|
// This type has align 16 in Rust, but as a byval argument on i686-linux, it will have align 4.
|
|
|
|
#[repr(C)]
|
|
|
|
#[repr(align(16))]
|
|
|
|
struct Align16 {
|
|
|
|
x: u128,
|
|
|
|
y: u128,
|
|
|
|
z: u128,
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
fn extern_c_align1(x: Align1);
|
|
|
|
fn extern_c_align16(x: Align16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @rust_to_c_increases_alignment
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe fn rust_to_c_increases_alignment(x: Align1) {
|
|
|
|
// i686-linux: start:
|
2024-02-24 05:48:20 +00:00
|
|
|
// i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 4
|
2024-03-08 22:11:27 +00:00
|
|
|
// i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 4 {{.*}}[[ALLOCA]], ptr {{.*}}align 1 {{.*}}%x
|
|
|
|
// i686-linux-NEXT: call void @extern_c_align1({{.+}} [[ALLOCA]])
|
|
|
|
|
|
|
|
// x86_64-linux: start:
|
|
|
|
// x86_64-linux-NEXT: call void @extern_c_align1
|
|
|
|
extern_c_align1(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @rust_to_c_decreases_alignment
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe fn rust_to_c_decreases_alignment(x: Align16) {
|
|
|
|
// CHECK: start:
|
|
|
|
// CHECK-NEXT: call void @extern_c_align16
|
|
|
|
extern_c_align16(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "Rust" {
|
|
|
|
fn extern_rust_align1(x: Align1);
|
|
|
|
fn extern_rust_align16(x: Align16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @c_to_rust_decreases_alignment
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn c_to_rust_decreases_alignment(x: Align1) {
|
|
|
|
// CHECK: start:
|
|
|
|
// CHECK-NEXT: call void @extern_rust_align1
|
|
|
|
extern_rust_align1(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @c_to_rust_increases_alignment
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn c_to_rust_increases_alignment(x: Align16) {
|
|
|
|
// i686-linux: start:
|
2024-02-24 05:48:20 +00:00
|
|
|
// i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16
|
2024-03-08 22:11:27 +00:00
|
|
|
// i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0
|
|
|
|
// i686-linux-NEXT: call void @extern_rust_align16({{.+}} [[ALLOCA]])
|
|
|
|
|
|
|
|
// x86_64-linux: start:
|
|
|
|
// x86_64-linux-NEXT: call void @extern_rust_align16
|
|
|
|
extern_rust_align16(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "Rust" {
|
|
|
|
fn extern_rust_ref_align1(x: &Align1);
|
|
|
|
fn extern_rust_ref_align16(x: &Align16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @c_to_rust_ref_decreases_alignment
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn c_to_rust_ref_decreases_alignment(x: Align1) {
|
|
|
|
// CHECK: start:
|
|
|
|
// CHECK-NEXT: call void @extern_rust_ref_align1
|
|
|
|
extern_rust_ref_align1(&x);
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @c_to_rust_ref_increases_alignment
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn c_to_rust_ref_increases_alignment(x: Align16) {
|
|
|
|
// i686-linux: start:
|
2024-02-24 05:48:20 +00:00
|
|
|
// i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16
|
2024-03-08 22:11:27 +00:00
|
|
|
// i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0
|
|
|
|
// i686-linux-NEXT: call void @extern_rust_ref_align16({{.+}} [[ALLOCA]])
|
|
|
|
|
|
|
|
// x86_64-linux: start:
|
|
|
|
// x86_64-linux-NEXT: call void @extern_rust_ref_align16
|
|
|
|
extern_rust_ref_align16(&x);
|
|
|
|
}
|