diff options
| author | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2023-05-20 16:11:09 -0400 |
|---|---|---|
| committer | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2023-07-10 19:19:38 -0400 |
| commit | ed317e4a479b4bacf102188445d03fabfb81a2c5 (patch) | |
| tree | 6665df282145b0592ee265f42564bb09218dcd59 /compiler/rustc_target/src | |
| parent | 7089321c6deabb3c25cf0ec829ca209f77b8ee5a (diff) | |
| download | rust-ed317e4a479b4bacf102188445d03fabfb81a2c5.tar.gz rust-ed317e4a479b4bacf102188445d03fabfb81a2c5.zip | |
i686-windows: pass arguments with requested alignment > 4 indirectly
Diffstat (limited to 'compiler/rustc_target/src')
| -rw-r--r-- | compiler/rustc_target/src/abi/call/x86.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/mod.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_target/src/lib.rs | 1 |
3 files changed, 34 insertions, 4 deletions
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index d2c604fafa6..dd52b3cb520 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -54,7 +54,31 @@ where continue; } - if arg.layout.is_aggregate() { + // FIXME: MSVC 2015+ will pass the first 3 vector arguments in [XYZ]MM0-2 + // See https://reviews.llvm.org/D72114 for Clang behavior + + let t = cx.target_spec(); + let align_4 = Align::from_bytes(4).unwrap(); + let align_16 = Align::from_bytes(16).unwrap(); + + if t.is_like_msvc + && arg.layout.is_adt() + && let Some(requested_align) = arg.layout.repr_options().align + && requested_align > align_4 + { + // MSVC has special rules for overaligned arguments: https://reviews.llvm.org/D72114. + // Summarized here: + // - Arguments with _requested_ alignment > 4 are passed indirectly. + // - For backwards compatibility, arguments with natural alignment > 4 are still passed + // on stack (via `byval`). For example, this includes `double`, `int64_t`, + // and structs containing them, provided they lack an explicit alignment attribute. + assert!(arg.layout.align.abi >= requested_align, + "abi alignment {:?} less than requested alignment {:?}", + arg.layout.align.abi, + requested_align + ); + arg.make_indirect(); + } else if arg.layout.is_aggregate() { // We need to compute the alignment of the `byval` argument. The rules can be found in // `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized // here, they are: @@ -87,9 +111,6 @@ where } } - let t = cx.target_spec(); - let align_4 = Align::from_bytes(4).unwrap(); - let align_16 = Align::from_bytes(16).unwrap(); let byval_align = if arg.layout.align.abi < align_4 { // (1.) align_4 diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 589cd3cf96b..aecf8b339f0 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -55,6 +55,7 @@ pub trait TyAbiInterface<'a, C>: Sized { fn is_never(this: TyAndLayout<'a, Self>) -> bool; fn is_tuple(this: TyAndLayout<'a, Self>) -> bool; fn is_unit(this: TyAndLayout<'a, Self>) -> bool; + fn repr_options(this: TyAndLayout<'a, Self>) -> ReprOptions; } impl<'a, Ty> TyAndLayout<'a, Ty> { @@ -125,6 +126,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty::is_unit(self) } + pub fn repr_options<C>(self) -> ReprOptions + where + Ty: TyAbiInterface<'a, C>, + { + Ty::repr_options(self) + } + pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size where Ty: TyAbiInterface<'a, C>, diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index a7b54766bc6..3307244a217 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -12,6 +12,7 @@ #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] #![feature(iter_intersperse)] +#![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] |
