Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fe0db9c
update rotate operation doc
notJoon Aug 11, 2025
cbc3860
Use rust rather than LLVM target features in the target spec
bjorn3 Nov 21, 2025
2af849a
Merge commit '55171cfa8b53970e06dcd2f5f2e2b8d82eeb0885' into subtree-…
GuillaumeGomez Nov 26, 2025
a7ea98b
Update GCC commit
GuillaumeGomez Nov 26, 2025
8059907
Update GCC submodule
GuillaumeGomez Nov 26, 2025
d923fdd
Auto merge of #149348 - GuillaumeGomez:subtree-update_cg_gcc_2025-11-…
bors Nov 28, 2025
4054d07
Remove -Zoom=panic
bjorn3 Oct 15, 2025
1c89fe9
Remove an unnecessary `unwrap` in `rustc_codegen_gcc`
AudaciousAxiom Nov 29, 2025
5c467cb
Allow PowerPC spe_acc as clobber-only register
pmur Dec 3, 2025
701b9ba
Merge commit 'dab6863ce82346cf56c88b6f90a146200358207f' into subtree-…
GuillaumeGomez Dec 4, 2025
8d9b1d0
Auto merge of #149642 - GuillaumeGomez:subtree-update_cg_gcc_2025-12-…
bors Dec 4, 2025
c0d4f5f
Move the libgccjit.so file in a target directory
antoyo Nov 28, 2025
8e77eeb
Move to rustlib directory
antoyo Nov 29, 2025
b00418c
Fix lib path
antoyo Nov 29, 2025
ff29461
Remove libgccjit_path function
antoyo Dec 5, 2025
e614396
Fix clippy lint in `cg_gcc`
GuillaumeGomez Dec 9, 2025
c53b4c3
Rollup merge of #147725 - bjorn3:remove_oom_panic, r=Amanieu
matthiaskrgr Dec 10, 2025
bc06068
Rollup merge of #149458 - GuillaumeGomez:clippy-cg_gcc, r=kobzol
matthiaskrgr Dec 10, 2025
a95aaca
Adapt and fix `cg_gcc` to the overhauled filename remapping
Urgau Dec 6, 2025
824f41e
Use `let...else` instead of `match foo { ... _ => return };` and `if …
estebank Dec 9, 2025
8ff1c63
Rollup merge of #145278 - notJoon:doc/rotate-operation, r=antoyo
jhpratt Dec 13, 2025
2afb92f
Rollup merge of #148837 - estebank:let-else, r=Kivooeo
jhpratt Dec 13, 2025
09c34cb
Auto merge of #149709 - Urgau:overhaul-filenames, r=davidtwco
bors Dec 13, 2025
f0418b3
When we cannot load libgccjit.so, show the paths that were tried
antoyo Dec 11, 2025
11bc2e0
codegen: implement `repr(scalable)`
davidtwco Jul 10, 2025
cf522c0
Merge branch 'master' into sync_from_rust_2025_12_20
antoyo Dec 20, 2025
cd8cc6f
Update to nightly-2025-12-20
antoyo Dec 20, 2025
93cf63b
Move libgccjit.so to the new location within the sysroot
antoyo Dec 20, 2025
1ac26a7
Add new failing tests
antoyo Dec 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions build_system/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,20 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu

// Symlink libgccjit.so to sysroot.
let lib_path = start_dir.join("sysroot").join("lib");
let rustlib_target_path = lib_path
.join("rustlib")
.join(&config.host_triple)
.join("codegen-backends")
.join("lib")
.join(&config.target_triple);
let libgccjit_path =
PathBuf::from(config.gcc_path.as_ref().expect("libgccjit should be set by this point"))
.join("libgccjit.so");
let libgccjit_in_sysroot_path = lib_path.join("libgccjit.so");
let libgccjit_in_sysroot_path = rustlib_target_path.join("libgccjit.so");
// First remove the file to be able to create the symlink even when the file already exists.
let _ = fs::remove_file(&libgccjit_in_sysroot_path);
create_dir(&lib_path)?;
symlink(libgccjit_path, libgccjit_in_sysroot_path)
create_dir(&rustlib_target_path)?;
symlink(libgccjit_path, &libgccjit_in_sysroot_path)
.map_err(|error| format!("Cannot create symlink for libgccjit.so: {}", error))?;

let library_dir = start_dir.join("sysroot_src").join("library");
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-11-24"
channel = "nightly-2025-12-20"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
39 changes: 1 addition & 38 deletions src/allocator.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#[cfg(feature = "master")]
use gccjit::FnAttribute;
use gccjit::{Context, FunctionType, RValue, ToRValue, Type};
use gccjit::{Context, FunctionType, ToRValue, Type};
use rustc_ast::expand::allocator::{
AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name,
};
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::OomStrategy;
use rustc_symbol_mangling::mangle_internal_symbol;

use crate::GccContext;
Expand Down Expand Up @@ -59,14 +58,6 @@ pub(crate) unsafe fn codegen(
create_wrapper_function(tcx, context, &from_name, Some(&to_name), &types, output);
}

create_const_value_function(
tcx,
context,
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
i8,
context.new_rvalue_from_int(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as i32),
);

create_wrapper_function(
tcx,
context,
Expand All @@ -77,34 +68,6 @@ pub(crate) unsafe fn codegen(
);
}

fn create_const_value_function(
tcx: TyCtxt<'_>,
context: &Context<'_>,
name: &str,
output: Type<'_>,
value: RValue<'_>,
) {
let func = context.new_function(None, FunctionType::Exported, output, &[], name, false);

#[cfg(feature = "master")]
{
func.add_attribute(FnAttribute::Visibility(symbol_visibility_to_gcc(
tcx.sess.default_visibility(),
)));

// FIXME(antoyo): cg_llvm sets AlwaysInline, but AlwaysInline is different in GCC and using
// it here will causes linking errors when using LTO.
func.add_attribute(FnAttribute::Inline);
}

if tcx.sess.must_emit_unwind_tables() {
// TODO(antoyo): emit unwind tables.
}

let block = func.new_block("entry");
block.end_with_return(None, value);
}

fn create_wrapper_function(
tcx: TyCtxt<'_>,
context: &Context<'_>,
Expand Down
23 changes: 16 additions & 7 deletions src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,16 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
}
("r", dummy_output_type(self.cx, reg.reg_class()))
} else {
// `clobber_abi` can add lots of clobbers that are not supported by the target,
// such as AVX-512 registers, so we just ignore unsupported registers
let is_target_supported =
reg.reg_class().supported_types(asm_arch, true).iter().any(
let is_target_supported = match reg.reg_class() {
// `clobber_abi` clobbers spe_acc on all PowerPC targets. This
// register is unique to the powerpc*spe target, and the target
// is not supported by gcc. Ignore it.
InlineAsmRegClass::PowerPC(
PowerPCInlineAsmRegClass::spe_acc,
) => false,
// `clobber_abi` can add lots of clobbers that are not supported by the target,
// such as AVX-512 registers, so we just ignore unsupported registers
x => x.supported_types(asm_arch, true).iter().any(
|&(_, feature)| {
if let Some(feature) = feature {
self.tcx
Expand All @@ -222,7 +228,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
true // Register class is unconditionally supported
}
},
);
),
};

if is_target_supported && !clobbers.contains(&reg_name) {
clobbers.push(reg_name);
Expand Down Expand Up @@ -710,7 +717,8 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
PowerPCInlineAsmRegClass::cr
| PowerPCInlineAsmRegClass::ctr
| PowerPCInlineAsmRegClass::lr
| PowerPCInlineAsmRegClass::xer,
| PowerPCInlineAsmRegClass::xer
| PowerPCInlineAsmRegClass::spe_acc,
) => {
unreachable!("clobber-only")
}
Expand Down Expand Up @@ -793,7 +801,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
PowerPCInlineAsmRegClass::cr
| PowerPCInlineAsmRegClass::ctr
| PowerPCInlineAsmRegClass::lr
| PowerPCInlineAsmRegClass::xer,
| PowerPCInlineAsmRegClass::xer
| PowerPCInlineAsmRegClass::spe_acc,
) => {
unreachable!("clobber-only")
}
Expand Down
12 changes: 8 additions & 4 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,12 +500,12 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
}

fn set_rvalue_location<'a, 'gcc, 'tcx>(
bx: &mut Builder<'a, 'gcc, 'tcx>,
_bx: &mut Builder<'a, 'gcc, 'tcx>,
rvalue: RValue<'gcc>,
) -> RValue<'gcc> {
if bx.location.is_some() {
#[cfg(feature = "master")]
rvalue.set_location(bx.location.unwrap());
#[cfg(feature = "master")]
if let Some(location) = _bx.location {
rvalue.set_location(location);
}
rvalue
}
Expand Down Expand Up @@ -943,6 +943,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
.get_address(self.location)
}

fn scalable_alloca(&mut self, _elt: u64, _align: Align, _element_ty: Ty<'_>) -> RValue<'gcc> {
todo!()
}

fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
let block = self.llbb();
let function = block.get_function();
Expand Down
28 changes: 5 additions & 23 deletions src/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,29 +297,11 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
let pos = span.lo();
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
match file.name {
rustc_span::FileName::Real(ref name) => match *name {
rustc_span::RealFileName::LocalPath(ref name) => {
if let Some(name) = name.to_str() {
self.context.new_location(name, line as i32, col as i32)
} else {
Location::null()
}
}
rustc_span::RealFileName::Remapped {
ref local_path,
virtual_name: ref _unused,
} => {
if let Some(name) = local_path.as_ref() {
if let Some(name) = name.to_str() {
self.context.new_location(name, line as i32, col as i32)
} else {
Location::null()
}
} else {
Location::null()
}
}
},
rustc_span::FileName::Real(ref name) => self.context.new_location(
name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(),
line as i32,
col as i32,
),
_ => Location::null(),
}
}
Expand Down
15 changes: 9 additions & 6 deletions src/gcc_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec<String> {
// should be taken in cases like these.
let mut features = vec![];

// Features implied by an implicit or explicit `--target`.
features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));

// -Ctarget-features
target_features::flag_to_backend_features(sess, |feature, enable| {
let mut extend_backend_features = |feature: &str, enable: bool| {
// We run through `to_gcc_features` when
// passing requests down to GCC. This means that all in-language
// features also work on the command line instead of having two
Expand All @@ -48,7 +44,13 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec<String> {
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
.map(|feature| if !enable { format!("-{}", feature) } else { feature.to_string() }),
);
});
};

// Features implied by an implicit or explicit `--target`.
target_features::target_spec_to_backend_features(sess, &mut extend_backend_features);

// -Ctarget-features
target_features::flag_to_backend_features(sess, extend_backend_features);

gcc_features_by_flags(sess, &mut features);

Expand All @@ -66,6 +68,7 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]>
(&Arch::X86 | &Arch::X86_64, "rdrand") => smallvec!["rdrnd"],
(&Arch::X86 | &Arch::X86_64, "bmi1") => smallvec!["bmi"],
(&Arch::X86 | &Arch::X86_64, "cmpxchg16b") => smallvec!["cx16"],
(&Arch::X86 | &Arch::X86_64, "lahfsahf") => smallvec!["sahf"],
(&Arch::X86 | &Arch::X86_64, "avx512vaes") => smallvec!["vaes"],
(&Arch::X86 | &Arch::X86_64, "avx512gfni") => smallvec!["gfni"],
(&Arch::X86 | &Arch::X86_64, "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
Expand Down
7 changes: 4 additions & 3 deletions src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,9 +424,10 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}
sym::bitreverse => self.bit_reverse(width, args[0].immediate()),
sym::rotate_left | sym::rotate_right => {
// TODO(antoyo): implement using algorithm from:
// Using optimized branchless algorithm from:
// https://blog.regehr.org/archives/1063
// for other platforms.
// This implementation uses the pattern (x<<n) | (x>>(-n&(width-1)))
// which generates efficient code for other platforms.
let is_left = name == sym::rotate_left;
let val = args[0].immediate();
let raw_shift = args[1].immediate();
Expand Down Expand Up @@ -467,7 +468,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
let layout = self.layout_of(tp_ty).layout;
let _use_integer_compare = match layout.backend_repr() {
Scalar(_) | ScalarPair(_, _) => true,
SimdVector { .. } => false,
SimdVector { .. } | ScalableVector { .. } => false,
Memory { .. } => {
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
Expand Down
31 changes: 15 additions & 16 deletions src/intrinsic/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,24 +774,23 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return Err(());
}};
}
let (elem_ty_str, elem_ty, cast_type) = if let ty::Float(ref f) = *in_elem.kind() {
let elem_ty = bx.cx.type_float_from_ty(*f);
match f.bit_width() {
16 => ("", elem_ty, Some(bx.cx.double_type)),
32 => ("f", elem_ty, None),
64 => ("", elem_ty, None),
_ => {
return_error!(InvalidMonomorphization::FloatingPointVector {
span,
name,
f_ty: *f,
in_ty
});
}
}
} else {
let ty::Float(ref f) = *in_elem.kind() else {
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
};
let elem_ty = bx.cx.type_float_from_ty(*f);
let (elem_ty_str, elem_ty, cast_type) = match f.bit_width() {
16 => ("", elem_ty, Some(bx.cx.double_type)),
32 => ("f", elem_ty, None),
64 => ("", elem_ty, None),
_ => {
return_error!(InvalidMonomorphization::FloatingPointVector {
span,
name,
f_ty: *f,
in_ty
});
}
};

let vec_ty = bx.cx.type_vector(elem_ty, in_len);

Expand Down
35 changes: 25 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,12 @@ pub struct GccCodegenBackend {

static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false);

fn libgccjit_path(sysroot_path: &Path) -> PathBuf {
let sysroot_lib_dir = sysroot_path.join("lib");
sysroot_lib_dir.join("libgccjit.so")
}

fn load_libgccjit_if_needed(sysroot_path: &Path) {
fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) {
if gccjit::is_loaded() {
// Do not load a libgccjit second time.
return;
}

let libgccjit_target_lib_file = libgccjit_path(sysroot_path);
let path = libgccjit_target_lib_file.to_str().expect("libgccjit path");

let string = CString::new(path).expect("string to libgccjit path");
Expand All @@ -212,17 +206,38 @@ impl CodegenBackend for GccCodegenBackend {
}

fn init(&self, sess: &Session) {
fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf {
let rustlib_path =
rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target);
sysroot_path
.join(rustlib_path)
.join("codegen-backends")
.join("lib")
.join(sess.target.llvm_target.as_ref())
.join("libgccjit.so")
}

// We use all_paths() instead of only path() in case the path specified by --sysroot is
// invalid.
// This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null.
for path in sess.opts.sysroot.all_paths() {
let libgccjit_target_lib_file = libgccjit_path(path);
if let Ok(true) = fs::exists(libgccjit_target_lib_file) {
load_libgccjit_if_needed(path);
let libgccjit_target_lib_file = file_path(path, sess);
if let Ok(true) = fs::exists(&libgccjit_target_lib_file) {
load_libgccjit_if_needed(&libgccjit_target_lib_file);
break;
}
}

if !gccjit::is_loaded() {
let mut paths = vec![];
for path in sess.opts.sysroot.all_paths() {
let libgccjit_target_lib_file = file_path(path, sess);
paths.push(libgccjit_target_lib_file);
}

panic!("Could not load libgccjit.so. Attempted paths: {:#?}", paths);
}

#[cfg(feature = "master")]
{
let target_cpu = target_cpu(sess);
Expand Down
4 changes: 4 additions & 0 deletions src/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
);
}
BackendRepr::Memory { .. } => {}
BackendRepr::ScalableVector { .. } => todo!(),
}

let name = match *layout.ty.kind() {
Expand Down Expand Up @@ -179,6 +180,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
fn is_gcc_immediate(&self) -> bool {
match self.backend_repr {
BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true,
// FIXME(rustc_scalable_vector): Not yet implemented in rustc_codegen_gcc.
BackendRepr::ScalableVector { .. } => todo!(),
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
}
}
Expand All @@ -188,6 +191,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
BackendRepr::ScalarPair(..) => true,
BackendRepr::Scalar(_)
| BackendRepr::SimdVector { .. }
| BackendRepr::ScalableVector { .. }
| BackendRepr::Memory { .. } => false,
}
}
Expand Down
Loading