about summary refs log tree commit diff
path: root/compiler/rustc_codegen_gcc
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-06-28 23:37:08 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2025-06-28 23:37:08 +0200
commitf8491b11f344222446a9bcd0c72b7bbb0834cdc0 (patch)
treed5ea49ead00ec3d34ecc6b7b50f0034705e5cc96 /compiler/rustc_codegen_gcc
parent7ba34c704529e7fcab80130c3fe40efe415d61b5 (diff)
parentb7091eca6d8eb0fe88b58cc9a7aec405d8de5b85 (diff)
downloadrust-f8491b11f344222446a9bcd0c72b7bbb0834cdc0.tar.gz
rust-f8491b11f344222446a9bcd0c72b7bbb0834cdc0.zip
Merge commit 'b7091eca6d8eb0fe88b58cc9a7aec405d8de5b85' into subtree-update_cg_gcc_2025-06-28
Diffstat (limited to 'compiler/rustc_codegen_gcc')
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/abi_test.rs65
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/main.rs8
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/test.rs9
-rw-r--r--compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch39
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs65
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs33
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs5
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs21
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt1
12 files changed, 150 insertions, 117 deletions
diff --git a/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs
new file mode 100644
index 00000000000..3c1531be27a
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs
@@ -0,0 +1,65 @@
+use std::ffi::OsStr;
+use std::path::Path;
+
+use crate::utils::run_command_with_output;
+
+fn show_usage() {
+    println!(
+        r#"
+`abi-test` command help:
+    --help                 : Show this help"#
+    );
+}
+
+pub fn run() -> Result<(), String> {
+    let mut args = std::env::args().skip(2);
+    // FractalFir: In the future, I'd like to add some more subcommands / options.
+    // So, this loop ought to stay for that purpose. It should also stay as a while loop(to parse args)
+    #[allow(clippy::never_loop, clippy::while_let_on_iterator)]
+    while let Some(arg) = args.next() {
+        match arg.as_str() {
+            "--help" => {
+                show_usage();
+                return Ok(());
+            }
+            _ => return Err(format!("Unknown option {arg:?}")),
+        }
+    }
+    // Ensure that we have a cloned version of abi-cafe on hand.
+    crate::utils::git_clone(
+        "https://github.com/Gankra/abi-cafe.git",
+        Some("clones/abi-cafe".as_ref()),
+        true,
+    )
+    .map_err(|err| (format!("Git clone failed with message: {err:?}!")))?;
+    // Configure abi-cafe to use the exact same rustc version we use - this is crucial.
+    // Otherwise, the concept of ABI compatibility becomes meanignless.
+    std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain")
+        .expect("Could not copy toolchain configs!");
+    // Get the backend path.
+    // We will use the *debug* build of the backend - it has more checks enabled.
+    let backend_path = std::path::absolute("target/debug/librustc_codegen_gcc.so").unwrap();
+    let backend_arg = format!("--add-rustc-codegen-backend=cg_gcc:{}", backend_path.display());
+    // Run ABI cafe using cargo.
+    let cmd: &[&dyn AsRef<OsStr>] = &[
+        &"cargo",
+        &"run",
+        &"--release",
+        &"--",
+        &backend_arg,
+        // Test rust-LLVM to Rust-GCC calls
+        &"--pairs",
+        &"rustc_calls_cg_gcc",
+        &"--pairs",
+        &"cg_gcc_calls_rustc",
+        // Test Rust-GCC to C calls
+        &"--pairs",
+        &"cg_gcc_calls_c",
+        &"--pairs",
+        &"c_calls_cg_gcc",
+    ];
+    // Run ABI cafe.
+    run_command_with_output(cmd, Some(Path::new("clones/abi-cafe")))?;
+
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs
index 078a4726ba8..ae975c94fff 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/main.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs
@@ -1,5 +1,6 @@
 use std::{env, process};
 
+mod abi_test;
 mod build;
 mod clean;
 mod clone_gcc;
@@ -12,7 +13,6 @@ mod rust_tools;
 mod rustc_info;
 mod test;
 mod utils;
-
 const BUILD_DIR: &str = "build";
 
 macro_rules! arg_error {
@@ -44,7 +44,8 @@ Commands:
         info      : Displays information about the build environment and project configuration.
         clone-gcc : Clones the GCC compiler from a specified source.
         fmt       : Runs rustfmt
-        fuzz      : Fuzzes `cg_gcc` using rustlantis"
+        fuzz      : Fuzzes `cg_gcc` using rustlantis
+        abi-test   : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM"
     );
 }
 
@@ -59,6 +60,7 @@ pub enum Command {
     Info,
     Fmt,
     Fuzz,
+    AbiTest,
 }
 
 fn main() {
@@ -77,6 +79,7 @@ fn main() {
         Some("test") => Command::Test,
         Some("info") => Command::Info,
         Some("clone-gcc") => Command::CloneGcc,
+        Some("abi-test") => Command::AbiTest,
         Some("fmt") => Command::Fmt,
         Some("fuzz") => Command::Fuzz,
         Some("--help") => {
@@ -102,6 +105,7 @@ fn main() {
         Command::CloneGcc => clone_gcc::run(),
         Command::Fmt => fmt::run(),
         Command::Fuzz => fuzz::run(),
+        Command::AbiTest => abi_test::run(),
     } {
         eprintln!("Command failed to run: {e}");
         process::exit(1);
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index bcaab0fb526..f1f31f83ca2 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -738,14 +738,7 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
     let path = get_sysroot_dir().join("sysroot_src/library/coretests");
     let _ = remove_dir_all(path.join("target"));
     // TODO(antoyo): run in release mode when we fix the failures.
-    // TODO(antoyo): remove the --skip f16::test_total_cmp when this issue is fixed:
-    // https://github.com/rust-lang/rust/issues/141503
-    run_cargo_command(
-        &[&"test", &"--", &"--skip", &"f16::test_total_cmp"],
-        Some(&path),
-        env,
-        args,
-    )?;
+    run_cargo_command(&[&"test"], Some(&path), env, args)?;
     Ok(())
 }
 
diff --git a/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch b/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch
deleted file mode 100644
index 39266e081ed..00000000000
--- a/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From cdb3d407740e4f15c3746051f8ba89b8e74e99d3 Mon Sep 17 00:00:00 2001
-From: None <none@example.com>
-Date: Fri, 30 May 2025 13:46:22 -0400
-Subject: [PATCH] Pin compiler_builtins to 0.1.160
-
----
- library/alloc/Cargo.toml | 2 +-
- library/std/Cargo.toml   | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
-index 9d0d957..365c9dc 100644
---- a/library/alloc/Cargo.toml
-+++ b/library/alloc/Cargo.toml
-@@ -16,7 +16,7 @@ bench = false
- 
- [dependencies]
- core = { path = "../core", public = true }
--compiler_builtins = { version = "=0.1.159", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "=0.1.160", features = ['rustc-dep-of-std'] }
- 
- [features]
- compiler-builtins-mem = ['compiler_builtins/mem']
-diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
-index 4ff4895..31371f0 100644
---- a/library/std/Cargo.toml
-+++ b/library/std/Cargo.toml
-@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
- panic_unwind = { path = "../panic_unwind", optional = true }
- panic_abort = { path = "../panic_abort" }
- core = { path = "../core", public = true }
--compiler_builtins = { version = "=0.1.159" }
-+compiler_builtins = { version = "=0.1.160" }
- unwind = { path = "../unwind" }
- hashbrown = { version = "0.15", default-features = false, features = [
-     'rustc-dep-of-std',
--- 
-2.49.0
-
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index bafe497a2a2..8be204c1581 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2025-05-21"
+channel = "nightly-2025-06-02"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 7852aebe0c2..a4454cd9c73 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -520,8 +520,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.block
     }
 
-    fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
-        let func = cx.rvalue_as_function(func);
+    fn append_block(_: &'a CodegenCx<'gcc, 'tcx>, func: Function<'gcc>, name: &str) -> Block<'gcc> {
         func.new_block(name)
     }
 
@@ -782,6 +781,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
                 return self.context.new_call(self.location, fmod, &[a, b]);
             }
             TypeKind::FP128 => {
+                // TODO(antoyo): use get_simple_function_f128_2args.
                 let f128_type = self.type_f128();
                 let fmodf128 = self.context.new_function(
                     None,
@@ -938,22 +938,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
         let block = self.llbb();
         let function = block.get_function();
+        // NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned.
+        // For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned)
+        // Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked"
+        //
+        // From GCCs perspective:
+        // __int128_t  __attribute__((aligned(16)))  __attribute__((aligned(16)))
+        // and:
+        // __int128_t  __attribute__((aligned(16)))
+        // are 2 distinct, incompatible types.
+        //
+        // So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types,
+        // but the GCC APIs to facilitate this just aren't quite there yet.
+
+        // This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment.
+        // Otherwise, this may be an under-aligned load, so we will still call get_aligned.
+        let mut can_skip_align = (pointee_ty == self.cx.u128_type
+            || pointee_ty == self.cx.i128_type)
+            && align == self.int128_align;
+        // We can skip the call to `get_aligned` for byte-sized types with alignment of 1.
+        can_skip_align = can_skip_align
+            || (pointee_ty == self.cx.u8_type || pointee_ty == self.cx.i8_type)
+                && align.bytes() == 1;
+        // Skip the call to `get_aligned` when possible.
+        let aligned_type =
+            if can_skip_align { pointee_ty } else { pointee_ty.get_aligned(align.bytes()) };
+
+        let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
         // NOTE: instead of returning the dereference here, we have to assign it to a variable in
         // the current basic block. Otherwise, it could be used in another basic block, causing a
         // dereference after a drop, for instance.
-        // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
-        // Ideally, we shouldn't need to do this check.
-        // FractalFir: the `align == self.int128_align` check ensures we *do* call `get_aligned` if
-        // the alignment of a `u128`/`i128` is not the one mandated by the ABI. This ensures we handle
-        // under-aligned loads correctly.
-        let aligned_type = if (pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type)
-            && align == self.int128_align
-        {
-            pointee_ty
-        } else {
-            pointee_ty.get_aligned(align.bytes())
-        };
-        let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
         let deref = ptr.dereference(self.location).to_rvalue();
         let loaded_value = function.new_local(
             self.location,
@@ -1105,7 +1119,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // TODO(antoyo)
     }
 
-    fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
+    fn store(&mut self, mut val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
+        if self.structs_as_pointer.borrow().contains(&val) {
+            // NOTE: hack to workaround a limitation of the rustc API: see comment on
+            // CodegenCx.structs_as_pointer
+            val = val.dereference(self.location).to_rvalue();
+        }
+
         self.store_with_flags(val, ptr, align, MemFlags::empty())
     }
 
@@ -1551,16 +1571,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         aggregate_value
     }
 
-    fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
+    fn set_personality_fn(&mut self, _personality: Function<'gcc>) {
         #[cfg(feature = "master")]
-        {
-            let personality = self.rvalue_as_function(_personality);
-            self.current_func().set_personality_function(personality);
-        }
+        self.current_func().set_personality_function(_personality);
     }
 
     #[cfg(feature = "master")]
-    fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+    fn cleanup_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
         self.set_personality_fn(pers_fn);
 
         // NOTE: insert the current block in a variable so that a later call to invoke knows to
@@ -1581,7 +1598,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     #[cfg(not(feature = "master"))]
-    fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+    fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
         let value1 = self
             .current_func()
             .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0")
@@ -1591,7 +1608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         (value1, value2)
     }
 
-    fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) {
+    fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
         // TODO(antoyo): generate the correct landing pad
         self.cleanup_landing_pad(pers_fn);
     }
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 58ff2f1f8f0..fdd47821b51 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -234,19 +234,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
         match cv {
             Scalar::Int(int) => {
                 let data = int.to_bits(layout.size(self));
-
-                // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
-                // the paths for floating-point values.
-                // TODO: Remove this code?
-                /*if ty == self.float_type {
-                    return self
-                        .context
-                        .new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
-                }
-                if ty == self.double_type {
-                    return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64));
-                }*/
-
                 let value = self.const_uint_big(self.type_ix(bitsize), data);
                 let bytesize = layout.size(self).bytes();
                 if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() {
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index ff141ad365b..1d029811dfe 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -118,14 +118,15 @@ pub struct CodegenCx<'gcc, 'tcx> {
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
 
-    eh_personality: Cell<Option<RValue<'gcc>>>,
+    eh_personality: Cell<Option<Function<'gcc>>>,
     #[cfg(feature = "master")]
     pub rust_try_fn: Cell<Option<(Type<'gcc>, Function<'gcc>)>>,
 
     pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
 
     /// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such,
-    /// `const_undef()` returns struct as pointer so that they can later be assigned a value.
+    /// `const_undef()` returns struct as pointer so that they can later be assigned a value (in
+    /// e.g. Builder::insert_value).
     /// As such, this set remembers which of these pointers were returned by this function so that
     /// they can be dereferenced later.
     /// FIXME(antoyo): fix the rustc API to avoid having this hack.
@@ -155,6 +156,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                 .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
                 .unwrap();
             let align = layout.align.abi.bytes();
+            // For types with size 1, the alignment can be 1 and only 1
+            // So, we can skip the call to ``get_aligned`.
+            // In the future, we can add a GCC API to query the type align,
+            // and call `get_aligned` if and only if that differs from Rust's expectations.
+            if layout.size.bytes() == 1 {
+                return context.new_c_type(ctype);
+            }
             #[cfg(feature = "master")]
             {
                 context.new_c_type(ctype).get_aligned(align)
@@ -373,8 +381,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
     type Value = RValue<'gcc>;
     type Metadata = RValue<'gcc>;
-    // TODO(antoyo): change to Function<'gcc>.
-    type Function = RValue<'gcc>;
+    type Function = Function<'gcc>;
 
     type BasicBlock = Block<'gcc>;
     type Type = Type<'gcc>;
@@ -392,11 +399,10 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         &self.vtables
     }
 
-    fn get_fn(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
+    fn get_fn(&self, instance: Instance<'tcx>) -> Function<'gcc> {
         let func = get_fn(self, instance);
         *self.current_func.borrow_mut() = Some(func);
-        // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
-        unsafe { std::mem::transmute(func) }
+        func
     }
 
     fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
@@ -420,7 +426,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         ptr
     }
 
-    fn eh_personality(&self) -> RValue<'gcc> {
+    fn eh_personality(&self) -> Function<'gcc> {
         // The exception handling personality function.
         //
         // If our compilation unit has the `eh_personality` lang item somewhere
@@ -458,9 +464,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                 let symbol_name = tcx.symbol_name(instance).name;
                 let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
                 self.linkage.set(FunctionType::Extern);
-                let func = self.declare_fn(symbol_name, fn_abi);
-                let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
-                func
+                self.declare_fn(symbol_name, fn_abi)
             }
             _ => {
                 let name = if wants_msvc_seh(self.sess()) {
@@ -468,8 +472,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                 } else {
                     "rust_eh_personality"
                 };
-                let func = self.declare_func(name, self.type_i32(), &[], true);
-                unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) }
+                self.declare_func(name, self.type_i32(), &[], true)
             }
         };
         // TODO(antoyo): apply target cpu attributes.
@@ -481,11 +484,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         self.tcx.sess
     }
 
-    fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) {
+    fn set_frame_pointer_type(&self, _llfn: Function<'gcc>) {
         // TODO(antoyo)
     }
 
-    fn apply_target_cpu_attr(&self, _llfn: RValue<'gcc>) {
+    fn apply_target_cpu_attr(&self, _llfn: Function<'gcc>) {
         // TODO(antoyo)
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index 3a265fbc64f..4c8585192a1 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -1,7 +1,7 @@
 use std::ops::Range;
 use std::sync::Arc;
 
-use gccjit::{Location, RValue};
+use gccjit::{Function, Location, RValue};
 use rustc_abi::Size;
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
 use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
@@ -221,7 +221,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         &self,
         instance: Instance<'tcx>,
         fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
-        llfn: RValue<'gcc>,
+        llfn: Function<'gcc>,
         mir: &mir::Body<'tcx>,
     ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
         if self.sess().opts.debuginfo == DebugInfo::None {
@@ -272,7 +272,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         &self,
         _instance: Instance<'tcx>,
         _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
-        _maybe_definition_llfn: Option<RValue<'gcc>>,
+        _maybe_definition_llfn: Option<Function<'gcc>>,
     ) -> Self::DIScope {
         // TODO(antoyo): implement.
     }
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index bed82073e2c..691fd8729e3 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -94,7 +94,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         _fn_type: Type<'gcc>,
         #[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>,
         #[cfg(not(feature = "master"))] callconv: Option<()>,
-    ) -> RValue<'gcc> {
+    ) -> Function<'gcc> {
         // TODO(antoyo): use the fn_type parameter.
         let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
         let return_type = self.type_i32();
@@ -111,8 +111,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         // NOTE: it is needed to set the current_func here as well, because get_fn() is not called
         // for the main function.
         *self.current_func.borrow_mut() = Some(func);
-        // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
-        unsafe { std::mem::transmute(func) }
+        func
     }
 
     pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 09132c34aae..4c10380fe74 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -4,7 +4,9 @@ mod simd;
 #[cfg(feature = "master")]
 use std::iter;
 
