Rollup merge of #115499 - msizanoen1:riscv-fix-transparent-union-abi, r=bjorn3
rustc_target/riscv: Fix passing of transparent unions with only one non-ZST member This ensures that `MaybeUninit<T>` has the same ABI as `T` when passed through an `extern "C"` function. Fixes https://github.com/rust-lang/rust/issues/115481. r? `@RalfJung`
This commit is contained in:
commit
edd7be59da
4 changed files with 24 additions and 2 deletions
|
@ -1118,6 +1118,10 @@ where
|
||||||
fn is_unit(this: TyAndLayout<'tcx>) -> bool {
|
fn is_unit(this: TyAndLayout<'tcx>) -> bool {
|
||||||
matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
|
matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_transparent(this: TyAndLayout<'tcx>) -> bool {
|
||||||
|
matches!(this.ty.kind(), ty::Adt(def, _) if def.repr().transparent())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates whether a function's ABI can unwind or not.
|
/// Calculates whether a function's ABI can unwind or not.
|
||||||
|
|
|
@ -89,6 +89,17 @@ where
|
||||||
}
|
}
|
||||||
FieldsShape::Union(_) => {
|
FieldsShape::Union(_) => {
|
||||||
if !arg_layout.is_zst() {
|
if !arg_layout.is_zst() {
|
||||||
|
if arg_layout.is_transparent() {
|
||||||
|
let non_1zst_elem = arg_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in non-ZST repr(transparent) union").1;
|
||||||
|
return should_use_fp_conv_helper(
|
||||||
|
cx,
|
||||||
|
&non_1zst_elem,
|
||||||
|
xlen,
|
||||||
|
flen,
|
||||||
|
field1_kind,
|
||||||
|
field2_kind,
|
||||||
|
);
|
||||||
|
}
|
||||||
return Err(CannotUseFpConv);
|
return Err(CannotUseFpConv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
|
||||||
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
|
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
|
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
|
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
|
fn is_transparent(this: TyAndLayout<'a, Self>) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
|
@ -136,6 +137,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
Ty::is_unit(self)
|
Ty::is_unit(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_transparent<C>(self) -> bool
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C>,
|
||||||
|
{
|
||||||
|
Ty::is_transparent(self)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
|
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
|
||||||
where
|
where
|
||||||
Ty: TyAbiInterface<'a, C>,
|
Ty: TyAbiInterface<'a, C>,
|
||||||
|
|
|
@ -10,7 +10,6 @@ use std::ptr::NonNull;
|
||||||
// Hence there are `cfg` throughout this test to disable parts of it on those targets.
|
// Hence there are `cfg` throughout this test to disable parts of it on those targets.
|
||||||
// sparc64: https://github.com/rust-lang/rust/issues/115336
|
// sparc64: https://github.com/rust-lang/rust/issues/115336
|
||||||
// mips64: https://github.com/rust-lang/rust/issues/115404
|
// mips64: https://github.com/rust-lang/rust/issues/115404
|
||||||
// riscv64: https://github.com/rust-lang/rust/issues/115481
|
|
||||||
// loongarch64: https://github.com/rust-lang/rust/issues/115509
|
// loongarch64: https://github.com/rust-lang/rust/issues/115509
|
||||||
|
|
||||||
macro_rules! assert_abi_compatible {
|
macro_rules! assert_abi_compatible {
|
||||||
|
@ -110,7 +109,7 @@ macro_rules! test_transparent {
|
||||||
test_abi_compatible!(wrap1, $t, Wrapper1<$t>);
|
test_abi_compatible!(wrap1, $t, Wrapper1<$t>);
|
||||||
test_abi_compatible!(wrap2, $t, Wrapper2<$t>);
|
test_abi_compatible!(wrap2, $t, Wrapper2<$t>);
|
||||||
test_abi_compatible!(wrap3, $t, Wrapper3<$t>);
|
test_abi_compatible!(wrap3, $t, Wrapper3<$t>);
|
||||||
#[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))]
|
#[cfg(not(target_arch = "loongarch64"))]
|
||||||
test_abi_compatible!(wrap4, $t, WrapperUnion<$t>);
|
test_abi_compatible!(wrap4, $t, WrapperUnion<$t>);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue