diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 27476465d74..9b7ee8380ca 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -111,14 +111,20 @@ pub fn build_sysroot(env: &HashMap, 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"); diff --git a/rust-toolchain b/rust-toolchain index f9645451e96..86ae738d448 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-11-24" +channel = "nightly-2025-12-20" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/allocator.rs b/src/allocator.rs index 647569694b0..1f464d7e122 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -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; @@ -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, @@ -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<'_>, diff --git a/src/asm.rs b/src/asm.rs index f237861b159..ceb3dd3ffed 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -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 @@ -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(®_name) { clobbers.push(reg_name); @@ -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") } @@ -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") } diff --git a/src/builder.rs b/src/builder.rs index c0519f7a68e..79228c20d29 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -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 } @@ -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(); diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 3979f62987f..53d3670c152 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -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(), } } diff --git a/src/gcc_util.rs b/src/gcc_util.rs index e4e2dfdd564..330b5ff6828 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -33,11 +33,7 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec { // 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 @@ -48,7 +44,13 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec { .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); @@ -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"], diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 84fbd92eb29..3c7ffa94253 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -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&(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(); @@ -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`), diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index c7ed887b30d..39b4bb3ebef 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -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); diff --git a/src/lib.rs b/src/lib.rs index c1506ee6176..96d3a0024f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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"); @@ -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); diff --git a/src/type_of.rs b/src/type_of.rs index 93202483eed..68fca5a17ad 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -85,6 +85,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( ); } BackendRepr::Memory { .. } => {} + BackendRepr::ScalableVector { .. } => todo!(), } let name = match *layout.ty.kind() { @@ -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, } } @@ -188,6 +191,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { BackendRepr::ScalarPair(..) => true, BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } + | BackendRepr::ScalableVector { .. } | BackendRepr::Memory { .. } => false, } } diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 2380bd0fc13..99a80fa7e4f 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -88,3 +88,12 @@ tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs tests/ui/iterators/rangefrom-overflow-debug.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