* Introduce RUST_CODEGEN_BACKENDS USE_EXPAND to control the supported
  codegen backends for rust.

  Right now, that's:
  * llvm
  * gcc

  In future, we may try out e.g. cranelift too.

  I've done this both because it felt natural but also because it is very
  plausible that packages may need to require a specific (llvm, really)
  backend at least for a period when something like intrinsics are used
  heavily and it's not yet supported in an alternative backend. It will also
  be useful to work around any ICEs or miscompilations with specific backends.

* Add support for rustc_codegen_gcc.

  This works by using libgccjit (sys-devel/gcc[jit]) at runtime.

Some remaining issues:
* Uses a fork of GCC (https://github.com/rust-lang/gcc). This ebuild as a
  first cut always builds this in-tree.

  We may add a USE=system-gcc later depending on how upstreaming of the
  remaining libgccjit patches goes, etc (progress is being made there, but
  would need to assess which ones have landed and which haven't, and their
  relative importance).

* No multilib support yet 
(https://github.com/rust-lang/rustc_codegen_gcc/issues/779).

* The first value listed for 'codegen-backends' in the build system will
  be the default.

  The toggle to change the codegen backend at runtime is still an unstable
  feature 
(https://doc.rust-lang.org/beta/unstable-book/compiler-flags/codegen-backend.html).

  The interaction here with rust.eclass is a bit awkward, so we list LLVM
  first (as we know it always works) to keep things simpler. Users wanting
  to use alternative backends, at least for now, can pass either
  -Zcodegen-backend=PATH in RUSTFLAGS or just disable all other backends in
  Rust via the USE_EXPAND.

* The ebuild relies on some hacks for final installation.

  Upstream commit 6f0746da4effaceae569ae69d4ea05758f49dff7 gets us very close
  to installation Just Working but a bit more is needed to get a dist/install
  target. I've hacked up a patch for that but it doesn't completely work so
  I've worked around that at the end of src_install.

Bug: https://bugs.gentoo.org/965182
Signed-off-by: Sam James <[email protected]>
---
 dev-lang/rust/Manifest                        |   1 +
 .../files/rustc_codegen_gcc-avoid-oom.patch   | 176 +++++++++++++
 .../rust/files/rustc_codegen_gcc-dist.patch   | 236 ++++++++++++++++++
 ...degen_gcc-include-lib-path-bootstrap.patch | 108 ++++++++
 dev-lang/rust/rust-1.91.0.ebuild              | 119 +++++++--
 dev-lang/rust/rust-9999.ebuild                | 121 +++++++--
 profiles/base/make.defaults                   |   2 +-
 profiles/base/package.use.force               |   4 +
 profiles/base/package.use.mask                |   5 +
 .../desc/rust_codegen_backends.desc           |   7 +-
 profiles/desc/rust_sysroots.desc              |   2 +-
 11 files changed, 743 insertions(+), 38 deletions(-)
 create mode 100644 dev-lang/rust/files/rustc_codegen_gcc-avoid-oom.patch
 create mode 100644 dev-lang/rust/files/rustc_codegen_gcc-dist.patch
 create mode 100644 
dev-lang/rust/files/rustc_codegen_gcc-include-lib-path-bootstrap.patch
 copy acct-group/clock/clock-0.ebuild => 
profiles/desc/rust_codegen_backends.desc (51%)

diff --git a/dev-lang/rust/Manifest b/dev-lang/rust/Manifest
index 3ecab9d4c1bb7..950e55cda1ebd 100644
--- a/dev-lang/rust/Manifest
+++ b/dev-lang/rust/Manifest
@@ -1,3 +1,4 @@
+DIST gcc-fork-b93730ce97c738bdb9209aa973d3fc6fd4ce1d81.tar.gz 158655960 
BLAKE2B 
6424f2c924b51dff1995159da28166cd30e68ccd92ff182e3fcb3ed628cafb6c3bfedc24f2c6860f03a5fc585ad417b39daf841ad2be4f4b556c4c0566049c54
 SHA512 
f6c9fbfe108abd8be1f8aa1bfc4c76de0ec097765b09c00975002fffef34f4ff8fefbe527d8e4ab71009d9cb84ccd28b4c9f365194d497fe360e206e86e5f2d1
 DIST rust-patches-1.74.1-r101.tar.bz2 3887 BLAKE2B 
0afb0252fe56ac8c572fe20acd989f9ef3f33cb8134cdb8fbf5cb064156556aedeb226fd50af465f35f656ebd0c0a163ca060490f44811def8535bad70f5f24d
 SHA512 
7253728000d49fd8533182aa8961e70aef41a48e2df03e72d1ea93ca7abb924bbe1689692d874f2b18469e5a54ea572e55ddc18c9f4d81d1e8ec380f2d72095b
 DIST rust-patches-1.75.0-r101.tar.bz2 4419 BLAKE2B 
389a688a6e92d5f9325bade125b006deb7453d9d7ae0483c8ec0cf580f95eb03a65f600e79ed354029b4b91ab8f66929877bdc6ebf83e7b8d3b1d9451fecd8b6
 SHA512 
6f36e9e13e590bff72483ea4364c045579858da5db3868048f79e0dd6ac896aaf00a1fb9d156820e742a1f5ec412ddfa897677133669b77a4f219c6d90365775
 DIST rust-patches-1.76.0-r101.tar.bz2 5513 BLAKE2B 
52816dffac969520e7b73ceaae1201bb7abba129da1021e8e39ccd6e471281c51cf005221589c7b08fc328be54ba2d6134fc8e240cb15f0b877e370009937084
 SHA512 
a65d306d709e99c688e4febb439a60f9ac8b506a86fdb3021782dfbb8991ddcc07adcd19494a8e76233ad2bec7f23896b6eb80c13929b7c997fdc3fd45f8b63a
diff --git a/dev-lang/rust/files/rustc_codegen_gcc-avoid-oom.patch 
b/dev-lang/rust/files/rustc_codegen_gcc-avoid-oom.patch
new file mode 100644
index 0000000000000..23b661dda6093
--- /dev/null
+++ b/dev-lang/rust/files/rustc_codegen_gcc-avoid-oom.patch
@@ -0,0 +1,176 @@
+Avoid OOM when building cargo during bootstrap.
+
+https://github.com/rust-lang/rustc_codegen_gcc/issues/777
+https://github.com/rust-lang/rustc_codegen_gcc/pull/783
+
+From 77a97960514f6d24573e95abf1e02e7337abc193 Mon Sep 17 00:00:00 2001
+From: Antoni Boucher <[email protected]>
+Date: Sat, 25 Oct 2025 20:10:39 -0400
+Subject: [PATCH] Fix RAM usage by splitting deeply nested expressions
+
+---
+ src/builder.rs | 61 +++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 40 insertions(+), 21 deletions(-)
+
+diff --git a/src/builder.rs b/src/builder.rs
+index 5657620879c..481b12d842f 100644
+--- a/src/builder.rs
++++ b/src/builder.rs
+@@ -668,32 +668,38 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for 
Builder<'a, 'gcc, 'tcx> {
+     }
+ 
+     fn add(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.gcc_add(a, b)
++        self.assign_to_var(self.gcc_add(a, b))
+     }
+ 
+     fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        a + b
++        self.assign_to_var(a + b)
+     }
+ 
+     // TODO(antoyo): should we also override the `unchecked_` versions?
+     fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.gcc_sub(a, b)
++        self.assign_to_var(self.gcc_sub(a, b))
+     }
+ 
+     fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        a - b
++        self.assign_to_var(a - b)
+     }
+ 
+     fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.gcc_mul(a, b)
++        self.assign_to_var(self.gcc_mul(a, b))
+     }
+ 
+     fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.cx.context.new_binary_op(self.location, BinaryOp::Mult, 
a.get_type(), a, b)
++        self.assign_to_var(self.cx.context.new_binary_op(
++            self.location,
++            BinaryOp::Mult,
++            a.get_type(),
++            a,
++            b,
++        ))
+     }
+ 
+     fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.gcc_udiv(a, b)
++        self.assign_to_var(self.gcc_udiv(a, b))
+     }
+ 
+     fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> 
{
+@@ -702,11 +708,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for 
Builder<'a, 'gcc, 'tcx> {
+         let a = self.gcc_int_cast(a, a_type);
+         let b_type = b.get_type().to_unsigned(self);
+         let b = self.gcc_int_cast(b, b_type);
+-        self.gcc_udiv(a, b)
++        self.assign_to_var(self.gcc_udiv(a, b))
+     }
+ 
+     fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.gcc_sdiv(a, b)
++        self.assign_to_var(self.gcc_sdiv(a, b))
+     }
+ 
+     fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> 
{
+@@ -715,19 +721,19 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for 
Builder<'a, 'gcc, 'tcx> {
+         // should be the same.
+         let typ = a.get_type().to_signed(self);
+         let b = self.gcc_int_cast(b, typ);
+-        self.gcc_sdiv(a, b)
++        self.assign_to_var(self.gcc_sdiv(a, b))
+     }
+ 
+     fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        a / b
++        self.assign_to_var(a / b)
+     }
+ 
+     fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.gcc_urem(a, b)
++        self.assign_to_var(self.gcc_urem(a, b))
+     }
+ 
+     fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+-        self.gcc_srem(a, b)
++        self.assign_to_var(self.gcc_srem(a, b))
+     }
+ 
+     fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+@@ -865,22 +871,26 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for 
Builder<'a, 'gcc, 'tcx> {
+ 
+     fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        set_rvalue_location(self, lhs + rhs)
++        let result = set_rvalue_location(self, lhs + rhs);
++        self.assign_to_var(result)
+     }
+ 
+     fn fsub_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        set_rvalue_location(self, lhs - rhs)
++        let result = set_rvalue_location(self, lhs - rhs);
++        self.assign_to_var(result)
+     }
+ 
+     fn fmul_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        set_rvalue_location(self, lhs * rhs)
++        let result = set_rvalue_location(self, lhs * rhs);
++        self.assign_to_var(result)
+     }
+ 
+     fn fdiv_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        set_rvalue_location(self, lhs / rhs)
++        let result = set_rvalue_location(self, lhs / rhs);
++        self.assign_to_var(result)
+     }
+ 
+     fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+@@ -892,22 +902,22 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for 
Builder<'a, 'gcc, 'tcx> {
+ 
+     fn fadd_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        lhs + rhs
++        self.assign_to_var(lhs + rhs)
+     }
+ 
+     fn fsub_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        lhs - rhs
++        self.assign_to_var(lhs - rhs)
+     }
+ 
+     fn fmul_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        lhs * rhs
++        self.assign_to_var(lhs * rhs)
+     }
+ 
+     fn fdiv_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+         // NOTE: it seems like we cannot enable fast-mode for a single 
operation in GCC.
+-        lhs / rhs
++        self.assign_to_var(lhs / rhs)
+     }
+ 
+     fn frem_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> 
RValue<'gcc> {
+@@ -2409,6 +2419,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
+         let res = then_vals | else_vals;
+         self.bitcast_if_needed(res, result_type)
+     }
++
++    // GCC doesn't like deeply nested expressions.
++    // By assigning intermediate expressions to a variable, this allow us to 
avoid deeply nested
++    // expressions and GCC will use much less RAM.
++    fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> {
++        let var = self.current_func().new_local(self.location, 
value.get_type(), "opResult");
++        self.llbb().add_assignment(self.location, var, value);
++        var.to_rvalue()
++    }
+ }
+ 
+ fn difference_or_zero<'gcc>(
diff --git a/dev-lang/rust/files/rustc_codegen_gcc-dist.patch 
b/dev-lang/rust/files/rustc_codegen_gcc-dist.patch
new file mode 100644
index 0000000000000..e72c3c120c906
--- /dev/null
+++ b/dev-lang/rust/files/rustc_codegen_gcc-dist.patch
@@ -0,0 +1,236 @@
+Incomplete attempt at implementing the dist/install step mentioned in upstream
+commit 6f0746da4effaceae569ae69d4ea05758f49dff7 for rustc_codegen_gcc. It's
+partly there but not quite enough, see manual steps in src_install in the
+ebuild.
+--- a/src/bootstrap/src/core/build_steps/compile.rs
++++ b/src/bootstrap/src/core/build_steps/compile.rs
+@@ -1573,13 +1573,13 @@ fn run(self, builder: &Builder<'_>) {
+ /// It includes the path to the libgccjit library on which this backend 
depends.
+ #[derive(Clone)]
+ pub struct GccCodegenBackendOutput {
+-    stamp: BuildStamp,
++    pub stamp: BuildStamp,
+     gcc: GccOutput,
+ }
+ 
+ #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+ pub struct GccCodegenBackend {
+-    compilers: RustcPrivateCompilers,
++    pub compilers: RustcPrivateCompilers,
+ }
+ 
+ impl Step for GccCodegenBackend {
+--- a/src/bootstrap/src/core/build_steps/dist.rs
++++ b/src/bootstrap/src/core/build_steps/dist.rs
+@@ -1582,6 +1582,93 @@ fn metadata(&self) -> Option<StepMetadata> {
+     }
+ }
+ 
++#[derive(Debug, Clone, Hash, PartialEq, Eq)]
++pub struct GccCodegenBackend {
++    pub compilers: RustcPrivateCompilers,
++    pub target: TargetSelection,
++}
++
++impl Step for GccCodegenBackend {
++    type Output = Option<GeneratedTarball>;
++    const DEFAULT: bool = true;
++    const IS_HOST: bool = true;
++
++    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
++        // We only want to build the gcc backend in `x dist` if the backend 
was enabled
++        // in rust.codegen-backends.
++        // Sadly, we don't have access to the actual target for which we're 
disting gcc here..
++        // So we just use the host target.
++        let gcc_enabled_by_default = run
++            .builder
++            .config
++            .enabled_codegen_backends(run.builder.host_target)
++            .contains(&CodegenBackendKind::Gcc);
++        
run.alias("rustc_codegen_gcc").default_condition(gcc_enabled_by_default)
++    }
++
++    fn make_run(run: RunConfig<'_>) {
++        run.builder.ensure(GccCodegenBackend {
++            compilers: RustcPrivateCompilers::new(run.builder, 
run.builder.top_stage, run.target),
++            target: run.target,
++        });
++    }
++
++    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
++        // This prevents rustc_codegen_gcc from being built for "dist"
++        // or "install" on the stable/beta channels. It is not yet stable and
++        // should not be included.
++        if !builder.build.unstable_features() {
++            return None;
++        }
++
++        let target = self.target;
++        // TODO: Is there an equivalent for the gcc backend here? cranelift 
has this.
++        //if !target_supports_gcc_backend(target) {
++        //    builder.info("target not supported by rustc_codegen_gcc. 
skipping");
++        //    return None;
++        //}
++
++        let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", 
&target.triple);
++        tarball.set_overlay(OverlayKind::RustcCodegenGcc);
++        tarball.is_preview(true);
++        tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
++
++        let compilers = self.compilers;
++        let stamp = builder.ensure(compile::GccCodegenBackend { compilers 
}).stamp;
++
++        if builder.config.dry_run() {
++            return None;
++        }
++
++        // Get the relative path of where the codegen backend should be 
stored.
++        let backends_dst = 
builder.sysroot_codegen_backends(compilers.target_compiler());
++        let backends_rel = backends_dst
++            .strip_prefix(builder.sysroot(compilers.target_compiler()))
++            .unwrap()
++            
.strip_prefix(builder.sysroot_libdir_relative(compilers.target_compiler()))
++            .unwrap();
++        // Don't use custom libdir here because ^lib/ will be resolved again 
with installer
++        let backends_dst = PathBuf::from("lib").join(backends_rel);
++
++        let codegen_backend_dylib = get_codegen_backend_file(&stamp);
++        tarball.add_renamed_file(
++            &codegen_backend_dylib,
++            &backends_dst,
++            &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
++            FileType::NativeLibrary,
++        );
++
++        Some(tarball.generate())
++    }
++
++    fn metadata(&self) -> Option<StepMetadata> {
++        Some(
++            StepMetadata::dist("rustc_codegen_gcc", self.target)
++                .built_by(self.compilers.build_compiler()),
++        )
++    }
++}
++
+ #[derive(Debug, Clone, Hash, PartialEq, Eq)]
+ pub struct Rustfmt {
+     pub compilers: RustcPrivateCompilers,
+@@ -1695,6 +1782,10 @@ macro_rules! add_component {
+             compilers: rustc_private_compilers,
+             target
+         });
++        add_component!("rustc-codegen-gcc" => GccCodegenBackend {
++            compilers: rustc_private_compilers,
++            target
++        });
+         add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
+             build_compiler,
+             target
+@@ -1796,6 +1887,7 @@ fn filter(contents: &str, marker: &str) -> String {
+                 "rust-docs",
+                 "miri",
+                 "rustc-codegen-cranelift",
++                "rustc-codegen-gcc",
+             ] {
+                 if built_tools.contains(tool) {
+                     prepare(tool);
+--- a/src/bootstrap/src/core/build_steps/install.rs
++++ b/src/bootstrap/src/core/build_steps/install.rs
+@@ -289,6 +289,19 @@ fn run($sel, $builder: &Builder<'_>) {
+             );
+         }
+     };
++    RustcCodegenGcc, alias = "rustc-codegen-gcc", 
Self::should_build(_config), IS_HOST: true, {
++        if let Some(tarball) = builder.ensure(dist::GccCodegenBackend {
++            compilers: RustcPrivateCompilers::from_build_compiler(builder, 
self.build_compiler, self.target),
++            target: self.target
++        }) {
++            install_sh(builder, "rustc-codegen-gcc", self.build_compiler, 
Some(self.target), &tarball);
++        } else {
++            builder.info(
++                &format!("skipping Install CodegenBackend(\"gcc\") stage{} 
({})",
++                         self.build_compiler.stage + 1, self.target),
++            );
++        }
++    };
+     LlvmBitcodeLinker, alias = "llvm-bitcode-linker", 
Self::should_build(_config), IS_HOST: true, {
+         if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { 
build_compiler: self.build_compiler, target: self.target }) {
+             install_sh(builder, "llvm-bitcode-linker", self.build_compiler, 
Some(self.target), &tarball);
+--- a/src/bootstrap/src/core/builder/mod.rs
++++ b/src/bootstrap/src/core/builder/mod.rs
+@@ -1185,6 +1185,7 @@ macro_rules! describe {
+                 dist::Mingw,
+                 dist::Rustc,
+                 dist::CraneliftCodegenBackend,
++                dist::GccCodegenBackend,
+                 dist::Std,
+                 dist::RustcDev,
+                 dist::Analysis,
+--- a/src/bootstrap/src/utils/tarball.rs
++++ b/src/bootstrap/src/utils/tarball.rs
+@@ -25,6 +25,7 @@ pub(crate) enum OverlayKind {
+     Rustfmt,
+     RustAnalyzer,
+     RustcCodegenCranelift,
++    RustcCodegenGcc,
+     LlvmBitcodeLinker,
+ }
+ 
+@@ -66,6 +67,11 @@ fn legal_and_readme(&self) -> &[&str] {
+                 "compiler/rustc_codegen_cranelift/LICENSE-APACHE",
+                 "compiler/rustc_codegen_cranelift/LICENSE-MIT",
+             ],
++            OverlayKind::RustcCodegenGcc => &[
++                "compiler/rustc_codegen_gcc/Readme.md",
++                //"compiler/rustc_codegen_cranelift/LICENSE-APACHE",
++                //"compiler/rustc_codegen_cranelift/LICENSE-MIT",
++            ],
+             OverlayKind::LlvmBitcodeLinker => &[
+                 "COPYRIGHT",
+                 "LICENSE-APACHE",
+@@ -93,6 +99,7 @@ fn version(&self, builder: &Builder<'_>) -> String {
+                 .rust_analyzer_info
+                 .version(builder, 
&builder.release_num("rust-analyzer/crates/rust-analyzer")),
+             OverlayKind::RustcCodegenCranelift => builder.rust_version(),
++            OverlayKind::RustcCodegenGcc => builder.rust_version(),
+             OverlayKind::LlvmBitcodeLinker => builder.rust_version(),
+         }
+     }
+--- a/src/tools/build-manifest/src/main.rs
++++ b/src/tools/build-manifest/src/main.rs
+@@ -490,6 +490,7 @@ fn target_host_combination(&mut self, host: &str, 
manifest: &Manifest) -> Option
+                 | PkgType::RustAnalysis
+                 | PkgType::JsonDocs
+                 | PkgType::RustcCodegenCranelift
++                | PkgType::RustcCodegenGcc
+                 | PkgType::LlvmBitcodeLinker => {
+                     extensions.push(host_component(pkg));
+                 }
+--- a/src/tools/build-manifest/src/versions.rs
++++ b/src/tools/build-manifest/src/versions.rs
+@@ -58,6 +58,7 @@ pub(crate) fn all() -> &'static [PkgType] {
+     Miri = "miri"; preview = true,
+     JsonDocs = "rust-docs-json"; preview = true,
+     RustcCodegenCranelift = "rustc-codegen-cranelift"; preview = true,
++    RustcCodegenGcc = "rustc-codegen-gcc"; preview = true,
+     LlvmBitcodeLinker = "llvm-bitcode-linker"; preview = true,
+ }
+ 
+@@ -82,6 +83,8 @@ fn should_use_rust_version(&self) -> bool {
+             PkgType::LlvmTools => false,
+             PkgType::Miri => false,
+             PkgType::RustcCodegenCranelift => false,
++            // TODO
++            PkgType::RustcCodegenGcc => false,
+ 
+             PkgType::Rust => true,
+             PkgType::RustStd => true,
+@@ -111,6 +114,7 @@ pub(crate) fn targets(&self) -> &[&str] {
+             RustcDocs => HOSTS,
+             Cargo => HOSTS,
+             RustcCodegenCranelift => HOSTS,
++            RustcCodegenGcc => HOSTS, // TODO
+             RustMingw => MINGW,
+             RustStd => TARGETS,
+             HtmlDocs => HOSTS,
diff --git 
a/dev-lang/rust/files/rustc_codegen_gcc-include-lib-path-bootstrap.patch 
b/dev-lang/rust/files/rustc_codegen_gcc-include-lib-path-bootstrap.patch
new file mode 100644
index 0000000000000..aee2ef26ec5ec
--- /dev/null
+++ b/dev-lang/rust/files/rustc_codegen_gcc-include-lib-path-bootstrap.patch
@@ -0,0 +1,108 @@
+This fixes finding tools built in earlier stages even with `rust.rpath = true`
+(at least for rustc_codegen_gcc).
+
+https://github.com/rust-lang/rust/issues/146930
+https://github.com/rust-lang/rust/pull/147419
+
+From 03cdcb5cd5383857b339af226471f96c46e26b47 Mon Sep 17 00:00:00 2001
+From: Josh Stone <[email protected]>
+Date: Mon, 6 Oct 2025 13:34:42 -0700
+Subject: [PATCH] bootstrap: add `Builder::rustc_cmd` that includes the lib
+ path
+
+When building with `rust.rpath = false`, every `rustc` invocation needs
+to include the library path as well. I particularly ran into this in
+`generate_target_spec_json_schema` when testing 1.91-beta in Fedora,
+where we do disable rpath for our system builds. The new helper function
+will hopefully encourage the right thing going forward.
+---
+ src/bootstrap/src/core/build_steps/compile.rs           | 2 +-
+ src/bootstrap/src/core/build_steps/dist.rs              | 2 +-
+ src/bootstrap/src/core/build_steps/synthetic_targets.rs | 3 +--
+ src/bootstrap/src/core/builder/cargo.rs                 | 6 ++----
+ src/bootstrap/src/core/builder/mod.rs                   | 8 ++++++++
+ 5 files changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/src/bootstrap/src/core/build_steps/compile.rs 
b/src/bootstrap/src/core/build_steps/compile.rs
+index d29d1041486bd..b363b8f93b361 100644
+--- a/src/bootstrap/src/core/build_steps/compile.rs
++++ b/src/bootstrap/src/core/build_steps/compile.rs
+@@ -519,7 +519,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: 
TargetSelection, cargo: &mut Car
+         // Query rustc for the deployment target, and the associated env var.
+         // The env var is one of the standard `*_DEPLOYMENT_TARGET` vars, i.e.
+         // `MACOSX_DEPLOYMENT_TARGET`, `IPHONEOS_DEPLOYMENT_TARGET`, etc.
+-        let mut cmd = command(builder.rustc(cargo.compiler()));
++        let mut cmd = builder.rustc_cmd(cargo.compiler());
+         cmd.arg("--target").arg(target.rustc_target_arg());
+         cmd.arg("--print=deployment-target");
+         let output = cmd.run_capture_stdout(builder).stdout();
+diff --git a/src/bootstrap/src/core/build_steps/dist.rs 
b/src/bootstrap/src/core/build_steps/dist.rs
+index b79d2cb413db7..411d42962644d 100644
+--- a/src/bootstrap/src/core/build_steps/dist.rs
++++ b/src/bootstrap/src/core/build_steps/dist.rs
+@@ -625,7 +625,7 @@ fn generate_target_spec_json_schema(builder: &Builder<'_>, 
sysroot: &Path) {
+     // We do this by using the stage 1 compiler, which is always compiled for 
the host,
+     // even in a cross build.
+     let stage1_host = builder.compiler(1, builder.host_target);
+-    let mut rustc = command(builder.rustc(stage1_host)).fail_fast();
++    let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
+     rustc
+         .env("RUSTC_BOOTSTRAP", "1")
+         .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
+diff --git a/src/bootstrap/src/core/build_steps/synthetic_targets.rs 
b/src/bootstrap/src/core/build_steps/synthetic_targets.rs
+index 21733c5d9e3f7..2cc691832b5f0 100644
+--- a/src/bootstrap/src/core/build_steps/synthetic_targets.rs
++++ b/src/bootstrap/src/core/build_steps/synthetic_targets.rs
+@@ -10,7 +10,6 @@
+ use crate::Compiler;
+ use crate::core::builder::{Builder, ShouldRun, Step};
+ use crate::core::config::TargetSelection;
+-use crate::utils::exec::command;
+ 
+ #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+ pub(crate) struct MirOptPanicAbortSyntheticTarget {
+@@ -55,7 +54,7 @@ fn create_synthetic_target(
+         return TargetSelection::create_synthetic(&name, 
path.to_str().unwrap());
+     }
+ 
+-    let mut cmd = command(builder.rustc(compiler));
++    let mut cmd = builder.rustc_cmd(compiler);
+     cmd.arg("--target").arg(base.rustc_target_arg());
+     cmd.args(["-Zunstable-options", "--print", "target-spec-json"]);
+ 
+diff --git a/src/bootstrap/src/core/builder/cargo.rs 
b/src/bootstrap/src/core/builder/cargo.rs
+index a404aec512091..c2029f97391d4 100644
+--- a/src/bootstrap/src/core/builder/cargo.rs
++++ b/src/bootstrap/src/core/builder/cargo.rs
+@@ -728,10 +728,8 @@ impl Builder<'_> {
+                 // Build proc macros both for the host and the target unless 
proc-macros are not
+                 // supported by the target.
+                 if target != compiler.host && cmd_kind != Kind::Check {
+-                    let mut rustc_cmd = command(self.rustc(compiler));
+-                    self.add_rustc_lib_path(compiler, &mut rustc_cmd);
+-
+-                    let error = rustc_cmd
++                    let error = self
++                        .rustc_cmd(compiler)
+                         .arg("--target")
+                         .arg(target.rustc_target_arg())
+                         .arg("--print=file-names")
+diff --git a/src/bootstrap/src/core/builder/mod.rs 
b/src/bootstrap/src/core/builder/mod.rs
+index fc06db8f80b9d..1ddfbd51df523 100644
+--- a/src/bootstrap/src/core/builder/mod.rs
++++ b/src/bootstrap/src/core/builder/mod.rs
+@@ -1605,6 +1605,14 @@ Alternatively, you can set `build.local-rebuild=true` 
and use a stage0 compiler
+         }
+     }
+ 
++    /// Gets a command to run the compiler specified, including the dynamic 
library
++    /// path in case the executable has not been build with `rpath` enabled.
++    pub fn rustc_cmd(&self, compiler: Compiler) -> BootstrapCommand {
++        let mut cmd = command(self.rustc(compiler));
++        self.add_rustc_lib_path(compiler, &mut cmd);
++        cmd
++    }
++
+     /// Gets the paths to all of the compiler's codegen backends.
+     fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = 
PathBuf> {
+         fs::read_dir(self.sysroot_codegen_backends(compiler))
diff --git a/dev-lang/rust/rust-1.91.0.ebuild b/dev-lang/rust/rust-1.91.0.ebuild
index 928864b571a18..ec9d2eb1ab583 100644
--- a/dev-lang/rust/rust-1.91.0.ebuild
+++ b/dev-lang/rust/rust-1.91.0.ebuild
@@ -8,9 +8,9 @@ EAPI=8
 LLVM_COMPAT=( 21 )
 PYTHON_COMPAT=( python3_{11..14} )
 
-RUST_PATCH_VER=${PV#*_p}
-RUST_MAX_VER=${PV%%_*}
+RUST_PATCH_VER=${PVR}
 
+RUST_MAX_VER=${PV%%_*}
 if [[ ${PV} == *9999* ]]; then
        RUST_MIN_VER="1.88.0" # Update this as new `beta` releases come out.
 elif [[ ${PV} == *beta* ]]; then
@@ -30,17 +30,26 @@ elif [[ ${PV} == *beta* ]]; then
        # curl -Ls static.rust-lang.org/dist/channel-rust-beta.toml | grep 
beta-src.tar.xz
        betaver=${PV//*beta}
        BETA_SNAPSHOT="${betaver:0:4}-${betaver:4:2}-${betaver:6:2}"
+       # compiler/rustc_codegen_gcc/libgccjit.version
+       #GCC_FORK_COMMIT="4e995bd73c4490edfe5080ec6014d63aa9abed5f"
+       GCC_FORK_COMMIT="b93730ce97c738bdb9209aa973d3fc6fd4ce1d81"
        MY_P="rustc-beta"
-       
SRC_URI="https://static.rust-lang.org/dist/${BETA_SNAPSHOT}/rustc-beta-src.tar.xz
 -> rustc-${PV}-src.tar.xz
+       SRC_URI="
+               
https://static.rust-lang.org/dist/${BETA_SNAPSHOT}/rustc-beta-src.tar.xz -> 
rustc-${PV}-src.tar.xz
                
https://gitweb.gentoo.org/proj/rust-patches.git/snapshot/rust-patches-${RUST_PATCH_VER}.tar.bz2
+               rust_codegen_backends_gcc? ( 
https://github.com/rust-lang/gcc/archive/${GCC_FORK_COMMIT}.tar.gz -> 
gcc-fork-${GCC_FORK_COMMIT}.tar.gz )
                verify-sig? ( 
https://static.rust-lang.org/dist/${BETA_SNAPSHOT}/rustc-beta-src.tar.xz.asc
                        -> rustc-${PV}-src.tar.xz.asc )
        "
        S="${WORKDIR}/${MY_P}-src"
 else
+       # compiler/rustc_codegen_gcc/libgccjit.version
+       GCC_FORK_COMMIT="04ce66d8c918de9273bd7101638ad8724edf5e21"
        MY_P="rustc-${PV}"
-       SRC_URI="https://static.rust-lang.org/dist/${MY_P}-src.tar.xz
+       SRC_URI="
+               https://static.rust-lang.org/dist/${MY_P}-src.tar.xz
                
https://gitweb.gentoo.org/proj/rust-patches.git/snapshot/rust-patches-${RUST_PATCH_VER}.tar.bz2
+               rust_codegen_backends_gcc? ( 
https://github.com/rust-lang/gcc/archive/${GCC_FORK_COMMIT}.tar.gz -> 
gcc-fork-${GCC_FORK_COMMIT}.tar.gz )
                verify-sig? ( 
https://static.rust-lang.org/dist/${MY_P}-src.tar.xz.asc )
        "
        S="${WORKDIR}/${MY_P}-src"
@@ -69,10 +78,22 @@ done
 ALL_RUST_SYSROOTS=( bpf wasm )
 ALL_RUST_SYSROOTS=( "${ALL_RUST_SYSROOTS[@]/#/rust_sysroots_}" )
 
+# The order here is important. The first is default. We have to pick LLVM
+# first for now (if enabled) to avoid some hassle with mangling RUSTFLAGS
+# depending on what an ebuild supports if we know it's broken with an
+# alternative backend.
+#
+# Further, note that the runtime toggle for choosing the backend is marked 
unstable:
+# 
https://doc.rust-lang.org/beta/unstable-book/compiler-flags/codegen-backend.html
+#
+# TODO: cranelift?
+ALL_RUST_CODEGEN_BACKENDS=( llvm gcc )
+ALL_RUST_CODEGEN_BACKENDS=( 
"${ALL_RUST_CODEGEN_BACKENDS[@]/#/rust_codegen_backends_}" )
+
 LICENSE="|| ( MIT Apache-2.0 ) BSD BSD-1 BSD-2 BSD-4"
 SLOT="${PV%%_*}" # Beta releases get to share the same SLOT as the eventual 
stable
 
-IUSE="big-endian clippy cpu_flags_x86_sse2 debug dist doc llvm-libunwind lto 
rustfmt rust-analyzer rust-src system-llvm test ${ALL_LLVM_TARGETS[*]} 
${ALL_RUST_SYSROOTS[*]}"
+IUSE="big-endian clippy cpu_flags_x86_sse2 debug dist doc llvm-libunwind lto 
rustfmt rust-analyzer rust-src system-llvm test ${ALL_LLVM_TARGETS[*]} 
${ALL_RUST_SYSROOTS[*]} ${ALL_RUST_CODEGEN_BACKENDS[*]}"
 
 if [[ ${PV} = *9999* ]]; then
        # These USE flags require nightly rust
@@ -117,13 +138,22 @@ DEPEND="
        net-misc/curl:=[http2,ssl]
        sys-libs/zlib:=
        dev-libs/openssl:0=
-       system-llvm? (
-               ${LLVM_DEPEND[*]}
-               llvm-libunwind? ( llvm-runtimes/libunwind:= )
+       rust_codegen_backends_gcc? (
+               app-arch/zstd:=
+               dev-libs/gmp:=
+               dev-libs/isl:=
+               dev-libs/mpc:=
+               dev-libs/mpfr:=
        )
-       !system-llvm? (
-               !llvm-libunwind? (
-                       elibc_musl? ( sys-libs/libunwind:= )
+       rust_codegen_backends_llvm? (
+               system-llvm? (
+                       ${LLVM_DEPEND[*]}
+                       llvm-libunwind? ( llvm-runtimes/libunwind:= )
+               )
+               !system-llvm? (
+                       !llvm-libunwind? (
+                               elibc_musl? ( sys-libs/libunwind:= )
+                       )
                )
        )
 "
@@ -317,9 +347,23 @@ src_unpack() {
        elif use verify-sig ; then
                # Patch tarballs are not signed (but we trust Gentoo infra)
                verify-sig_verify_detached 
"${DISTDIR}"/rustc-${PV}-src.tar.xz{,.asc}
-               default
+               unpack rustc-${PV}-src.tar.xz{,.asc}
+               unpack rust-patches-${RUST_PATCH_VER}.tar.bz2
+
+               if use rust_codegen_backends_gcc ; then
+                       (
+                               cd "${S}"/src || die
+                               rm gcc/notice.txt || die
+                               rmdir gcc || die
+                               unpack gcc-fork-${GCC_FORK_COMMIT}.tar.gz
+                               mv gcc-${GCC_FORK_COMMIT} gcc
+                       )
+               fi
        else
-               default
+               unpack rustc-${PV}-src.tar.xz{,.asc}
+               unpack rust-patches-${RUST_PATCH_VER}.tar.bz2
+               # TODO: system-gcc
+               use rust_codegen_backends_gcc && unpack 
gcc-fork-${GCC_FORK_COMMIT}.tar.gz
        fi
 }
 
@@ -339,7 +383,22 @@ src_prepare() {
                export RUSTFLAGS+=" -C link-arg=-fuse-ld=lld"
        fi
 
+       if use rust_codegen_backends_gcc ; then
+               # We should have all of these available on Gentoo systems.
+               cat <<-EOF > src/gcc/contrib/download_prerequisites || die
+               #!/bin/sh
+               exit 0
+               EOF
+               chmod +x src/gcc/contrib/download_prerequisites || die
+       fi
+
        default
+
+       if use rust_codegen_backends_gcc ; then
+               eapply 
"${FILESDIR}"/rustc_codegen_gcc-include-lib-path-bootstrap.patch
+               eapply "${FILESDIR}"/rustc_codegen_gcc-dist.patch
+               eapply -d "${S}"/compiler/rustc_codegen_gcc -p1 -- 
"${FILESDIR}"/rustc_codegen_gcc-avoid-oom.patch
+       fi
 }
 
 src_configure() {
@@ -383,6 +442,8 @@ src_configure() {
        use rustfmt && tools+=',"rustfmt"'
        use rust-analyzer && 
tools+=',"rust-analyzer","rust-analyzer-proc-macro-srv"'
        use rust-src && tools+=',"src"'
+       # TODO: see if these are (all) still needed
+       use rust_codegen_backends_gcc && 
tools+=',"rustc-dev","gcc","rustc-codegen-gcc"'
 
        if [[ ${PV} == *9999* ]]; then
                use miri && tools+=',"miri"'
@@ -419,8 +480,20 @@ src_configure() {
                        ;;
        esac
 
-       # TODO: Add optimized-compiler-builtins for system-llvm to avoid
-       # building bundled compiler-rt.
+       # XXX: Clean this up?
+       codegen_backends=''
+       local codegen_backend
+       for codegen_backend in "${RUST_CODEGEN_BACKENDS[@]}" ; do
+               use rust_codegen_backends_${codegen_backend} && \
+                       codegen_backends+="\"${codegen_backend}\","
+       done
+
+       # XXX: Needed for dist target and some of the switches?
+       if use rust_codegen_backends_gcc ; then
+               ewarn "Forcing build as nightly for GCC codegen backend"
+               build_channel="nightly"
+       fi
+
        cat <<- _EOF_ > "${S}"/bootstrap.toml
                # Suppresses a warning about tracking changes which we don't 
care about.
                change-id = "ignore"
@@ -495,7 +568,9 @@ src_configure() {
                bindir = "bin"
                libdir = "lib"
                mandir = "share/man"
+
                [rust]
+               codegen-backends = [${codegen_backends}]
                # https://github.com/rust-lang/rust/issues/54872
                codegen-units-std = 1
                optimize = true
@@ -828,6 +903,20 @@ src_install() {
                insinto "/usr/lib/${PN}/${SLOT}/dist"
                doins -r "${S}/build/dist/."
        fi
+
+       if use rust_codegen_backends_gcc ; then
+               # XXX: This is a hack because dist/install support is incomplete
+               # for now (as of 1.91.0, even with a patch I've hacked up).
+               cd "${ED}/usr/lib/${PN}/${SLOT}/lib/rustlib" || die
+
+               # TODO: Replace glob with Rust target
+               tar --strip-components=4 -xvf 
"${S}"/build/dist/rustc-codegen-gcc*.tar.xz || die
+
+               # Now place libgccjit.so in too
+               cd */codegen-backends/ || die
+               # TODO: Replace 'host' with Rust target
+               cp "${S}"/build/host/gcc/install/lib/libgccjit.so 
../lib/libgccjit.so.0 || die
+       fi
 }
 
 pkg_postinst() {
diff --git a/dev-lang/rust/rust-9999.ebuild b/dev-lang/rust/rust-9999.ebuild
index ea39085f1f6e7..ec9d2eb1ab583 100644
--- a/dev-lang/rust/rust-9999.ebuild
+++ b/dev-lang/rust/rust-9999.ebuild
@@ -8,11 +8,11 @@ EAPI=8
 LLVM_COMPAT=( 21 )
 PYTHON_COMPAT=( python3_{11..14} )
 
-RUST_PATCH_VER=${PV#*_p}
-RUST_MAX_VER=${PV%%_*}
+RUST_PATCH_VER=${PVR}
 
+RUST_MAX_VER=${PV%%_*}
 if [[ ${PV} == *9999* ]]; then
-       RUST_MIN_VER="1.91.0" # Update this as new `beta` releases come out.
+       RUST_MIN_VER="1.88.0" # Update this as new `beta` releases come out.
 elif [[ ${PV} == *beta* ]]; then
        RUST_MAX_VER="$(ver_cut 1).$(ver_cut 2).0"
        RUST_MIN_VER="$(ver_cut 1).$(($(ver_cut 2) - 1)).0"
@@ -30,17 +30,26 @@ elif [[ ${PV} == *beta* ]]; then
        # curl -Ls static.rust-lang.org/dist/channel-rust-beta.toml | grep 
beta-src.tar.xz
        betaver=${PV//*beta}
        BETA_SNAPSHOT="${betaver:0:4}-${betaver:4:2}-${betaver:6:2}"
+       # compiler/rustc_codegen_gcc/libgccjit.version
+       #GCC_FORK_COMMIT="4e995bd73c4490edfe5080ec6014d63aa9abed5f"
+       GCC_FORK_COMMIT="b93730ce97c738bdb9209aa973d3fc6fd4ce1d81"
        MY_P="rustc-beta"
-       
SRC_URI="https://static.rust-lang.org/dist/${BETA_SNAPSHOT}/rustc-beta-src.tar.xz
 -> rustc-${PV}-src.tar.xz
+       SRC_URI="
+               
https://static.rust-lang.org/dist/${BETA_SNAPSHOT}/rustc-beta-src.tar.xz -> 
rustc-${PV}-src.tar.xz
                
https://gitweb.gentoo.org/proj/rust-patches.git/snapshot/rust-patches-${RUST_PATCH_VER}.tar.bz2
+               rust_codegen_backends_gcc? ( 
https://github.com/rust-lang/gcc/archive/${GCC_FORK_COMMIT}.tar.gz -> 
gcc-fork-${GCC_FORK_COMMIT}.tar.gz )
                verify-sig? ( 
https://static.rust-lang.org/dist/${BETA_SNAPSHOT}/rustc-beta-src.tar.xz.asc
                        -> rustc-${PV}-src.tar.xz.asc )
        "
        S="${WORKDIR}/${MY_P}-src"
 else
+       # compiler/rustc_codegen_gcc/libgccjit.version
+       GCC_FORK_COMMIT="04ce66d8c918de9273bd7101638ad8724edf5e21"
        MY_P="rustc-${PV}"
-       SRC_URI="https://static.rust-lang.org/dist/${MY_P}-src.tar.xz
+       SRC_URI="
+               https://static.rust-lang.org/dist/${MY_P}-src.tar.xz
                
https://gitweb.gentoo.org/proj/rust-patches.git/snapshot/rust-patches-${RUST_PATCH_VER}.tar.bz2
+               rust_codegen_backends_gcc? ( 
https://github.com/rust-lang/gcc/archive/${GCC_FORK_COMMIT}.tar.gz -> 
gcc-fork-${GCC_FORK_COMMIT}.tar.gz )
                verify-sig? ( 
https://static.rust-lang.org/dist/${MY_P}-src.tar.xz.asc )
        "
        S="${WORKDIR}/${MY_P}-src"
@@ -69,10 +78,22 @@ done
 ALL_RUST_SYSROOTS=( bpf wasm )
 ALL_RUST_SYSROOTS=( "${ALL_RUST_SYSROOTS[@]/#/rust_sysroots_}" )
 
+# The order here is important. The first is default. We have to pick LLVM
+# first for now (if enabled) to avoid some hassle with mangling RUSTFLAGS
+# depending on what an ebuild supports if we know it's broken with an
+# alternative backend.
+#
+# Further, note that the runtime toggle for choosing the backend is marked 
unstable:
+# 
https://doc.rust-lang.org/beta/unstable-book/compiler-flags/codegen-backend.html
+#
+# TODO: cranelift?
+ALL_RUST_CODEGEN_BACKENDS=( llvm gcc )
+ALL_RUST_CODEGEN_BACKENDS=( 
"${ALL_RUST_CODEGEN_BACKENDS[@]/#/rust_codegen_backends_}" )
+
 LICENSE="|| ( MIT Apache-2.0 ) BSD BSD-1 BSD-2 BSD-4"
 SLOT="${PV%%_*}" # Beta releases get to share the same SLOT as the eventual 
stable
 
-IUSE="big-endian clippy cpu_flags_x86_sse2 debug dist doc llvm-libunwind lto 
rustfmt rust-analyzer rust-src system-llvm test ${ALL_LLVM_TARGETS[*]} 
${ALL_RUST_SYSROOTS[*]}"
+IUSE="big-endian clippy cpu_flags_x86_sse2 debug dist doc llvm-libunwind lto 
rustfmt rust-analyzer rust-src system-llvm test ${ALL_LLVM_TARGETS[*]} 
${ALL_RUST_SYSROOTS[*]} ${ALL_RUST_CODEGEN_BACKENDS[*]}"
 
 if [[ ${PV} = *9999* ]]; then
        # These USE flags require nightly rust
@@ -117,13 +138,22 @@ DEPEND="
        net-misc/curl:=[http2,ssl]
        sys-libs/zlib:=
        dev-libs/openssl:0=
-       system-llvm? (
-               ${LLVM_DEPEND[*]}
-               llvm-libunwind? ( llvm-runtimes/libunwind:= )
+       rust_codegen_backends_gcc? (
+               app-arch/zstd:=
+               dev-libs/gmp:=
+               dev-libs/isl:=
+               dev-libs/mpc:=
+               dev-libs/mpfr:=
        )
-       !system-llvm? (
-               !llvm-libunwind? (
-                       elibc_musl? ( sys-libs/libunwind:= )
+       rust_codegen_backends_llvm? (
+               system-llvm? (
+                       ${LLVM_DEPEND[*]}
+                       llvm-libunwind? ( llvm-runtimes/libunwind:= )
+               )
+               !system-llvm? (
+                       !llvm-libunwind? (
+                               elibc_musl? ( sys-libs/libunwind:= )
+                       )
                )
        )
 "
@@ -317,9 +347,23 @@ src_unpack() {
        elif use verify-sig ; then
                # Patch tarballs are not signed (but we trust Gentoo infra)
                verify-sig_verify_detached 
"${DISTDIR}"/rustc-${PV}-src.tar.xz{,.asc}
-               default
+               unpack rustc-${PV}-src.tar.xz{,.asc}
+               unpack rust-patches-${RUST_PATCH_VER}.tar.bz2
+
+               if use rust_codegen_backends_gcc ; then
+                       (
+                               cd "${S}"/src || die
+                               rm gcc/notice.txt || die
+                               rmdir gcc || die
+                               unpack gcc-fork-${GCC_FORK_COMMIT}.tar.gz
+                               mv gcc-${GCC_FORK_COMMIT} gcc
+                       )
+               fi
        else
-               default
+               unpack rustc-${PV}-src.tar.xz{,.asc}
+               unpack rust-patches-${RUST_PATCH_VER}.tar.bz2
+               # TODO: system-gcc
+               use rust_codegen_backends_gcc && unpack 
gcc-fork-${GCC_FORK_COMMIT}.tar.gz
        fi
 }
 
@@ -339,7 +383,22 @@ src_prepare() {
                export RUSTFLAGS+=" -C link-arg=-fuse-ld=lld"
        fi
 
+       if use rust_codegen_backends_gcc ; then
+               # We should have all of these available on Gentoo systems.
+               cat <<-EOF > src/gcc/contrib/download_prerequisites || die
+               #!/bin/sh
+               exit 0
+               EOF
+               chmod +x src/gcc/contrib/download_prerequisites || die
+       fi
+
        default
+
+       if use rust_codegen_backends_gcc ; then
+               eapply 
"${FILESDIR}"/rustc_codegen_gcc-include-lib-path-bootstrap.patch
+               eapply "${FILESDIR}"/rustc_codegen_gcc-dist.patch
+               eapply -d "${S}"/compiler/rustc_codegen_gcc -p1 -- 
"${FILESDIR}"/rustc_codegen_gcc-avoid-oom.patch
+       fi
 }
 
 src_configure() {
@@ -383,6 +442,8 @@ src_configure() {
        use rustfmt && tools+=',"rustfmt"'
        use rust-analyzer && 
tools+=',"rust-analyzer","rust-analyzer-proc-macro-srv"'
        use rust-src && tools+=',"src"'
+       # TODO: see if these are (all) still needed
+       use rust_codegen_backends_gcc && 
tools+=',"rustc-dev","gcc","rustc-codegen-gcc"'
 
        if [[ ${PV} == *9999* ]]; then
                use miri && tools+=',"miri"'
@@ -419,8 +480,20 @@ src_configure() {
                        ;;
        esac
 
-       # TODO: Add optimized-compiler-builtins for system-llvm to avoid
-       # building bundled compiler-rt.
+       # XXX: Clean this up?
+       codegen_backends=''
+       local codegen_backend
+       for codegen_backend in "${RUST_CODEGEN_BACKENDS[@]}" ; do
+               use rust_codegen_backends_${codegen_backend} && \
+                       codegen_backends+="\"${codegen_backend}\","
+       done
+
+       # XXX: Needed for dist target and some of the switches?
+       if use rust_codegen_backends_gcc ; then
+               ewarn "Forcing build as nightly for GCC codegen backend"
+               build_channel="nightly"
+       fi
+
        cat <<- _EOF_ > "${S}"/bootstrap.toml
                # Suppresses a warning about tracking changes which we don't 
care about.
                change-id = "ignore"
@@ -495,7 +568,9 @@ src_configure() {
                bindir = "bin"
                libdir = "lib"
                mandir = "share/man"
+
                [rust]
+               codegen-backends = [${codegen_backends}]
                # https://github.com/rust-lang/rust/issues/54872
                codegen-units-std = 1
                optimize = true
@@ -828,6 +903,20 @@ src_install() {
                insinto "/usr/lib/${PN}/${SLOT}/dist"
                doins -r "${S}/build/dist/."
        fi
+
+       if use rust_codegen_backends_gcc ; then
+               # XXX: This is a hack because dist/install support is incomplete
+               # for now (as of 1.91.0, even with a patch I've hacked up).
+               cd "${ED}/usr/lib/${PN}/${SLOT}/lib/rustlib" || die
+
+               # TODO: Replace glob with Rust target
+               tar --strip-components=4 -xvf 
"${S}"/build/dist/rustc-codegen-gcc*.tar.xz || die
+
+               # Now place libgccjit.so in too
+               cd */codegen-backends/ || die
+               # TODO: Replace 'host' with Rust target
+               cp "${S}"/build/host/gcc/install/lib/libgccjit.so 
../lib/libgccjit.so.0 || die
+       fi
 }
 
 pkg_postinst() {
diff --git a/profiles/base/make.defaults b/profiles/base/make.defaults
index 1d272050d3758..11e8b9e5b9de2 100644
--- a/profiles/base/make.defaults
+++ b/profiles/base/make.defaults
@@ -12,7 +12,7 @@ USE_EXPAND_VALUES_KERNEL="Darwin linux SunOS"
 
 # Env vars to expand into USE vars.  Modifying this requires prior
 # discussion on [email protected].
-USE_EXPAND="ABI_MIPS ABI_S390 ABI_X86 ADA_TARGET ALSA_CARDS AMDGPU_TARGETS 
APACHE2_MODULES APACHE2_MPMS CALLIGRA_FEATURES CAMERAS COLLECTD_PLUGINS 
CPU_FLAGS_ARM CPU_FLAGS_PPC CPU_FLAGS_X86 CURL_SSL CURL_QUIC ELIBC FFTOOLS 
GPSD_PROTOCOLS GRUB_PLATFORMS GUILE_SINGLE_TARGET GUILE_TARGETS INPUT_DEVICES 
KERNEL L10N LCD_DEVICES LIBREOFFICE_EXTENSIONS LLVM_SLOT LLVM_TARGETS 
LUA_SINGLE_TARGET LUA_TARGETS NGINX_MODULES_HTTP NGINX_MODULES_MAIL 
NGINX_MODULES_STREAM OFFICE_IMPLEMENTATION OPENMPI_FABRICS 
OPENMPI_OFED_FEATURES OPENMPI_RM PERL_FEATURES PHP_TARGETS POSTGRES_TARGETS 
PYTHON_SINGLE_TARGET PYTHON_TARGETS QEMU_SOFTMMU_TARGETS QEMU_USER_TARGETS 
RUBY_TARGETS RUST_SYSROOTS SANE_BACKENDS UWSGI_PLUGINS VIDEO_CARDS 
VOICEMAIL_STORAGE XTABLES_ADDONS"
+USE_EXPAND="ABI_MIPS ABI_S390 ABI_X86 ADA_TARGET ALSA_CARDS AMDGPU_TARGETS 
APACHE2_MODULES APACHE2_MPMS CALLIGRA_FEATURES CAMERAS COLLECTD_PLUGINS 
CPU_FLAGS_ARM CPU_FLAGS_PPC CPU_FLAGS_X86 CURL_SSL CURL_QUIC ELIBC FFTOOLS 
GPSD_PROTOCOLS GRUB_PLATFORMS GUILE_SINGLE_TARGET GUILE_TARGETS INPUT_DEVICES 
KERNEL L10N LCD_DEVICES LIBREOFFICE_EXTENSIONS LLVM_SLOT LLVM_TARGETS 
LUA_SINGLE_TARGET LUA_TARGETS NGINX_MODULES_HTTP NGINX_MODULES_MAIL 
NGINX_MODULES_STREAM OFFICE_IMPLEMENTATION OPENMPI_FABRICS 
OPENMPI_OFED_FEATURES OPENMPI_RM PERL_FEATURES PHP_TARGETS POSTGRES_TARGETS 
PYTHON_SINGLE_TARGET PYTHON_TARGETS QEMU_SOFTMMU_TARGETS QEMU_USER_TARGETS 
RUBY_TARGETS RUST_CODEGEN_BACKENDS RUST_SYSROOTS SANE_BACKENDS UWSGI_PLUGINS 
VIDEO_CARDS VOICEMAIL_STORAGE XTABLES_ADDONS"
 
 # USE_EXPAND variables whose contents are not shown in package manager
 # output. Changes need discussion on gentoo-dev.
diff --git a/profiles/base/package.use.force b/profiles/base/package.use.force
index 5ee5e2e152ef0..b71a732574178 100644
--- a/profiles/base/package.use.force
+++ b/profiles/base/package.use.force
@@ -1,6 +1,10 @@
 # Copyright 1999-2025 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
+# Sam James <[email protected]> (2025-10-27)
+# Other backends are experimental for now. Force the upstream default (LLVM).
+dev-lang/rust rust_codegen_backends_llvm
+
 # Andreas Sturmlechner <[email protected]> (2025-06-22)
 # This is currently more footgun than real option. Bug #958638
 <kde-plasma/kwin-6.5.0 X
diff --git a/profiles/base/package.use.mask b/profiles/base/package.use.mask
index 489969f291887..ea27c6b8ef621 100644
--- a/profiles/base/package.use.mask
+++ b/profiles/base/package.use.mask
@@ -6,6 +6,11 @@
 
 # New entries go on top.
 
+# Sam James <[email protected]> (2025-10-31)
+# Other backends are experimental for now. LLVM is forced on and mask other
+# backends.
+dev-lang/rust rust_codegen_backends_gcc
+
 # Sam James <[email protected]> (2025-10-29)
 # Help Portage resolve app-crypt/gnupg[verify-sig] with the 
app-alternatives/gpg
 # transition. The any-of dep in verify-sig.eclass helps a bit, but it struggles
diff --git a/acct-group/clock/clock-0.ebuild 
b/profiles/desc/rust_codegen_backends.desc
similarity index 51%
copy from acct-group/clock/clock-0.ebuild
copy to profiles/desc/rust_codegen_backends.desc
index 57a7ba93f17e5..9dcb4c7082e16 100644
--- a/acct-group/clock/clock-0.ebuild
+++ b/profiles/desc/rust_codegen_backends.desc
@@ -1,8 +1,5 @@
 # Copyright 2025 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-EAPI=8
-
-inherit acct-group
-
-ACCT_GROUP_ID=550
+llvm - Backend based on llvm-core/llvm
+gcc - Backend based on sys-devel/gcc, using libgccjit
diff --git a/profiles/desc/rust_sysroots.desc b/profiles/desc/rust_sysroots.desc
index fe9fcdacf5fc1..741a56205d1ff 100644
--- a/profiles/desc/rust_sysroots.desc
+++ b/profiles/desc/rust_sysroots.desc
@@ -1,4 +1,4 @@
-# Copyright 2025 Gentoo Authors.
+# Copyright 2025 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 bpf - Berkeley Packet Filter target
-- 
2.51.2



Reply via email to