Merge pull request #820 from rust-lang/sync_from_rust_2025_12_20

Sync from rust 2025/12/20
This commit is contained in:
antoyo 2025-12-20 18:08:23 -05:00 committed by GitHub
commit 02f889aec5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 106 additions and 111 deletions

View file

@ -111,14 +111,20 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
// Symlink libgccjit.so to sysroot. // Symlink libgccjit.so to sysroot.
let lib_path = start_dir.join("sysroot").join("lib"); 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 = let libgccjit_path =
PathBuf::from(config.gcc_path.as_ref().expect("libgccjit should be set by this point")) PathBuf::from(config.gcc_path.as_ref().expect("libgccjit should be set by this point"))
.join("libgccjit.so"); .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. // 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); let _ = fs::remove_file(&libgccjit_in_sysroot_path);
create_dir(&lib_path)?; create_dir(&rustlib_target_path)?;
symlink(libgccjit_path, libgccjit_in_sysroot_path) symlink(libgccjit_path, &libgccjit_in_sysroot_path)
.map_err(|error| format!("Cannot create symlink for libgccjit.so: {}", error))?; .map_err(|error| format!("Cannot create symlink for libgccjit.so: {}", error))?;
let library_dir = start_dir.join("sysroot_src").join("library"); let library_dir = start_dir.join("sysroot_src").join("library");

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly-2025-11-24" channel = "nightly-2025-12-20"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"] components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -1,12 +1,11 @@
#[cfg(feature = "master")] #[cfg(feature = "master")]
use gccjit::FnAttribute; use gccjit::FnAttribute;
use gccjit::{Context, FunctionType, RValue, ToRValue, Type}; use gccjit::{Context, FunctionType, ToRValue, Type};
use rustc_ast::expand::allocator::{ use rustc_ast::expand::allocator::{
AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name, AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name,
}; };
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::config::OomStrategy;
use rustc_symbol_mangling::mangle_internal_symbol; use rustc_symbol_mangling::mangle_internal_symbol;
use crate::GccContext; use crate::GccContext;
@ -59,14 +58,6 @@ pub(crate) unsafe fn codegen(
create_wrapper_function(tcx, context, &from_name, Some(&to_name), &types, output); 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( create_wrapper_function(
tcx, tcx,
context, context,
@ -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( fn create_wrapper_function(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
context: &Context<'_>, context: &Context<'_>,

View file

@ -209,10 +209,16 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
} }
("r", dummy_output_type(self.cx, reg.reg_class())) ("r", dummy_output_type(self.cx, reg.reg_class()))
} else { } else {
// `clobber_abi` can add lots of clobbers that are not supported by the target, let is_target_supported = match reg.reg_class() {
// such as AVX-512 registers, so we just ignore unsupported registers // `clobber_abi` clobbers spe_acc on all PowerPC targets. This
let is_target_supported = // register is unique to the powerpc*spe target, and the target
reg.reg_class().supported_types(asm_arch, true).iter().any( // 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)| { |&(_, feature)| {
if let Some(feature) = feature { if let Some(feature) = feature {
self.tcx self.tcx
@ -222,7 +228,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
true // Register class is unconditionally supported true // Register class is unconditionally supported
} }
}, },
); ),
};
if is_target_supported && !clobbers.contains(&reg_name) { if is_target_supported && !clobbers.contains(&reg_name) {
clobbers.push(reg_name); clobbers.push(reg_name);
@ -710,7 +717,8 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
PowerPCInlineAsmRegClass::cr PowerPCInlineAsmRegClass::cr
| PowerPCInlineAsmRegClass::ctr | PowerPCInlineAsmRegClass::ctr
| PowerPCInlineAsmRegClass::lr | PowerPCInlineAsmRegClass::lr
| PowerPCInlineAsmRegClass::xer, | PowerPCInlineAsmRegClass::xer
| PowerPCInlineAsmRegClass::spe_acc,
) => { ) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
@ -793,7 +801,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
PowerPCInlineAsmRegClass::cr PowerPCInlineAsmRegClass::cr
| PowerPCInlineAsmRegClass::ctr | PowerPCInlineAsmRegClass::ctr
| PowerPCInlineAsmRegClass::lr | PowerPCInlineAsmRegClass::lr
| PowerPCInlineAsmRegClass::xer, | PowerPCInlineAsmRegClass::xer
| PowerPCInlineAsmRegClass::spe_acc,
) => { ) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }

View file

@ -500,12 +500,12 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
} }
fn set_rvalue_location<'a, '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: RValue<'gcc>,
) -> RValue<'gcc> { ) -> RValue<'gcc> {
if bx.location.is_some() { #[cfg(feature = "master")]
#[cfg(feature = "master")] if let Some(location) = _bx.location {
rvalue.set_location(bx.location.unwrap()); rvalue.set_location(location);
} }
rvalue rvalue
} }
@ -943,6 +943,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
.get_address(self.location) .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> { fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
let block = self.llbb(); let block = self.llbb();
let function = block.get_function(); let function = block.get_function();

View file

@ -297,29 +297,11 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
let pos = span.lo(); let pos = span.lo();
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos); let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
match file.name { match file.name {
rustc_span::FileName::Real(ref name) => match *name { rustc_span::FileName::Real(ref name) => self.context.new_location(
rustc_span::RealFileName::LocalPath(ref name) => { name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(),
if let Some(name) = name.to_str() { line as i32,
self.context.new_location(name, line as i32, col 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()
}
}
},
_ => Location::null(), _ => Location::null(),
} }
} }

View file

@ -33,11 +33,7 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec<String> {
// should be taken in cases like these. // should be taken in cases like these.
let mut features = vec![]; let mut features = vec![];
// Features implied by an implicit or explicit `--target`. let mut extend_backend_features = |feature: &str, enable: bool| {
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| {
// We run through `to_gcc_features` when // We run through `to_gcc_features` when
// passing requests down to GCC. This means that all in-language // passing requests down to GCC. This means that all in-language
// features also work on the command line instead of having two // features also work on the command line instead of having two
@ -48,7 +44,13 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec<String> {
.flat_map(|feat| to_gcc_features(sess, feat).into_iter()) .flat_map(|feat| to_gcc_features(sess, feat).into_iter())
.map(|feature| if !enable { format!("-{}", feature) } else { feature.to_string() }), .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); gcc_features_by_flags(sess, &mut features);
@ -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, "rdrand") => smallvec!["rdrnd"],
(&Arch::X86 | &Arch::X86_64, "bmi1") => smallvec!["bmi"], (&Arch::X86 | &Arch::X86_64, "bmi1") => smallvec!["bmi"],
(&Arch::X86 | &Arch::X86_64, "cmpxchg16b") => smallvec!["cx16"], (&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, "avx512vaes") => smallvec!["vaes"],
(&Arch::X86 | &Arch::X86_64, "avx512gfni") => smallvec!["gfni"], (&Arch::X86 | &Arch::X86_64, "avx512gfni") => smallvec!["gfni"],
(&Arch::X86 | &Arch::X86_64, "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], (&Arch::X86 | &Arch::X86_64, "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],

View file

@ -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::bitreverse => self.bit_reverse(width, args[0].immediate()),
sym::rotate_left | sym::rotate_right => { sym::rotate_left | sym::rotate_right => {
// TODO(antoyo): implement using algorithm from: // Using optimized branchless algorithm from:
// https://blog.regehr.org/archives/1063 // 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 is_left = name == sym::rotate_left;
let val = args[0].immediate(); let val = args[0].immediate();
let raw_shift = args[1].immediate(); let raw_shift = args[1].immediate();
@ -467,7 +468,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
let layout = self.layout_of(tp_ty).layout; let layout = self.layout_of(tp_ty).layout;
let _use_integer_compare = match layout.backend_repr() { let _use_integer_compare = match layout.backend_repr() {
Scalar(_) | ScalarPair(_, _) => true, Scalar(_) | ScalarPair(_, _) => true,
SimdVector { .. } => false, SimdVector { .. } | ScalableVector { .. } => false,
Memory { .. } => { Memory { .. } => {
// For rusty ABIs, small aggregates are actually passed // For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),

View file

@ -774,24 +774,23 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return Err(()); return Err(());
}}; }};
} }
let (elem_ty_str, elem_ty, cast_type) = if let ty::Float(ref f) = *in_elem.kind() { let ty::Float(ref f) = *in_elem.kind() else {
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 {
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); 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); let vec_ty = bx.cx.type_vector(elem_ty, in_len);

View file

@ -181,18 +181,12 @@ pub struct GccCodegenBackend {
static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false); static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false);
fn libgccjit_path(sysroot_path: &Path) -> PathBuf { fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) {
let sysroot_lib_dir = sysroot_path.join("lib");
sysroot_lib_dir.join("libgccjit.so")
}
fn load_libgccjit_if_needed(sysroot_path: &Path) {
if gccjit::is_loaded() { if gccjit::is_loaded() {
// Do not load a libgccjit second time. // Do not load a libgccjit second time.
return; return;
} }
let libgccjit_target_lib_file = libgccjit_path(sysroot_path);
let path = libgccjit_target_lib_file.to_str().expect("libgccjit path"); let path = libgccjit_target_lib_file.to_str().expect("libgccjit path");
let string = CString::new(path).expect("string to libgccjit path"); let string = CString::new(path).expect("string to libgccjit path");
@ -212,17 +206,38 @@ impl CodegenBackend for GccCodegenBackend {
} }
fn init(&self, sess: &Session) { 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 // We use all_paths() instead of only path() in case the path specified by --sysroot is
// invalid. // invalid.
// This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null. // This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null.
for path in sess.opts.sysroot.all_paths() { for path in sess.opts.sysroot.all_paths() {
let libgccjit_target_lib_file = libgccjit_path(path); let libgccjit_target_lib_file = file_path(path, sess);
if let Ok(true) = fs::exists(libgccjit_target_lib_file) { if let Ok(true) = fs::exists(&libgccjit_target_lib_file) {
load_libgccjit_if_needed(path); load_libgccjit_if_needed(&libgccjit_target_lib_file);
break; 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")] #[cfg(feature = "master")]
{ {
let target_cpu = target_cpu(sess); let target_cpu = target_cpu(sess);

View file

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

View file

@ -88,3 +88,12 @@ tests/ui/test-attrs/test-panic-while-printing.rs
tests/ui/thir-print/offset_of.rs tests/ui/thir-print/offset_of.rs
tests/ui/iterators/rangefrom-overflow-debug.rs tests/ui/iterators/rangefrom-overflow-debug.rs
tests/ui/iterators/rangefrom-overflow-overflow-checks.rs tests/ui/iterators/rangefrom-overflow-overflow-checks.rs
tests/ui/iterators/iter-filter-count-debug-check.rs
tests/ui/eii/codegen_single_crate.rs
tests/ui/eii/codegen_cross_crate.rs
tests/ui/eii/default/local_crate.rs
tests/ui/eii/multiple_impls.rs
tests/ui/eii/default/call_default.rs
tests/ui/eii/same-symbol.rs
tests/ui/eii/privacy1.rs
tests/ui/eii/default/call_impl.rs