Skip to content

Commit

Permalink
Rollup merge of #115499 - msizanoen1:riscv-fix-transparent-union-abi,…
Browse files Browse the repository at this point in the history
… 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 #115481.

r? `@RalfJung`
  • Loading branch information
GuillaumeGomez authored Sep 19, 2023
2 parents 7a27acf + 4d4c13b commit edd7be5
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 2 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_target/src/abi/call/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_target/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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>,
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/abi/compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use std::ptr::NonNull;
// Hence there are `cfg` throughout this test to disable parts of it on those targets.
// sparc64: https://github.com/rust-lang/rust/issues/115336
// 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

macro_rules! assert_abi_compatible {
Expand Down Expand Up @@ -110,7 +109,7 @@ macro_rules! test_transparent {
test_abi_compatible!(wrap1, $t, Wrapper1<$t>);
test_abi_compatible!(wrap2, $t, Wrapper2<$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>);
}
};
Expand Down

0 comments on commit edd7be5

Please sign in to comment.