diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 5de9a8dfa7ac1..ab9170b2aaa01 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -449,9 +449,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { // program-invisible so can't possibly capture attrs.set(ArgAttribute::NoAlias).set(ArgAttribute::NoCapture).set(ArgAttribute::NonNull); attrs.pointee_size = self.layout.size; - // FIXME(eddyb) We should be doing this, but at least on - // i686-pc-windows-msvc, it results in wrong stack offsets. - // attrs.pointee_align = Some(self.layout.align.abi); + attrs.pointee_align = Some(self.layout.align.abi); let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new()); diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 3511c7c5185ee..8a0e680a23fa2 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -54,7 +54,7 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { pub fn mutable_borrow(_: &mut i32) { } -// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32) %_1) +// CHECK: @indirect_struct(%S* noalias nocapture align 4 dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) { } @@ -73,7 +73,7 @@ pub fn _box(x: Box) -> Box { x } -// CHECK: @struct_return(%S* noalias nocapture sret dereferenceable(32){{( %0)?}}) +// CHECK: @struct_return(%S* noalias nocapture sret align 4 dereferenceable(32){{( %0)?}}) #[no_mangle] pub fn struct_return() -> S { S { diff --git a/src/test/codegen/issue-80127-arg-align.rs b/src/test/codegen/issue-80127-arg-align.rs new file mode 100644 index 0000000000000..f07b4cf446da1 --- /dev/null +++ b/src/test/codegen/issue-80127-arg-align.rs @@ -0,0 +1,63 @@ +// ignore-tidy-linelength +// only-x86_64 + +// Regression test for issue 80127 +// Tests that we properly propagate apply a `#[repr(align)]` attribute on a struct +// to external function definitions involving parameters with that struct type + +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Copy, Clone)] +pub struct bar { + pub a: ::std::os::raw::c_ulong, + pub b: ::std::os::raw::c_ulong, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct baz { + pub a: bool, + pub b: ::std::os::raw::c_uint, +} + +extern "C" { + // CHECK: declare i32 @foo_func(i8*, i8*, i8*, i64, i1 zeroext, i64, i8*, %bar* noalias nocapture byval(%bar) align 16 dereferenceable(16), i8*, i8*, i8*, i8*, i8*) + pub fn foo_func( + a: *mut ::std::os::raw::c_void, + b: *mut ::std::os::raw::c_void, + c: *const ::std::os::raw::c_char, + d: ::std::os::raw::c_ulong, + e: bool, + f: baz, + g: *mut ::std::os::raw::c_void, + h: bar, + i: *mut ::std::os::raw::c_void, + j: *mut ::std::os::raw::c_void, + k: *mut ::std::os::raw::c_void, + l: *mut ::std::os::raw::c_void, + m: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} + +fn main() { + let f = baz { a: true, b: 67 }; + let h = bar { a: 0, b: 99 }; + let m = std::ffi::CString::new("Hello, world").unwrap(); + unsafe { + foo_func( + std::ptr::null_mut(), + std::ptr::null_mut(), + std::ptr::null_mut(), + 12, + true, + f, + std::ptr::null_mut(), + h, + std::ptr::null_mut(), + std::ptr::null_mut(), + std::ptr::null_mut(), + std::ptr::null_mut(), + m.as_ptr(), + ) + }; +} diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index f3f5202206ced..7f1503af933e7 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -52,7 +52,7 @@ pub struct BigPacked2 { #[no_mangle] pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array -// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]]) +// CHECK: call void %{{.*}}(%Array* noalias nocapture sret align 4 dereferenceable(32) [[ALLOCA]]) // CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct // go through an alloca rather than calling the function with an @@ -64,7 +64,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { #[no_mangle] pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 { // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array -// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]]) +// CHECK: call void %{{.*}}(%Array* noalias nocapture sret align 4 dereferenceable(32) [[ALLOCA]]) // CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct // go through an alloca rather than calling the function with an