[llvm] [RISCV][Disassembler] Symbolize UImm20 and SImm12Lo operands (PR #217550)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 02:37:26 PDT 2026


https://github.com/Thrrreeee updated https://github.com/llvm/llvm-project/pull/217550

>From dcc390f261799f6ac50758248fbc6762c311d3aa Mon Sep 17 00:00:00 2001
From: shijinrui <shijinrui at bytedance.com>
Date: Thu, 20 Aug 2026 15:52:23 +0800
Subject: [PATCH 1/2] [RISCV][Disassembler] Symbolize UImm20 and SImm12Lo
 operands

---
 .../RISCV/Disassembler/RISCVDisassembler.cpp  | 25 +++++++++++++++++++
 llvm/lib/Target/RISCV/RISCVInstrInfo.td       |  2 ++
 2 files changed, 27 insertions(+)

diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 3b3eb5195a9b4..18fdfe69a11e3 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -403,6 +403,31 @@ static DecodeStatus decodeSImmOperand(MCInst &Inst, uint32_t Imm,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeSImm12LoOperand(MCInst &Inst, uint32_t Imm,
+                                          int64_t Address,
+                                          const MCDisassembler *Decoder) {
+  assert(isUInt<12>(Imm) && "Invalid immediate");
+  const int64_t Value = SignExtend64<12>(Imm);
+  if (!Decoder->tryAddingSymbolicOperand(Inst, Value, Address,
+                                         /*IsBranch=*/false,
+                                         /*Offset=*/0, /*OpSize=*/4,
+                                         /*InstSize=*/4))
+    Inst.addOperand(MCOperand::createImm(Value));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeUImm20Operand(MCInst &Inst, uint32_t Imm,
+                                        int64_t Address,
+                                        const MCDisassembler *Decoder) {
+  assert(isUInt<20>(Imm) && "Invalid immediate");
+  if (!Decoder->tryAddingSymbolicOperand(Inst, Imm, Address,
+                                         /*IsBranch=*/false,
+                                         /*Offset=*/0, /*OpSize=*/4,
+                                         /*InstSize=*/4))
+    Inst.addOperand(MCOperand::createImm(Imm));
+  return MCDisassembler::Success;
+}
+
 template <unsigned N>
 static DecodeStatus decodeSImmNonZeroOperand(MCInst &Inst, uint32_t Imm,
                                              int64_t Address,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 5be74d729c5b0..5a37b229664c4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -400,6 +400,7 @@ def uimm64 : RISCVUImmOp<64>;
 def simm12 : RISCVSImmLeafOp<12>;
 
 class Simm12LoOp : RISCVSImmLeafOp<12> {
+  let DecoderMethod = "decodeSImm12LoOperand";
   let MCOperandPredicate = [{
     int64_t Imm;
     if (MCOp.evaluateAsConstantImm(Imm))
@@ -455,6 +456,7 @@ def bare_simm13_lsb0 : BareSImm13Lsb0MaybeSym,
 def bare_simm13_lsb0_bb : BareSImm13Lsb0MaybeSym;
 
 class UImm20OperandMaybeSym : RISCVUImmOp<20> {
+  let DecoderMethod = "decodeUImm20Operand";
   let MCOperandPredicate = [{
     int64_t Imm;
     if (MCOp.evaluateAsConstantImm(Imm))

>From df79c12d14324ac4deadcabe84fdffc5ed1fd53c Mon Sep 17 00:00:00 2001
From: shijinrui <shijinrui at bytedance.com>
Date: Thu, 20 Aug 2026 17:37:07 +0800
Subject: [PATCH 2/2] fix

---
 .../MC/MCDisassembler/MCExternalSymbolizer.h  | 20 +++++++++++++++++--
 .../MCDisassembler/MCExternalSymbolizer.cpp   | 13 +++++++-----
 .../RISCV/Disassembler/RISCVDisassembler.cpp  | 20 +++++++++++++++++++
 3 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h b/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
index d8e39b4a4add7..10734f756563a 100644
--- a/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
+++ b/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h
@@ -25,6 +25,16 @@ namespace llvm {
 ///
 /// See llvm-c/Disassembler.h.
 class LLVM_ABI MCExternalSymbolizer : public MCSymbolizer {
+public:
+  /// Controls symbol-name lookup when operand relocation information is not
+  /// available.
+  enum class SymbolLookupPolicy {
+    /// Retain the generic immediate-width heuristic.
+    Default,
+    /// Only branch targets may fall back to a symbol-name lookup.
+    BranchesOnly,
+  };
+
 protected:
   /// \name Hooks for symbolic disassembly via the public 'C' interface.
   /// @{
@@ -36,13 +46,19 @@ class LLVM_ABI MCExternalSymbolizer : public MCSymbolizer {
   void *DisInfo;
   /// @}
 
+  /// Whether SymbolLookUp may guess symbols for non-branch operands when
+  /// GetOpInfo does not provide relocation information.
+  SymbolLookupPolicy LookupPolicy;
+
 public:
   MCExternalSymbolizer(MCContext &Ctx,
                        std::unique_ptr<MCRelocationInfo> RelInfo,
                        LLVMOpInfoCallback getOpInfo,
-                       LLVMSymbolLookupCallback symbolLookUp, void *disInfo)
+                       LLVMSymbolLookupCallback symbolLookUp, void *disInfo,
+                       SymbolLookupPolicy lookupPolicy =
+                           SymbolLookupPolicy::Default)
     : MCSymbolizer(Ctx, std::move(RelInfo)), GetOpInfo(getOpInfo),
-      SymbolLookUp(symbolLookUp), DisInfo(disInfo) {}
+      SymbolLookUp(symbolLookUp), DisInfo(disInfo), LookupPolicy(lookupPolicy) {}
 
   bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &CommentStream,
                                 int64_t Value, uint64_t Address, bool IsBranch,
diff --git a/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp b/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
index f0d6718bd2dfa..d362064d99ef4 100644
--- a/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
+++ b/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
@@ -49,11 +49,14 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(
     // if the Value is the address of a symbol.  In the case this is a branch
     // that always makes sense to guess.  But in the case of an immediate it is
     // a bit more questionable if it is an address of a symbol or some other
-    // reference.  So if the immediate Value comes from a width of 1 byte,
-    // OpSize, we will not guess it is an address of a symbol.  Because in
-    // object files assembled starting at address 0 this usually leads to
-    // incorrect symbolication.
-    if (!SymbolLookUp || (OpSize == 1 && !IsBranch))
+    // reference. Targets can require relocation information for non-branch
+    // operands instead of allowing this fallback. Otherwise, if the immediate
+    // Value comes from a width of 1 byte, OpSize, we will not guess it is an
+    // address of a symbol. Because in object files assembled starting at
+    // address 0 this usually leads to incorrect symbolication.
+    if (!SymbolLookUp ||
+        (!IsBranch &&
+         (LookupPolicy == SymbolLookupPolicy::BranchesOnly || OpSize == 1)))
       return false;
 
     uint64_t ReferenceType;
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 18fdfe69a11e3..779f246419a91 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -17,6 +17,7 @@
 #include "llvm/MC/MCDecoder.h"
 #include "llvm/MC/MCDecoderOps.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
@@ -65,17 +66,36 @@ static MCDisassembler *createRISCVDisassembler(const Target &T,
   return new RISCVDisassembler(STI, Ctx, T.createMCInstrInfo());
 }
 
+static MCSymbolizer *createRISCVExternalSymbolizer(
+    const Triple & /*TT*/, LLVMOpInfoCallback GetOpInfo,
+    LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx,
+    std::unique_ptr<MCRelocationInfo> &&RelInfo) {
+  // HI20 and LO12 operands are address fragments, so their decoded values
+  // cannot safely be treated as absolute addresses without relocations.
+  return new MCExternalSymbolizer(
+      *Ctx, std::move(RelInfo), GetOpInfo, SymbolLookUp, DisInfo,
+      MCExternalSymbolizer::SymbolLookupPolicy::BranchesOnly);
+}
+
 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
 LLVMInitializeRISCVDisassembler() {
   // Register the disassembler for each target.
   TargetRegistry::RegisterMCDisassembler(getTheRISCV32Target(),
                                          createRISCVDisassembler);
+  TargetRegistry::RegisterMCSymbolizer(getTheRISCV32Target(),
+                                       createRISCVExternalSymbolizer);
   TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
                                          createRISCVDisassembler);
+  TargetRegistry::RegisterMCSymbolizer(getTheRISCV64Target(),
+                                       createRISCVExternalSymbolizer);
   TargetRegistry::RegisterMCDisassembler(getTheRISCV32beTarget(),
                                          createRISCVDisassembler);
+  TargetRegistry::RegisterMCSymbolizer(getTheRISCV32beTarget(),
+                                       createRISCVExternalSymbolizer);
   TargetRegistry::RegisterMCDisassembler(getTheRISCV64beTarget(),
                                          createRISCVDisassembler);
+  TargetRegistry::RegisterMCSymbolizer(getTheRISCV64beTarget(),
+                                       createRISCVExternalSymbolizer);
 }
 
 template <unsigned FirstReg, unsigned NumRegsInClass, unsigned RVELimit = 0>



More information about the llvm-commits mailing list