Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,11 @@ impl WriterRelocate {
// HACK rust_eh_personality is likely not defined in the same crate,
// so get_finalized_function won't work. Use the rust_eh_personality
// of cg_clif itself, which is likely ABI compatible.
if jit_module.declarations().get_function_decl(func_id).name.as_deref()
== Some("rust_eh_personality")
if jit_module
.declarations()
.get_function_decl(func_id)
.name
.is_some_and(|name| name.ends_with("rust_eh_personality"))
{
unsafe extern "C" {
fn rust_eh_personality() -> !;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would break as there is no longer a rust_eh_personality symbol. This has to be the exact symbol that rust_eh_personality mangles too. Is adding #[lang = "eh_personality"] to this declaration allowed? Also make sure to add the right feature gate in that case.

This code is not tested in the rust CI as it is part of the JIT feature, which is disabled for rustup shipped versions of cg_clif. You could temporarily change Cargo.toml to enable the jit feature by default to test this code.

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub(crate) struct UnwindContext {
}

impl UnwindContext {
pub(crate) fn new(module: &mut dyn Module, pic_eh_frame: bool) -> Self {
pub(crate) fn new(module: &mut dyn Module, tcx: TyCtxt<'_>, pic_eh_frame: bool) -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe pass the name of the personality function as argument instead?

let endian = match module.isa().endianness() {
Endianness::Little => RunTimeEndian::Little,
Endianness::Big => RunTimeEndian::Big,
Expand Down Expand Up @@ -70,7 +70,7 @@ impl UnwindContext {
// FIXME use eh_personality lang item instead
let personality = module
.declare_function(
"rust_eh_personality",
&rustc_symbol_mangling::eh_personality_symbol(tcx),
Linkage::Import,
&Signature {
params: vec![
Expand Down
15 changes: 8 additions & 7 deletions compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,8 @@ fn produce_final_output_artifacts(
// These are used in linking steps and will be cleaned up afterward.
}

fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
let isa = crate::build_isa(sess, false);
fn make_module(tcx: TyCtxt<'_>, name: String) -> UnwindModule<ObjectModule> {
let isa = crate::build_isa(tcx.sess, false);

let mut builder =
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
Expand All @@ -333,12 +333,13 @@ fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
// explicitly disable it on MinGW as rustc already disables it by default on MinGW and as such
// isn't tested. If rustc enables it in the future on MinGW, we can re-enable it too once it has
// been on MinGW.
let default_function_sections = sess.target.function_sections && !sess.target.is_like_windows;
let default_function_sections =
tcx.sess.target.function_sections && !tcx.sess.target.is_like_windows;
builder.per_function_section(
sess.opts.unstable_opts.function_sections.unwrap_or(default_function_sections),
tcx.sess.opts.unstable_opts.function_sections.unwrap_or(default_function_sections),
);

UnwindModule::new(ObjectModule::new(builder), true)
UnwindModule::new(ObjectModule::new(builder), tcx, true)
}

fn emit_cgu(
Expand Down Expand Up @@ -579,7 +580,7 @@ fn module_codegen(
ConcurrencyLimiterToken,
),
) -> OngoingModuleCodegen {
let mut module = make_module(tcx.sess, cgu_name.as_str().to_string());
let mut module = make_module(tcx, cgu_name.as_str().to_string());

let (mut debug_context, codegened_functions, mut global_asm) =
codegen_cgu_content(tcx, &mut module, cgu_name);
Expand Down Expand Up @@ -643,7 +644,7 @@ fn module_codegen(
}

fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
let mut allocator_module = make_module(tcx.sess, "allocator_shim".to_string());
let mut allocator_module = make_module(tcx, "allocator_shim".to_string());
let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module);

if created_alloc_shim {
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_codegen_cranelift/src/unwind_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use cranelift_module::{
ModuleReloc, ModuleResult,
};
use cranelift_object::{ObjectModule, ObjectProduct};
use rustc_middle::ty::TyCtxt;

use crate::UnwindContext;

Expand All @@ -17,8 +18,8 @@ pub(crate) struct UnwindModule<T> {
}

impl<T: Module> UnwindModule<T> {
pub(crate) fn new(mut module: T, pic_eh_frame: bool) -> Self {
let unwind_context = UnwindContext::new(&mut module, pic_eh_frame);
pub(crate) fn new(mut module: T, tcx: TyCtxt<'_>, pic_eh_frame: bool) -> Self {
let unwind_context = UnwindContext::new(&mut module, tcx, pic_eh_frame);
UnwindModule { module, unwind_context }
}
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_gcc/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,12 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
self.declare_fn(symbol_name, fn_abi)
}
_ => {
let rust_name;
let name = if wants_msvc_seh(self.sess()) {
"__CxxFrameHandler3"
} else {
"rust_eh_personality"
rust_name = rustc_symbol_mangling::eh_personality_symbol(tcx);
&rust_name
};
self.declare_func(name, self.type_i32(), &[], true)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ fn declare_raw_fn<'gcc>(
cx.functions.borrow_mut().insert(name.to_string(), func);

#[cfg(feature = "master")]
if name == "rust_eh_personality" {
if name.ends_with("rust_eh_personality") {
// NOTE: GCC will sometimes change the personality function set on a function from
// rust_eh_personality to __gcc_personality_v0 as an optimization.
// As such, we need to create a weak alias from __gcc_personality_v0 to
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,6 @@ impl CodegenBackend for GccCodegenBackend {
let lto_supported = gccjit::is_lto_supported();
LTO_SUPPORTED.store(lto_supported, Ordering::SeqCst);
self.lto_supported.store(lto_supported, Ordering::SeqCst);

gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
}

#[cfg(not(feature = "master"))]
Expand Down Expand Up @@ -291,6 +289,8 @@ impl CodegenBackend for GccCodegenBackend {
}

fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
#[cfg(feature = "master")]
self.set_personality_function(tcx);
let target_cpu = target_cpu(tcx.sess);
let res = codegen_crate(self.clone(), tcx, target_cpu.to_string());

Expand All @@ -314,6 +314,17 @@ impl CodegenBackend for GccCodegenBackend {
}
}

impl GccCodegenBackend {
#[cfg(feature = "master")]
fn set_personality_function(&self, tcx: TyCtxt<'_>) {
let personality_symbol =
CString::new(rustc_symbol_mangling::eh_personality_symbol(tcx)).unwrap();
// FIXME: Change gccjit to store an owned string internally (https://github.com/rust-lang/rust/pull/148413#discussion_r2749777937)
let personality_symbol = Box::leak(personality_symbol.into_boxed_c_str());
gccjit::set_global_personality_function_name(personality_symbol.to_bytes_with_nul());
}
}

fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
let context = Context::default();
if matches!(tcx.sess.target.arch, Arch::X86 | Arch::X86_64) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn prepare_lto(
symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned());

// LTO seems to discard this otherwise under certain circumstances.
symbols_below_threshold.push(c"rust_eh_personality".to_owned());
symbols_below_threshold.push(CString::new(cgcx.rust_eh_personality_symbol.clone()).unwrap());

// If we're performing LTO for the entire crate graph, then for each of our
// upstream dependencies, find the corresponding rlib and load the bitcode
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,14 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
DUMMY_SP,
)),
_ => {
let name = name.unwrap_or("rust_eh_personality");
let mangled_symbol;
let name = match name {
Some(name) => name,
None => {
mangled_symbol = rustc_symbol_mangling::eh_personality_symbol(tcx);
mangled_symbol.as_str()
}
};
if let Some(llfn) = self.get_declared_value(name) {
llfn
} else {
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,11 @@ impl CodegenBackend for LlvmCodegenBackend {
llvm::LLVMRustLLVMHasZstdCompression()
}

fn can_mangle_eh_personality(&self) -> bool {
// https://github.com/llvm/llvm-project/pull/166095
llvm_util::get_version() > (22, 0, 0)
}

fn target_config(&self, sess: &Session) -> TargetConfig {
target_config(sess)
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
pub pointer_size: Size,
pub rust_eh_personality_symbol: String,

/// LLVM optimizations for which we want to print remarks.
pub remark: Passes,
Expand Down Expand Up @@ -1328,6 +1329,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
target_is_like_darwin: tcx.sess.target.is_like_darwin,
target_is_like_aix: tcx.sess.target.is_like_aix,
target_is_like_gpu: tcx.sess.target.is_like_gpu,
rust_eh_personality_symbol: rustc_symbol_mangling::eh_personality_symbol(tcx),
split_debuginfo: tcx.sess.split_debuginfo(),
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ pub trait CodegenBackend {
false
}

/// Whether the `rust_eh_personality` symbol can be mangled (this is false if the codegen
/// backend hardcodes the name for certain checks).
fn can_mangle_eh_personality(&self) -> bool {
true
}

/// The metadata loader used to load rlib and dylib metadata.
///
/// Alternative codegen backends may want to use different rlib or dylib formats than the
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
util::rustc_version_str().unwrap_or("unknown"),
config.ice_file,
config.using_internal_features,
codegen_backend.can_mangle_eh_personality(),
);

codegen_backend.init(&sess);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ where
"",
None,
&USING_INTERNAL_FEATURES,
true,
);
let cfg = parse_cfg(sess.dcx(), matches.opt_strs("cfg"));
let cfg = build_configuration(&sess, cfg);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ pub struct Session {
/// drown everything else in noise.
miri_unleashed_features: Lock<Vec<(Span, Option<Symbol>)>>,

/// Whether the codegen backend supports mangling of the personality.
/// See `CodegenBackend::can_mangle_eh_personality`.
pub codegen_backend_supports_eh_personality_mangling: bool,

/// Architecture to use for interpreting asm!.
pub asm_arch: Option<InlineAsmArch>,

Expand Down Expand Up @@ -970,6 +974,7 @@ pub fn build_session(
cfg_version: &'static str,
ice_file: Option<PathBuf>,
using_internal_features: &'static AtomicBool,
codegen_backend_supports_eh_personality_mangling: bool,
) -> Session {
// FIXME: This is not general enough to make the warning lint completely override
// normal diagnostic warnings, since the warning lint can also be denied and changed
Expand Down Expand Up @@ -1084,6 +1089,7 @@ pub fn build_session(
driver_lint_caps,
ctfe_backtrace,
miri_unleashed_features: Lock::new(Default::default()),
codegen_backend_supports_eh_personality_mangling,
asm_arch,
target_features: Default::default(),
unstable_target_features: Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_symbol_mangling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ mod v0;
pub mod errors;
pub mod test;

pub use v0::mangle_internal_symbol;
pub use v0::{eh_personality_symbol, mangle_internal_symbol};

/// This function computes the symbol name for the given `instance` and the
/// given instantiating crate. That is, if you know that instance X is
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,15 @@ pub(super) fn mangle<'tcx>(
std::mem::take(&mut p.out)
}

pub fn eh_personality_symbol<'tcx>(tcx: TyCtxt<'tcx>) -> String {
mangle_internal_symbol(tcx, "rust_eh_personality")
}

pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String {
match item_name {
// rust_eh_personality must not be renamed as LLVM hard-codes the name
"rust_eh_personality" => return item_name.to_owned(),
"rust_eh_personality" if !tcx.sess.codegen_backend_supports_eh_personality_mangling => {
return item_name.to_owned();
}
// Apple availability symbols need to not be mangled to be usable by
// C/Objective-C code.
"__isPlatformVersionAtLeast" | "__isOSVersionAtLeast" => return item_name.to_owned(),
Expand Down
4 changes: 4 additions & 0 deletions src/tools/compiletest/src/runtest/run_make.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ impl TestCx<'_> {
cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
}

if let Some(ref llvm_version) = self.config.llvm_version {
cmd.env("LLVM_VERSION", llvm_version.to_string());
}

if let Some(ref remote_test_client) = self.config.remote_test_client {
cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
}
Expand Down
13 changes: 13 additions & 0 deletions src/tools/run-make-support/src/external_deps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ use std::path::{Path, PathBuf};
use crate::command::Command;
use crate::env::env_var;

pub fn llvm_version() -> (u32, u32, u32) {
let version_string = env_var("LLVM_VERSION");
let mut parts = version_string.split(".");
let mut part = || {
parts
.next()
.expect(&format!("invalid LLVM version: {version_string}"))
.parse::<u32>()
.expect(&format!("invalid LLVM version: {version_string}"))
};
(part(), part(), part())
}

/// Construct a new `llvm-readobj` invocation with the `GNU` output style.
/// This assumes that `llvm-readobj` is available at `$LLVM_BIN_DIR/llvm-readobj`.
#[track_caller]
Expand Down
2 changes: 1 addition & 1 deletion src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub use crate::external_deps::llvm::{
self, LlvmAr, LlvmBcanalyzer, LlvmDis, LlvmDwarfdump, LlvmFilecheck, LlvmNm, LlvmObjcopy,
LlvmObjdump, LlvmProfdata, LlvmReadobj, llvm_ar, llvm_as, llvm_bcanalyzer, llvm_dis,
llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objcopy, llvm_objdump, llvm_profdata,
llvm_readobj,
llvm_readobj, llvm_version,
};
pub use crate::external_deps::python::python_command;
pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_path};
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen-llvm/gdb_debug_script_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! {
loop {}
}

#[no_mangle]
#[lang = "eh_personality"]
extern "C" fn rust_eh_personality() {
loop {}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/run-make/no-alloc-shim/foo.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(rustc_attrs)]
#![feature(rustc_attrs, lang_items)]
#![no_std]
#![no_main]

Expand All @@ -11,7 +11,7 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! {
loop {}
}

#[no_mangle]
#[lang = "eh_personality"]
extern "C" fn rust_eh_personality(
_version: i32,
_actions: i32,
Expand Down
14 changes: 2 additions & 12 deletions tests/run-make/repr128-dwarf/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,12 @@ use std::rc::Rc;
use gimli::read::DebuggingInformationEntry;
use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian};
use object::{Object, ObjectSection};
use run_make_support::{gimli, object, rfs, rustc};
use run_make_support::{gimli, llvm_version, object, rfs, rustc};

fn main() {
// Before LLVM 20, 128-bit enums with variants didn't emit debuginfo correctly.
// This check can be removed once Rust no longer supports LLVM 18 and 19.
let llvm_version = rustc()
.verbose()
.arg("--version")
.run()
.stdout_utf8()
.lines()
.filter_map(|line| line.strip_prefix("LLVM version: "))
.map(|version| version.split(".").next().unwrap().parse::<u32>().unwrap())
.next()
.unwrap();
let is_old_llvm = llvm_version < 20;
let is_old_llvm = llvm_version() < (20, 0, 0);

let output = PathBuf::from("repr128");
let mut rustc = rustc();
Expand Down
Loading
Loading