-use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp};
+#[cfg(feature = "master")]
+use gccjit::Type;
+use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp};
 #[cfg(feature = "master")]
 use rustc_abi::ExternAbi;
 use rustc_abi::{BackendRepr, HasDataLayout};
@@ -300,6 +302,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
         let fn_args = instance.args;
 
         let simple = get_simple_intrinsic(self, name);
+        // TODO(antoyo): Only call get_simple_function_f128 and get_simple_function_f128_2args when
+        // it is the symbols for the supported f128 builtins.
         let simple_func = get_simple_function(self, name)
             .or_else(|| get_simple_function_f128(self, name))
             .or_else(|| get_simple_function_f128_2args(self, name));
@@ -441,7 +445,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
                 match int_type_width_signed(args[0].layout.ty, self) {
                     Some((width, signed)) => match name {
                         sym::ctlz | sym::cttz => {
-                            let func = self.current_func.borrow().expect("func");
+                            let func = self.current_func();
                             let then_block = func.new_block("then");
                             let else_block = func.new_block("else");
                             let after_block = func.new_block("after");
@@ -1109,7 +1113,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         // for (int counter = 0; value != 0; counter++) {
         //     value &= value - 1;
         // }
-        let func = self.current_func.borrow().expect("func");
+        let func = self.current_func();
         let loop_head = func.new_block("head");
         let loop_body = func.new_block("body");
         let loop_tail = func.new_block("tail");
@@ -1188,7 +1192,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let result_type = lhs.get_type();
         if signed {
             // Based on algorithm from: https://stackoverflow.com/a/56531252/389119
-            let func = self.current_func.borrow().expect("func");
+            let func = self.current_func();
             let res = func.new_local(self.location, result_type, "saturating_sum");
             let supports_native_type = self.is_native_int_type(result_type);
             let overflow = if supports_native_type {
@@ -1259,7 +1263,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let result_type = lhs.get_type();
         if signed {
             // Based on algorithm from: https://stackoverflow.com/a/56531252/389119
-            let func = self.current_func.borrow().expect("func");
+            let func = self.current_func();
             let res = func.new_local(self.location, result_type, "saturating_diff");
             let supports_native_type = self.is_native_int_type(result_type);
             let overflow = if supports_native_type {
@@ -1483,10 +1487,9 @@ fn gen_fn<'a, 'gcc, 'tcx>(
     // FIXME(eddyb) find a nicer way to do this.
     cx.linkage.set(FunctionType::Internal);
     let func = cx.declare_fn(name, fn_abi);
-    let func_val = unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) };
-    cx.set_frame_pointer_type(func_val);
-    cx.apply_target_cpu_attr(func_val);
-    let block = Builder::append_block(cx, func_val, "entry-block");
+    cx.set_frame_pointer_type(func);
+    cx.apply_target_cpu_attr(func);
+    let block = Builder::append_block(cx, func, "entry-block");
     let bx = Builder::build(cx, block);
     codegen(bx);
     (return_type, func)
diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index d931f0d3b5e..544d0bfc710 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -9,6 +9,7 @@ tests/ui/iterators/iter-sum-overflow-debug.rs
 tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
 tests/ui/mir/mir_drop_order.rs
 tests/ui/mir/mir_let_chains_drop_order.rs
+tests/ui/mir/mir_match_guard_let_chains_drop_order.rs
 tests/ui/oom_unwind.rs
 tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
 tests/ui/panic-runtime/abort.rs