diff options
| author | 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> | 2025-06-03 20:19:44 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-03 20:19:44 +0800 |
| commit | 033b829e0a5b33f0b383a3711b7635a7464cd6fc (patch) | |
| tree | 6c3a4faecdcff30608e6efd6a41b3b5fcc900aa0 /compiler/rustc_codegen_ssa/src | |
| parent | 10f2bcc95738423fbdf01ce3bb00e4092102c438 (diff) | |
| parent | b65ceb28e0cc639e3adc9d93b11ecc3228fac4c2 (diff) | |
| download | rust-033b829e0a5b33f0b383a3711b7635a7464cd6fc.tar.gz rust-033b829e0a5b33f0b383a3711b7635a7464cd6fc.zip | |
Merge pull request #2451 from jieyouxu/rustc-pull
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 59 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 52 |
2 files changed, 81 insertions, 30 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 58fa3c392ca..1a39a0c3fda 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3,7 +3,7 @@ mod raw_dylib; use std::collections::BTreeSet; use std::ffi::OsString; use std::fs::{File, OpenOptions, read}; -use std::io::{BufWriter, Write}; +use std::io::{BufReader, BufWriter, Write}; use std::ops::{ControlFlow, Deref}; use std::path::{Path, PathBuf}; use std::process::{Output, Stdio}; @@ -184,6 +184,12 @@ pub fn link_binary( ); } + if sess.target.binary_format == BinaryFormat::Elf { + if let Err(err) = warn_if_linked_with_gold(sess, &out_filename) { + info!(?err, "Error while checking if gold was the linker"); + } + } + if output.is_stdout() { if output.is_tty() { sess.dcx().emit_err(errors::BinaryOutputToTty { @@ -3375,3 +3381,54 @@ fn add_lld_args( } } } + +// gold has been deprecated with binutils 2.44 +// and is known to behave incorrectly around Rust programs. +// There have been reports of being unable to bootstrap with gold: +// https://github.com/rust-lang/rust/issues/139425 +// Additionally, gold miscompiles SHF_GNU_RETAIN sections, which are +// emitted with `#[used(linker)]`. +fn warn_if_linked_with_gold(sess: &Session, path: &Path) -> Result<(), Box<dyn std::error::Error>> { + use object::read::elf::{FileHeader, SectionHeader}; + use object::read::{ReadCache, ReadRef, Result}; + use object::{Endianness, elf}; + + fn elf_has_gold_version_note<'a>( + elf: &impl FileHeader, + data: impl ReadRef<'a>, + ) -> Result<bool> { + let endian = elf.endian()?; + + let section = + elf.sections(endian, data)?.section_by_name(endian, b".note.gnu.gold-version"); + if let Some((_, section)) = section { + if let Some(mut notes) = section.notes(endian, data)? { + return Ok(notes.any(|note| { + note.is_ok_and(|note| note.n_type(endian) == elf::NT_GNU_GOLD_VERSION) + })); + } + } + + Ok(false) + } + + let data = ReadCache::new(BufReader::new(File::open(path)?)); + + let was_linked_with_gold = if sess.target.pointer_width == 64 { + let elf = elf::FileHeader64::<Endianness>::parse(&data)?; + elf_has_gold_version_note(elf, &data)? + } else if sess.target.pointer_width == 32 { + let elf = elf::FileHeader32::<Endianness>::parse(&data)?; + elf_has_gold_version_note(elf, &data)? + } else { + return Ok(()); + }; + + if was_linked_with_gold { + let mut warn = + sess.dcx().struct_warn("the gold linker is deprecated and has known bugs with Rust"); + warn.help("consider using LLD or ld from GNU binutils instead"); + warn.emit(); + } + Ok(()) +} diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index a79d67bb6cd..8c6f52084c2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,7 +1,7 @@ use rustc_abi::WrappingRange; +use rustc_middle::bug; use rustc_middle::mir::SourceInfo; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::sym; @@ -60,18 +60,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { source_info: SourceInfo, ) -> Result<(), ty::Instance<'tcx>> { let span = source_info.span; - let callee_ty = instance.ty(bx.tcx(), bx.typing_env()); - let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else { - span_bug!(span, "expected fn item type, found {}", callee_ty); - }; - - let sig = callee_ty.fn_sig(bx.tcx()); - let sig = bx.tcx().normalize_erasing_late_bound_regions(bx.typing_env(), sig); - let arg_tys = sig.inputs(); - let ret_ty = sig.output(); - let name = bx.tcx().item_name(def_id); + let name = bx.tcx().item_name(instance.def_id()); let name_str = name.as_str(); + let fn_args = instance.args; // If we're swapping something that's *not* an `OperandValue::Ref`, // then we can do it directly and avoid the alloca. @@ -97,13 +89,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - let llret_ty = bx.backend_type(bx.layout_of(ret_ty)); - let ret_llval = |bx: &mut Bx, llval| { if result.layout.ty.is_bool() { - OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout) - .val - .store(bx, result); + let val = bx.from_immediate(llval); + bx.store_to_place(val, result.val); } else if !result.layout.ty.is_unit() { bx.store_to_place(llval, result.val); } @@ -143,7 +132,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { sym::vtable_align => ty::COMMON_VTABLE_ENTRIES_ALIGN, _ => bug!(), }; - let value = meth::VirtualIndex::from_index(idx).get_usize(bx, vtable, callee_ty); + let value = meth::VirtualIndex::from_index(idx).get_usize( + bx, + vtable, + instance.ty(bx.tcx(), bx.typing_env()), + ); match name { // Size is always <= isize::MAX. sym::vtable_size => { @@ -164,7 +157,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | sym::type_name | sym::variant_count => { let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap(); - OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) + OperandRef::from_const(bx, value, result.layout.ty).immediate_or_packed_pair(bx) } sym::arith_offset => { let ty = fn_args.type_at(0); @@ -248,7 +241,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.or_disjoint(a, b) } sym::exact_div => { - let ty = arg_tys[0]; + let ty = args[0].layout.ty; match int_type_width_signed(ty, bx.tcx()) { Some((_width, signed)) => { if signed { @@ -268,7 +261,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { - match float_type_width(arg_tys[0]) { + match float_type_width(args[0].layout.ty) { Some(_width) => match name { sym::fadd_fast => bx.fadd_fast(args[0].immediate(), args[1].immediate()), sym::fsub_fast => bx.fsub_fast(args[0].immediate(), args[1].immediate()), @@ -281,7 +274,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicFloatType { span, name, - ty: arg_tys[0], + ty: args[0].layout.ty, }); return Ok(()); } @@ -291,7 +284,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | sym::fsub_algebraic | sym::fmul_algebraic | sym::fdiv_algebraic - | sym::frem_algebraic => match float_type_width(arg_tys[0]) { + | sym::frem_algebraic => match float_type_width(args[0].layout.ty) { Some(_width) => match name { sym::fadd_algebraic => { bx.fadd_algebraic(args[0].immediate(), args[1].immediate()) @@ -314,31 +307,32 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicFloatType { span, name, - ty: arg_tys[0], + ty: args[0].layout.ty, }); return Ok(()); } }, sym::float_to_int_unchecked => { - if float_type_width(arg_tys[0]).is_none() { + if float_type_width(args[0].layout.ty).is_none() { bx.tcx().dcx().emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, - ty: arg_tys[0], + ty: args[0].layout.ty, }); return Ok(()); } - let Some((_width, signed)) = int_type_width_signed(ret_ty, bx.tcx()) else { + let Some((_width, signed)) = int_type_width_signed(result.layout.ty, bx.tcx()) + else { bx.tcx().dcx().emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, - ty: ret_ty, + ty: result.layout.ty, }); return Ok(()); }; if signed { - bx.fptosi(args[0].immediate(), llret_ty) + bx.fptosi(args[0].immediate(), bx.backend_type(result.layout)) } else { - bx.fptoui(args[0].immediate(), llret_ty) + bx.fptoui(args[0].immediate(), bx.backend_type(result.layout)) } } |
