Skip to content

[RISCV][Disassembler] Use a table to store all the decoder tables and their associated features. NFC #130883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 13, 2025

Conversation

topperc
Copy link
Collaborator

@topperc topperc commented Mar 12, 2025

Replace the macros with a table that we can iterate over. Use a different table for each possible instruction bitwidth.

… their associated features. NFC

Replace the macros with a table that we can iterate over. Use a
different table for each possible instrution bitwidth.
@llvmbot
Copy link
Member

llvmbot commented Mar 12, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Craig Topper (topperc)

Changes

Replace the macros with a table that we can iterate over. Use a different table for each possible instruction bitwidth.


Full diff: https://github.com/llvm/llvm-project/pull/130883.diff

1 Files Affected:

  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+99-70)
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index de742ac428de2..752aad387c87e 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -620,29 +620,19 @@ void RISCVDisassembler::addSPOperands(MCInst &MI) const {
       MI.insert(MI.begin() + i, MCOperand::createReg(RISCV::X2));
 }
 
-#define TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION(FEATURE_CHECKS, DECODER_TABLE, \
-                                                DESC, ADDITIONAL_OPERATION)    \
-  do {                                                                         \
-    if (FEATURE_CHECKS) {                                                      \
-      LLVM_DEBUG(dbgs() << "Trying " << DESC << " table:\n");                  \
-      DecodeStatus Result =                                                    \
-          decodeInstruction(DECODER_TABLE, MI, Insn, Address, this, STI);      \
-      if (Result != MCDisassembler::Fail) {                                    \
-        ADDITIONAL_OPERATION;                                                  \
-        return Result;                                                         \
-      }                                                                        \
-    }                                                                          \
-  } while (false)
-#define TRY_TO_DECODE_AND_ADD_SP(FEATURE_CHECKS, DECODER_TABLE, DESC)          \
-  TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION(FEATURE_CHECKS, DECODER_TABLE, DESC, \
-                                          addSPOperands(MI))
-#define TRY_TO_DECODE(FEATURE_CHECKS, DECODER_TABLE, DESC)                     \
-  TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION(FEATURE_CHECKS, DECODER_TABLE, DESC, \
-                                          (void)nullptr)
-#define TRY_TO_DECODE_FEATURE(FEATURE, DECODER_TABLE, DESC)                    \
-  TRY_TO_DECODE(STI.hasFeature(FEATURE), DECODER_TABLE, DESC)
-#define TRY_TO_DECODE_FEATURE_ANY(FEATURES, DECODER_TABLE, DESC)               \
-  TRY_TO_DECODE((STI.getFeatureBits() & (FEATURES)).any(), DECODER_TABLE, DESC)
+namespace {
+
+struct DecoderListEntry {
+  const uint8_t *Table;
+  FeatureBitset RequiredFeatures;
+  const char *Desc;
+
+  bool haveRequiredFeatures(const FeatureBitset &ActiveFeatures) const {
+    return RequiredFeatures.none() || (RequiredFeatures & ActiveFeatures).any();
+  }
+};
+
+} // end anonymous namespace
 
 static constexpr FeatureBitset XCVFeatureGroup = {
     RISCV::FeatureVendorXCVbitmanip, RISCV::FeatureVendorXCVelw,
@@ -681,6 +671,31 @@ static constexpr FeatureBitset XTHeadGroup = {
     RISCV::FeatureVendorXTHeadMemPair, RISCV::FeatureVendorXTHeadSync,
     RISCV::FeatureVendorXTHeadVdot};
 
+static constexpr DecoderListEntry DecoderList32[]{
+    // Vendor Extensions
+    {DecoderTableXVentana32,
+     {RISCV::FeatureVendorXVentanaCondOps},
+     "XVentanaCondOps"},
+    {DecoderTableXTHead32, XTHeadGroup, "T-Head extensions"},
+    {DecoderTableXSfvector32, XSfVectorGroup, "SiFive vector extensions"},
+    {DecoderTableXSfsystem32, XSfSystemGroup, "SiFive system extensions"},
+    {DecoderTableXSfcease32, {RISCV::FeatureVendorXSfcease}, "SiFive sf.cease"},
+    {DecoderTableXmipslsp32, {RISCV::FeatureVendorXMIPSLSP}, "MIPS mips.lsp"},
+    {DecoderTableXmipscmove32,
+     {RISCV::FeatureVendorXMIPSCMove},
+     "MIPS mips.ccmov"},
+    // Standard Extensions
+    {DecoderTableXCV32, XCVFeatureGroup, "CORE-V extensions"},
+    {DecoderTableXqci32, XqciFeatureGroup, "Qualcomm uC Extensions"},
+    {DecoderTableXRivos32, XRivosFeatureGroup, "Rivos"},
+    {DecoderTable32, {}, "RISCV32"},
+    {DecoderTableRV32GPRPair32, {}, "RV32GPRPair (rv32 and GPR pairs)"},
+    {DecoderTableZfinx32, {}, "Zfinx (Float in Integer)"},
+    {DecoderTableZdinxRV32GPRPair32,
+     {},
+     "ZdinxRV32GPRPair (rv32 and Double in Integer)"},
+};
+
 DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
                                                  ArrayRef<uint8_t> Bytes,
                                                  uint64_t Address,
@@ -693,37 +708,40 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
 
   uint32_t Insn = support::endian::read32le(Bytes.data());
 
-  TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXVentanaCondOps,
-                        DecoderTableXVentana32, "XVentanaCondOps");
-  TRY_TO_DECODE_FEATURE_ANY(XTHeadGroup, DecoderTableXTHead32,
-                            "T-Head extensions");
-  TRY_TO_DECODE_FEATURE_ANY(XSfVectorGroup, DecoderTableXSfvector32,
-                            "SiFive vector extensions");
-  TRY_TO_DECODE_FEATURE_ANY(XSfSystemGroup, DecoderTableXSfsystem32,
-                            "SiFive system extensions");
-  TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSfcease, DecoderTableXSfcease32,
-                        "SiFive sf.cease");
-  TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXMIPSLSP, DecoderTableXmipslsp32,
-                        "MIPS mips.lsp");
-  TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXMIPSCMove,
-                        DecoderTableXmipscmove32, "MIPS mips.ccmov");
-  TRY_TO_DECODE_FEATURE_ANY(XCVFeatureGroup, DecoderTableXCV32,
-                            "CORE-V extensions");
-  TRY_TO_DECODE_FEATURE_ANY(XqciFeatureGroup, DecoderTableXqci32,
-                            "Qualcomm uC Extensions");
-
-  TRY_TO_DECODE_FEATURE_ANY(XRivosFeatureGroup, DecoderTableXRivos32, "Rivos");
-
-  TRY_TO_DECODE(true, DecoderTable32, "RISCV32");
-  TRY_TO_DECODE(true, DecoderTableRV32GPRPair32,
-                "RV32GPRPair (rv32 and GPR pairs)");
-  TRY_TO_DECODE(true, DecoderTableZfinx32, "Zfinx (Float in Integer)");
-  TRY_TO_DECODE(true, DecoderTableZdinxRV32GPRPair32,
-                "ZdinxRV32GPRPair (rv32 and Double in Integer)");
+  for (const DecoderListEntry &Entry : DecoderList32) {
+    if (!Entry.haveRequiredFeatures(STI.getFeatureBits()))
+      continue;
+
+    LLVM_DEBUG(dbgs() << "Trying " << Entry.Desc << "table:\n");
+    DecodeStatus Result =
+        decodeInstruction(Entry.Table, MI, Insn, Address, this, STI);
+    if (Result == MCDisassembler::Fail)
+      continue;
+
+    return Result;
+  }
 
   return MCDisassembler::Fail;
 }
 
