diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 92989ba2dcf46..dddd2a54742b5 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -203,7 +203,7 @@ pub(crate) fn target_machine_factory( let triple = SmallCStr::new(&versioned_llvm_target(sess)); let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); let features = CString::new(sess.global_backend_features.join(",")).unwrap(); - let abi = SmallCStr::new(sess.target.llvm_abiname.desc()); + let abi = SmallCStr::new(llvm_util::target_abi(sess)); let trap_unreachable = sess.opts.unstable_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable); let emit_stack_size_section = sess.opts.unstable_opts.emit_stack_sizes; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 3cfea4b80eb2b..3146cfd66756b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -563,13 +563,12 @@ pub(crate) unsafe fn create_module<'ll>( // to workaround lld as the LTO plugin not // correctly setting target-abi for the LTO object // FIXME: https://github.com/llvm/llvm-project/issues/50591 - let llvm_abiname = &sess.target.options.llvm_abiname; if matches!(sess.target.arch, Arch::RiscV32 | Arch::RiscV64) { llvm::add_module_flag_str( llmod, llvm::ModuleFlagMergeBehavior::Error, "target-abi", - llvm_abiname.desc(), + llvm_util::target_abi(sess), ); } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 90f31e0598f2d..72ffe64787c24 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -15,9 +15,9 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_fs_util::path_to_c_string; use rustc_session::config::{NATIVE_CPU, PrintKind, PrintRequest}; use rustc_session::{EarlySession, Session}; -use rustc_span::bug; +use rustc_span::{Symbol, bug}; use rustc_target::spec::{ - Arch, CfgAbi, Env, MergeFunctions, Os, PanicStrategy, SmallDataThresholdSupport, Target, + Arch, CfgAbi, Env, LlvmAbi, MergeFunctions, Os, PanicStrategy, SmallDataThresholdSupport, Target, }; use smallvec::{SmallVec, smallvec}; @@ -812,3 +812,34 @@ pub(crate) fn target_has_mnemonic(sess: &Session, mnemonic: &str) -> bool { let cstr = SmallCStr::new(mnemonic); unsafe { llvm::LLVMRustTargetHasMnemonic(tm.raw(), cstr.as_ptr()) } } + +pub(crate) fn target_abi(sess: &Session) -> &str { + if get_version().0 >= 24 && matches!(sess.target.arch, Arch::RiscV32 | Arch::RiscV64) { + let has_feature = + |feat: &str| sess.internal_target_features.contains(&Symbol::intern(feat)); + match sess.target.llvm_abiname { + // On LLVM 24+, `computeTargetABI()` treats an ABI requiring `d` (or `f`) as a fatal + // error if the feature is disabled (e.g. via `-Ctarget-feature=-d`). Fall back to a + // compatible ABI so that LLVM module asm parsing (e.g. for `.llvmbc`) succeeds. + LlvmAbi::Ilp32d if !has_feature("d") => { + if has_feature("f") { + LlvmAbi::Ilp32f.desc() + } else { + LlvmAbi::Ilp32.desc() + } + } + LlvmAbi::Lp64d if !has_feature("d") => { + if has_feature("f") { + LlvmAbi::Lp64f.desc() + } else { + LlvmAbi::Lp64.desc() + } + } + LlvmAbi::Ilp32f if !has_feature("f") => LlvmAbi::Ilp32.desc(), + LlvmAbi::Lp64f if !has_feature("f") => LlvmAbi::Lp64.desc(), + _ => sess.target.llvm_abiname.desc(), + } + } else { + sess.target.llvm_abiname.desc() + } +}