https://github.com/arichardson updated https://github.com/llvm/llvm-project/pull/225140
>From aa8098518e70ed47f32a0f3f40a01798cb49f3a7 Mon Sep 17 00:00:00 2001 From: Alex Richardson <[email protected]> Date: Tue, 22 Sep 2026 22:52:25 -0700 Subject: [PATCH 1/3] [RISC-V][MC] Update ELF streamer ArchString in setFlagsFromFeatures() During LTO, the TargetMachine subtarget is initialized with the linker's default CPU (e.g. `generic-rv64`, `rv64i2p1`), while RISCVAsmPrinter::emitStartOfAsmFile() reconstructs the module's actual ISA from the `riscv-isa` module flag and calls RISCVTargetStreamer::setFlagsFromFeatures() and RISCVTargetStreamer::emitTargetAttributes(). Because RISCVTargetELFStreamer previously only initialized InitialArchString and ArchString in its constructor rather than in setFlagsFromFeatures(), direct object emission bypassed the update and tagged `.text` with `$xrv64i2p1` instead of the module's full architecture string. Move the InitialArchString and ArchString initialization into RISCVTargetELFStreamer::setFlagsFromFeatures() and also call setArchString() alongside emitTextAttribute(RISCVAttrs::ARCH, ...) in RISCVTargetStreamer::emitTargetAttributes(). This commit was created with the help of AI tools --- .../riscv/lto-inline-asm-abi.c | 19 ++++++++----------- .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 7 ++----- .../RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 6 ++++++ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cross-project-tests/riscv/lto-inline-asm-abi.c b/cross-project-tests/riscv/lto-inline-asm-abi.c index 883244f1854f7..897413428500f 100644 --- a/cross-project-tests/riscv/lto-inline-asm-abi.c +++ b/cross-project-tests/riscv/lto-inline-asm-abi.c @@ -35,33 +35,30 @@ // FLAGS-NEXT: EF_RISCV_RVC (0x1) // FLAGS-NEXT: ] // -/// TODO: RISCVTargetELFStreamer::emitTextAttribute does not update the -/// streamer's ArchString when emitting the module's RISCVAttrs::ARCH attribute -/// ("rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_..."). // DISASM-LABEL: Disassembly of section .text: // DISASM-EMPTY: -// DISASM-NEXT: [[#%x,]] <$xrv64i2p1>: +// DISASM-NEXT: [[#%x,]] <$xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0>: // DISASM-NEXT: [[#%x,]]: nop // DISASM-EMPTY: -// DISASM-NEXT: [[#%x,]] <$xrv64i2p1>: +// DISASM-NEXT: [[#%x,]] <$xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0>: // DISASM-NEXT: [[#%x,]] <symver_fn>: // DISASM-NEXT: [[#%x,]]: ret // DISASM-EMPTY: -// DISASM-NEXT: [[#%x,]] <$xrv64i2p1>: +// DISASM-NEXT: [[#%x,]] <$xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0>: // DISASM-NEXT: [[#%x,]] <fn>: // DISASM-NEXT: [[#%x,]]: nop // DISASM-NEXT: [[#%x,]]: ret // DISASM-EMPTY: -// DISASM-NEXT: [[#%x,]] <$xrv64i2p1>: +// DISASM-NEXT: [[#%x,]] <$xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0>: // DISASM-NEXT: [[#%x,]] <caller>: // DISASM-NEXT: [[#%x,]]: nop // DISASM-NEXT: [[#%x,]]: ret // DISASM-NOT: {{.}} // -// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1{{$}} -// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1{{$}} -// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1{{$}} -// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1{{$}} +// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0{{$}} +// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0{{$}} +// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0{{$}} +// SYMS: [[#%x,]] l .text 0000000000000000 $xrv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0{{$}} // SYMS: [[#%x,]] g F .text 0000000000000004 fn{{$}} // SYMS: [[#%x,]] g F .text 0000000000000002 symver_fn{{$}} // SYMS: [[#%x,]] g F .text 0000000000000004 caller{{$}} diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 478a2c785819b..22030f23fb4fe 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -3583,12 +3583,9 @@ bool RISCVAsmParser::parseDirectiveAttribute() { if (resetToArch(StringValue, ValueExprLoc, Result, false)) return true; - // Then emit the arch string. + // Emit the arch string (which also updates the target streamer's active + // mapping symbol ISA). getTargetStreamer().emitTextAttribute(Tag, Result); - - // And then update the active ISA so the next instruction-run emits - // an ISA-specific mapping symbol. - getTargetStreamer().setArchString(Result); } return false; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 10702a836de33..704b195cbf0cb 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -20,6 +20,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/RISCVAttributes.h" using namespace llvm; @@ -84,6 +85,11 @@ void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute, StringRef String) { getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true); + // Keep the active mapping symbol ISA in sync with .attribute arch and + // RISCVTargetStreamer::emitTargetAttributes() (e.g. when LTO reconstructs the + // module's ISA from the riscv-isa module flag). + if (Attribute == RISCVAttrs::ARCH) + setArchString(String); } void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, >From 77bb91d35843081ebf8c6f9ffed2dac861aef0da Mon Sep 17 00:00:00 2001 From: Alex Richardson <[email protected]> Date: Wed, 23 Sep 2026 23:10:38 -0700 Subject: [PATCH 2/3] try to address feedback --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 7 +++++-- llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 6 ------ llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp | 4 +++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 22030f23fb4fe..478a2c785819b 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -3583,9 +3583,12 @@ bool RISCVAsmParser::parseDirectiveAttribute() { if (resetToArch(StringValue, ValueExprLoc, Result, false)) return true; - // Emit the arch string (which also updates the target streamer's active - // mapping symbol ISA). + // Then emit the arch string. getTargetStreamer().emitTextAttribute(Tag, Result); + + // And then update the active ISA so the next instruction-run emits + // an ISA-specific mapping symbol. + getTargetStreamer().setArchString(Result); } return false; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 704b195cbf0cb..10702a836de33 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -20,7 +20,6 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/RISCVAttributes.h" using namespace llvm; @@ -85,11 +84,6 @@ void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute, StringRef String) { getStreamer().setAttributeItem(Attribute, String, /*OverwriteExisting=*/true); - // Keep the active mapping symbol ISA in sync with .attribute arch and - // RISCVTargetStreamer::emitTargetAttributes() (e.g. when LTO reconstructs the - // module's ISA from the riscv-isa module flag). - if (Attribute == RISCVAttrs::ARCH) - setArchString(String); } void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp index d6523cb42c879..f5f62bc5200f1 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -86,7 +86,9 @@ void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI, report_fatal_error(ParseResult.takeError()); } else { auto &ISAInfo = *ParseResult; - emitTextAttribute(RISCVAttrs::ARCH, ISAInfo->toString()); + std::string Arch = ISAInfo->toString(); + emitTextAttribute(RISCVAttrs::ARCH, Arch); + setArchString(Arch); } if (RiscvAbiAttr && STI.hasFeature(RISCV::FeatureStdExtA)) { >From a115b8e14f3b558253d4b87117dbdcd5aacbf563 Mon Sep 17 00:00:00 2001 From: Alex Richardson <[email protected]> Date: Thu, 24 Sep 2026 10:15:25 -0700 Subject: [PATCH 3/3] use recommended approach --- .../RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 29 +++++++++++-------- .../RISCV/MCTargetDesc/RISCVELFStreamer.h | 5 ++-- .../RISCV/MCTargetDesc/RISCVTargetStreamer.h | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 10702a836de33..11093a700ac27 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -28,18 +28,6 @@ RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) : RISCVTargetStreamer(S), CurrentVendor("riscv") { setFlagsFromFeatures(STI); - - // Compute the initial ISA string. This serves two purposes: - // 1. Deduplication: subsequent .option arch/rvc/norvc directives compare - // against ArchString to avoid propagating redundant ISA updates. - // 2. Initial symbol: seed the streamer's active ISA so a "$x<ArchString>" - // mapping symbol is emitted before the first instruction, recording - // the full ISA in the object even when no .option directive is present. - if (auto ParseResult = RISCVFeatures::parseFeatureBits(STI)) { - InitialArchString = (*ParseResult)->toString(); - ArchString = InitialArchString; - getStreamer().setMappingSymbolArch(ArchString); - } } RISCVELFStreamer::RISCVELFStreamer(MCContext &C, @@ -52,6 +40,23 @@ RISCVELFStreamer &RISCVTargetELFStreamer::getStreamer() { return static_cast<RISCVELFStreamer &>(Streamer); } +void RISCVTargetELFStreamer::setFlagsFromFeatures(const MCSubtargetInfo &STI) { + RISCVTargetStreamer::setFlagsFromFeatures(STI); + + // Compute the initial ISA string. This serves two purposes: + // 1. Deduplication: subsequent .option arch/rvc/norvc directives compare + // against ArchString to avoid propagating redundant ISA updates. + // 2. Initial symbol: seed the streamer's active ISA so a "$x<ArchString>" + // mapping symbol is emitted before the first instruction, recording + // the full ISA in the object even when no .option directive is present. + if (auto ParseResult = RISCVFeatures::parseFeatureBits(STI)) { + InitialArchString = (*ParseResult)->toString(); + setArchString(InitialArchString); + } else { + consumeError(ParseResult.takeError()); + } +} + void RISCVTargetELFStreamer::setArchString(StringRef Arch) { if (Arch == ArchString) return; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h index ac738307922d7..e86144ac20c9b 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -56,8 +56,8 @@ class RISCVTargetELFStreamer : public RISCVTargetStreamer { private: StringRef CurrentVendor; - // Initial ISA string derived from the subtarget features in the constructor. - // Used to re-establish state on reset(). + // Initial ISA string derived from the subtarget features in + // setFlagsFromFeatures(). Used to re-establish state on reset(). std::string InitialArchString; // Current ISA string, kept in sync with each .option arch/rvc/norvc/pop @@ -81,6 +81,7 @@ class RISCVTargetELFStreamer : public RISCVTargetStreamer { RISCVELFStreamer &getStreamer(); RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); + void setFlagsFromFeatures(const MCSubtargetInfo &STI) override; // Update ArchString and propagate the change to the streamer so the next // instruction-run emits an ISA-specific mapping symbol. A no-op when // Arch == ArchString (deduplication). diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h index cd59089fae4c7..c7b4f752d7264 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -64,7 +64,7 @@ class RISCVTargetStreamer : public MCTargetStreamer { void setTargetABI(RISCVABI::ABI ABI); RISCVABI::ABI getTargetABI() const { return TargetABI; } bool hasTargetABI() const { return TargetABI != RISCVABI::ABI_Unknown; } - void setFlagsFromFeatures(const MCSubtargetInfo &STI); + virtual void setFlagsFromFeatures(const MCSubtargetInfo &STI); bool hasRVC() const { return HasRVC; } bool hasTSO() const { return HasTSO; } }; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
