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.
This commit is contained in:
msizanoen 2023-09-03 15:58:21 +07:00
parent ae9c330629
commit 751ecde064
3 changed files with 23 additions and 0 deletions

View File

@ -1118,6 +1118,10 @@ where
fn is_unit(this: TyAndLayout<'tcx>) -> bool {
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.

View File

@ -89,6 +89,17 @@ where
}
FieldsShape::Union(_) => {
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);
}
}

View File

@ -66,6 +66,7 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
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 is_transparent(this: TyAndLayout<'a, Self>) -> bool;
}
impl<'a, Ty> TyAndLayout<'a, Ty> {
@ -136,6 +137,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
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
where
Ty: TyAbiInterface<'a, C>,