+static constexpr DecoderListEntry DecoderList16[]{
+    // Vendor Extensions
+    {DecoderTableXqci16, XqciFeatureGroup, "Qualcomm uC 16bit"},
+    {DecoderTableXqccmp16,
+     {RISCV::FeatureVendorXqccmp},
+     "Xqccmp (Qualcomm 16-bit Push/Pop & Double Move Instructions)"},
+    {DecoderTableXwchc16, {RISCV::FeatureVendorXwchc}, "WCH QingKe XW"},
+    // Standard Extensions
+    // DecoderTableZicfiss16 must be checked before DecoderTable16.
+    {DecoderTableZicfiss16, {}, "RVZicfiss (Shadow Stack)"},
+    {DecoderTable16, {}, "RISCV_C (16-bit Instruction)"},
+    {DecoderTableRISCV32Only_16, {}, "RISCV32Only_16 (16-bit Instruction)"},
+    // Zc* instructions incompatible with Zcf or Zcd
+    {DecoderTableZcOverlap16,
+     {},
+     "ZcOverlap (16-bit Instructions overlapping with Zcf/Zcd)"},
+};
+
 DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
                                                  ArrayRef<uint8_t> Bytes,
                                                  uint64_t Address,
@@ -736,27 +754,28 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
 
   uint32_t Insn = support::endian::read16le(Bytes.data());
 
