From 774c1d004251a69ee17f2d7a3568a0279cca6164 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 | 35 +++++++++++++++++-- 3 files changed, 35 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 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() + } +}