mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-04 03:07:25 +00:00

alignment of `byval` on x86 in the process. Commit 88e4d2c2918428d55e34cd57c11279ea839c8822 from five years ago removed support for alignment on indirectly-passed arguments because of problems with the `i686-pc-windows-msvc` target. Unfortunately, the `memcpy` optimizations I recently added to LLVM 16 depend on this to forward `memcpy`s. This commit attempts to fix the problems with `byval` parameters on that target and now correctly adds the `align` attribute. The problem is summarized in [this comment] by @eddyb. Briefly, 32-bit x86 has special alignment rules for `byval` parameters: for the most part, their alignment is forced to 4. This is not well-documented anywhere but in the Clang source. I looked at the logic in Clang `TargetInfo.cpp` and tried to replicate it here. The relevant methods in that file are `X86_32ABIInfo::getIndirectResult()` and `X86_32ABIInfo::getTypeStackAlignInBytes()`. The `align` parameter attribute for `byval` parameters in LLVM must match the platform ABI, or miscompilations will occur. Note that this doesn't use the approach suggested by eddyb, because I felt it was overkill to store the alignment in `on_stack` when special handling is really only needed for 32-bit x86. As a side effect, this should fix #80127, because it will make the `align` parameter attribute for `byval` parameters match the platform ABI on LLVM x86-64. [this comment]: https://github.com/rust-lang/rust/pull/80822#issuecomment-829985417
57 lines
1.0 KiB
Rust
57 lines
1.0 KiB
Rust
// ignore-x86
|
|
// ignore-aarch64
|
|
// ignore-aarch64_be
|
|
// ignore-arm
|
|
// ignore-armeb
|
|
// ignore-avr
|
|
// ignore-bpfel
|
|
// ignore-bpfeb
|
|
// ignore-hexagon
|
|
// ignore-mips
|
|
// ignore-mips64
|
|
// ignore-msp430
|
|
// ignore-powerpc64
|
|
// ignore-powerpc64le
|
|
// ignore-powerpc
|
|
// ignore-r600
|
|
// ignore-amdgcn
|
|
// ignore-sparc
|
|
// ignore-sparcv9
|
|
// ignore-sparcel
|
|
// ignore-s390x
|
|
// ignore-tce
|
|
// ignore-thumb
|
|
// ignore-thumbeb
|
|
// ignore-xcore
|
|
// ignore-nvptx
|
|
// ignore-nvptx64
|
|
// ignore-le32
|
|
// ignore-le64
|
|
// ignore-amdil
|
|
// ignore-amdil64
|
|
// ignore-hsail
|
|
// ignore-hsail64
|
|
// ignore-spir
|
|
// ignore-spir64
|
|
// ignore-kalimba
|
|
// ignore-shave
|
|
//
|
|
// Tests that `byval` alignment is properly specified (#80127).
|
|
// The only targets that use `byval` are m68k, wasm, x86-64, and x86. Note that
|
|
// x86 has special rules (see #103830), and it's therefore ignored here.
|
|
|
|
#[repr(C)]
|
|
#[repr(align(16))]
|
|
struct Foo {
|
|
a: [i32; 16],
|
|
}
|
|
|
|
extern "C" {
|
|
// CHECK: declare void @f({{.*}}byval(%Foo) align 16{{.*}})
|
|
fn f(foo: Foo);
|
|
}
|
|
|
|
pub fn main() {
|
|
unsafe { f(Foo { a: [1; 16] }) }
|
|
}
|