-  TRY_TO_DECODE_FEATURE_ANY(XqciFeatureGroup, DecoderTableXqci16,
-                            "Qualcomm uC 16bit");
-  TRY_TO_DECODE_FEATURE(
-      RISCV::FeatureVendorXqccmp, DecoderTableXqccmp16,
-      "Xqccmp (Qualcomm 16-bit Push/Pop & Double Move Instructions)");
-  TRY_TO_DECODE_AND_ADD_SP(STI.hasFeature(RISCV::FeatureVendorXwchc),
-                           DecoderTableXwchc16, "WCH QingKe XW");
-
-  // DecoderTableZicfiss16 must be checked before DecoderTable16.
-  TRY_TO_DECODE(true, DecoderTableZicfiss16, "RVZicfiss (Shadow Stack)");
-  TRY_TO_DECODE_AND_ADD_SP(true, DecoderTable16,
-                           "RISCV_C (16-bit Instruction)");
-  TRY_TO_DECODE_AND_ADD_SP(true, DecoderTableRISCV32Only_16,
-                           "RISCV32Only_16 (16-bit Instruction)");
-  // Zc* instructions incompatible with Zcf or Zcd.
-  TRY_TO_DECODE(true, DecoderTableZcOverlap16,
-                "ZcOverlap (16-bit Instructions overlapping with Zcf/Zcd)");
+  for (const DecoderListEntry &Entry : DecoderList16) {
+    if (!Entry.haveRequiredFeatures(STI.getFeatureBits()))
+      continue;
+
+    LLVM_DEBUG(dbgs() << "Trying " << Entry.Desc << "table:\n");
+    DecodeStatus Result =
+        decodeInstruction(Entry.Table, MI, Insn, Address, this, STI);
+    if (Result == MCDisassembler::Fail)
+      continue;
+
+    addSPOperands(MI);
+
+    return Result;
+  }
 
   return MCDisassembler::Fail;
 }
 
+static constexpr DecoderListEntry DecoderList48[]{
+    {DecoderTableXqci48, XqciFeatureGroup, "Qualcomm uC 48bit"},
+};
+
 DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
                                                  ArrayRef<uint8_t> Bytes,
                                                  uint64_t Address,
@@ -768,11 +787,21 @@ DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
   Size = 6;
 
   uint64_t Insn = 0;
-  for (size_t i = Size; i-- != 0;) {
+  for (size_t i = Size; i-- != 0;)
     Insn += (static_cast<uint64_t>(Bytes[i]) << 8 * i);
+
+  for (const DecoderListEntry &Entry : DecoderList48) {
+    if (!Entry.haveRequiredFeatures(STI.getFeatureBits()))
+      continue;
+
+    LLVM_DEBUG(dbgs() << "Trying " << Entry.Desc << "table:\n");
+    DecodeStatus Result =
+        decodeInstruction(Entry.Table, MI, Insn, Address, this, STI);
+    if (Result == MCDisassembler::Fail)
+      continue;
+
+    return Result;
   }
-  TRY_TO_DECODE_FEATURE_ANY(XqciFeatureGroup, DecoderTableXqci48,
-                            "Qualcomm uC 48bit");
 
   return MCDisassembler::Fail;
 }

Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach seems reasonable to me, and the direction we've been working towards.

One naming issue, but overall I'm happy with this.

@wangpc-pp wangpc-pp removed the request for review from pcwang-thead March 12, 2025 04:08
Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the name update.

Agreed that it's simplest to just always invoke addSPOperands.

@topperc topperc merged commit 62e37a8 into llvm:main Mar 13, 2025
11 checks passed
@topperc topperc deleted the pr/disassembler-list branch March 13, 2025 03:15
frederik-h pushed a commit to frederik-h/llvm-project that referenced this pull request Mar 18, 2025
… their associated features. NFC (llvm#130883)

Replace the macros with a table that we can iterate over. Use a
different table for each possible instruction bitwidth.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants