From 8850b994e89bf1dc0f517dac35e6c6723b03dac0 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 14 Sep 2026 16:25:45 -0400 Subject: [PATCH] rustc_codegen_llvm: handle LLVM 24 ABI constraints LLVM 24 is pickier about things like hard-float being disabled but the compiled module ABI mentioning hard-float. As an example, if the user specifies target-features=-d to disable the d extension but the declared target-abi is lp64d that's now an error where before I guess it was a warning. This fix seems somewhat inelegant, but in the name of keeping the behavior changes minimal I did gate the new behavior to only happen on LLVM 24. I'm very open to alternative solutions! An LLM was used to identify the breaking commit and help me sort out _why_ the commit was breaking. --- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 3 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 36 +++++++++++++++++-- 3 files changed, 36 insertions(+), 5 deletions(-) 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 ac1bfcfb45afd..d84f7dc102f3c 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 5324ec240b0ab..de10d27f77183 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -16,9 +16,10 @@ 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, sym}; +use rustc_span::{Symbol, bug, sym}; 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}; @@ -821,3 +822,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() + } +}