From 751ecde0640f1d079515964e72e2646e82cb25f4 Mon Sep 17 00:00:00 2001
From: msizanoen <msizanoen@qtmlabs.xyz>
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<T>` 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 9a0e72d7b64..8b425ce0267 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 d90dce2a087..93a2045632a 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 636adcf6b17..74fe98920c4 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<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>,

From 4d4c13bbd6584fea9972da5bbbecfa51285dbe68 Mon Sep 17 00:00:00 2001
From: msizanoen <msizanoen@qtmlabs.xyz>
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 b3e75bb8233..d4f42cdda97 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>);
         }
     };