[lld] [llvm] [RISCV] Do not re-validate target ABI in AsmParser if already resolved by streamer (PR #223606)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 23:00:07 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Alexander Richardson (arichardson)
<details>
<summary>Changes</summary>
Commit 105ff16f816f (https://github.com/llvm/llvm-project/pull/213410)
changed RISCVABI::computeTargetABI() to return Expected<ABI> and added
validation to RISCVAsmParser::onBeginOfFile() to report invalid
-target-abi flags with real source location in llvm-mc.
However, this broke LTO builds containing inline assembly (e.g. Android
riscv64 builds and downstream Rust in
https://github.com/rust-lang/rust/pull/162783). During LTO, LLD sets
TargetOptions.MCOptions.ABIName from the module's target-abi metadata
("lp64d"), while the linker's default TargetMachine subtarget lacks
"+d" (individual functions specify "+d" in target-features).
RISCVSubtarget handles this gracefully by emitting a diagnostic note
and falling back to lp64 for code generation. When inline assembly was
subsequently parsed, AsmPrinter::emitInlineAsm instantiated
RISCVAsmParser with a subtarget lacking "+d", causing onBeginOfFile() to
re-validate TargetOptions.ABIName and fail with a fatal error.
To fix this, skip the parser validation whenever the streamer has
already resolved an ABI. This preserves llvm-mc diagnostics on invalid
command-line flags while avoiding conflicting validation when assembling
inline asm during code generation.
This commit was created with the help of AI tools
---
Full diff: https://github.com/llvm/llvm-project/pull/223606.diff
5 Files Affected:
- (modified) lld/test/ELF/lto/riscv-target-abi.ll (+7)
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+12-1)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp (+3-5)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h (+1)
- (modified) llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (+2)
``````````diff
diff --git a/lld/test/ELF/lto/riscv-target-abi.ll b/lld/test/ELF/lto/riscv-target-abi.ll
index 07fdf122cb0c4..fdb93b82fc41e 100644
--- a/lld/test/ELF/lto/riscv-target-abi.ll
+++ b/lld/test/ELF/lto/riscv-target-abi.ll
@@ -28,7 +28,14 @@
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
target triple = "riscv64"
+module asm "nop"
+;; Module asm with target features not including 'd' (would fail before fix)
+module asm(target_features: "+c") "c.nop"
+;; Module asm with target features enabling 'd'
+module asm(target_features: "+d") "fld f0, 0(sp)"
+
define void @_start() {
+ call void asm sideeffect "nop", ""()
ret void
}
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 4f1f3cbfb9b26..d18f7c7416ac6 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -343,10 +343,21 @@ class RISCVAsmParser : public MCTargetAsmParser {
// with the first token, so diagnostics can be reported with a real source
// location instead of being printed with no location information.
void onBeginOfFile() override {
+ // If the target streamer already has a resolved ABI (e.g. set by
+ // RISCVTargetELFStreamer for a valid -target-abi, or set by
+ // RISCVAsmPrinter during codegen), skip validation.
+ if (getTargetStreamer().hasTargetABI())
+ return;
+
Expected<RISCVABI::ABI> ABIOrErr =
RISCVABI::computeTargetABI(getSTI(), getTargetOptions().ABIName);
- if (!ABIOrErr)
+ if (!ABIOrErr) {
getParser().printError(getLoc(), toString(ABIOrErr.takeError()));
+ getTargetStreamer().setTargetABI(
+ cantFail(RISCVABI::computeTargetABI(getSTI(), "")));
+ return;
+ }
+ getTargetStreamer().setTargetABI(*ABIOrErr);
}
};
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index 049123068070f..1fb45627a1d03 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -40,12 +40,10 @@ RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
if (auto ABIOrErr = RISCVABI::computeTargetABI(STI, ABIName)) {
setTargetABI(*ABIOrErr);
} else {
- // Do not warn here and instead silently fall back to the default ABI:
- // either RISCVSubtarget::initializeSubtargetDependencies() or
- // RISCVAsmParser::onBeginOfFile() will print the message with proper
- // contexts. Reporting here would just duplicate that diagnostic.
+ // Do not set TargetABI here if invalid: RISCVSubtarget/RISCVAsmPrinter
+ // (in codegen) or RISCVAsmParser::onBeginOfFile() (in llvm-mc) will
+ // resolve or diagnose it with proper contexts.
consumeError(ABIOrErr.takeError());
- setTargetABI(cantFail(RISCVABI::computeTargetABI(STI, "")));
}
setFlagsFromFeatures(STI);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
index 0601cf0ed0362..cd59089fae4c7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
@@ -63,6 +63,7 @@ class RISCVTargetStreamer : public MCTargetStreamer {
void emitTargetAttributes(const MCSubtargetInfo &STI, bool EmitStackAlign);
void setTargetABI(RISCVABI::ABI ABI);
RISCVABI::ABI getTargetABI() const { return TargetABI; }
+ bool hasTargetABI() const { return TargetABI != RISCVABI::ABI_Unknown; }
void setFlagsFromFeatures(const MCSubtargetInfo &STI);
bool hasRVC() const { return HasRVC; }
bool hasTSO() const { return HasTSO; }
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index b535404d25c1f..57fb1dfc48fec 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -649,6 +649,8 @@ void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
if (const MDString *ModuleTargetABI =
dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
+ else if (!RTS.hasTargetABI())
+ RTS.setTargetABI(TM.getSubtarget<RISCVSubtarget>().getTargetABI());
MCSubtargetInfo SubtargetInfo = TM.getMCSubtargetInfo();
``````````
</details>
https://github.com/llvm/llvm-project/pull/223606
More information about the llvm-commits
mailing list