Merge pull request #820 from rust-lang/sync_from_rust_2025_12_20
Sync from rust 2025/12/20
This commit is contained in:
commit
02f889aec5
12 changed files with 106 additions and 111 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-11-24"
|
||||
channel = "nightly-2025-12-20"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -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<'_>,
|
||||
|
|
|
|||
23
src/asm.rs
23
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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"],
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -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`),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
35
src/lib.rs
35
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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue