From 751ecde0640f1d079515964e72e2646e82cb25f4 Mon Sep 17 00:00:00 2001 From: msizanoen Date: Sun, 3 Sep 2023 15:58:21 +0700 Subject: [PATCH 1/2] rustc_target/riscv: Fix passing of transparent unions with only one non-ZST member This ensures that `MaybeUninit` has the same ABI as `T` when passed through an `extern "C"` function. Fixes https://github.com/rust-lang/rust/issues/115481. --- compiler/rustc_middle/src/ty/layout.rs | 4 ++++ compiler/rustc_target/src/abi/call/riscv.rs | 11 +++++++++++ compiler/rustc_target/src/abi/mod.rs | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 9a0e72d7b640a..8b425ce0267d2 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -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. diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index d90dce2a08785..93a2045632a84 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -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); } } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 636adcf6b178d..74fe98920c459 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -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(self) -> bool + where + Ty: TyAbiInterface<'a, C>, + { + Ty::is_transparent(self) + } + pub fn offset_of_subfield(self, cx: &C, indices: impl Iterator) -> Size where Ty: TyAbiInterface<'a, C>, From 4d4c13bbd6584fea9972da5bbbecfa51285dbe68 Mon Sep 17 00:00:00 2001 From: msizanoen Date: Tue, 19 Sep 2023 12:22:45 +0200 Subject: [PATCH 2/2] tests/ui/abi: Enable repr(transparent) union ABI tests on RISC-V --- tests/ui/abi/compatibility.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index b3e75bb8233e3..d4f42cdda97a7 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -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 { @@ -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>); } };