[llvm] c8e760e - [LLVM][MC][DecoderEmitter] Fail fatally if `Insn` and decoder table bitwidths mismatch (#156734)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 4 05:59:17 PDT 2025


Author: Rahul Joshi
Date: 2025-09-04T05:59:13-07:00
New Revision: c8e760e03b41a327b05b71ab76a120dc0927f6a5

URL: https://github.com/llvm/llvm-project/commit/c8e760e03b41a327b05b71ab76a120dc0927f6a5
DIFF: https://github.com/llvm/llvm-project/commit/c8e760e03b41a327b05b71ab76a120dc0927f6a5.diff

LOG: [LLVM][MC][DecoderEmitter] Fail fatally if `Insn` and decoder table bitwidths mismatch (#156734)

Added: 
    

Modified: 
    llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td
    llvm/utils/TableGen/DecoderEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td b/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td
index b4142e983ef77..c656616a62451 100644
--- a/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td
+++ b/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td
@@ -105,7 +105,8 @@ def Inst3 : Instruction16Bit<3> {
 // When we specialize per bitwidth, we emit 2 decodeToMCInst functions and
 // DecodeIdx is assigned per bit width.
 
-// CHECK-SPECIALIZE-NO-TABLE-LABEL:   DecoderTable8[25]
+// CHECK-SPECIALIZE-NO-TABLE-LABEL:   DecoderTable8[26]
+// CHECK-SPECIALIZE-NO-TABLE:           /* 0 */ 8, // Bitwidth 8
 // CHECK-SPECIALIZE-NO-TABLE:           DecodeIdx: 0
 // CHECK-SPECIALIZE-NO-TABLE:           DecodeIdx: 1
 // CHECK-SPECIALIZE-NO-TABLE:         };
@@ -116,7 +117,8 @@ def Inst3 : Instruction16Bit<3> {
 // CHECK-SPECIALIZE-NO-TABLE:           case 0
 // CHECK-SPECIALIZE-NO-TABLE:           case 1
 
-// CHECK-SPECIALIZE-NO-TABLE-LABEL:   DecoderTable16[25]
+// CHECK-SPECIALIZE-NO-TABLE-LABEL:   DecoderTable16[26]
+// CHECK-SPECIALIZE-NO-TABLE:           /* 0 */ 16, // Bitwidth 16
 // CHECK-SPECIALIZE-NO-TABLE:           DecodeIdx: 0
 // CHECK-SPECIALIZE-NO-TABLE:           DecodeIdx: 1
 // CHECK-SPECIALIZE-NO-TABLE:         };
@@ -127,11 +129,17 @@ def Inst3 : Instruction16Bit<3> {
 // CHECK-SPECIALIZE-NO-TABLE:           case 0
 // CHECK-SPECIALIZE-NO-TABLE:           case 1
 
+// CHECK-SPECIALIZE-NO-TABLE-LABEL:   template <typename InsnType>
+// CHECK-SPECIALIZE-NO-TABLE-NEXT:    decodeInstruction
+// CHECK-SPECIALIZE-NO-TABLE:         uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);
+// CHECK-SPECIALIZE-NO-TABLE-NEXT:    assert(InsnBitWidth<InsnType> == BitWidth &&
+
 // -----------------------------------------------------------------------------
 // Per bitwidth specialization with function table.
 
 // 8 bit deccoder table, functions, and function table.
-// CHECK-SPECIALIZE-TABLE-LABEL:    DecoderTable8[25]
+// CHECK-SPECIALIZE-TABLE-LABEL:    DecoderTable8[26]
+// CHECK-SPECIALIZE-TABLE:           /* 0 */ 8, // Bitwidth 8
 // CHECK-SPECIALIZE-TABLE:            DecodeIdx: 0
 // CHECK-SPECIALIZE-TABLE:            DecodeIdx: 1
 // CHECK-SPECIALIZE-TABLE:          };
@@ -153,7 +161,8 @@ def Inst3 : Instruction16Bit<3> {
 // CHECK-SPECIALIZE-TABLE-NEXT:     };
 
 // 16 bit deccoder table, functions, and function table.
-// CHECK-SPECIALIZE-TABLE-LABEL:    DecoderTable16[25]
+// CHECK-SPECIALIZE-TABLE-LABEL:    DecoderTable16[26]
+// CHECK-SPECIALIZE-TABLE:            /* 0 */ 16, // Bitwidth 16
 // CHECK-SPECIALIZE-TABLE:            DecodeIdx: 0
 // CHECK-SPECIALIZE-TABLE:            DecodeIdx: 1
 // CHECK-SPECIALIZE-TABLE:          };
@@ -173,3 +182,8 @@ def Inst3 : Instruction16Bit<3> {
 // CHECK-SPECIALIZE-TABLE-NEXT:       decodeFn_16bit_0,
 // CHECK-SPECIALIZE-TABLE-NEXT:       decodeFn_16bit_1,
 // CHECK-SPECIALIZE-TABLE-NEXT:     };
+
+// CHECK-SPECIALIZE-TABLE-LABEL:    template <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT:     decodeInstruction
+// CHECK-SPECIALIZE-TABLE:          uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);
+// CHECK-SPECIALIZE-TABLE-NEXT:     assert(InsnBitWidth<InsnType> == BitWidth &&

diff  --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index fcaf433918092..2b06cfc7c3138 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -611,7 +611,11 @@ class DecoderTableBuilder {
                       DecoderTableInfo &TableInfo)
       : Target(Target), Encodings(Encodings), TableInfo(TableInfo) {}
 
-  void buildTable(const FilterChooser &FC) const {
+  void buildTable(const FilterChooser &FC, unsigned BitWidth) const {
+    // When specializing decoders per bit width, each decoder table will begin
+    // with the bitwidth for that table.
+    if (SpecializeDecodersPerBitwidth)
+      TableInfo.Table.insertULEB128(BitWidth);
     emitTableEntries(FC);
     assert(TableInfo.FixupStack.empty() && "Fixup stack phasing error!");
   }
@@ -774,6 +778,15 @@ unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
     OS << "Skip to: " << Index;
   };
 
+  // The first entry when specializing decoders per bitwidth is the bitwidth.
+  // This will be used for additional checks in `decodeInstruction`.
+  if (SpecializeDecodersPerBitwidth) {
+    OS << "/* 0  */";
+    OS.PadToColumn(14);
+    emitULEB128(I, OS);
+    OS << " // Bitwidth " << BitWidth << '\n';
+  }
+
   unsigned OpcodeMask = 0;
 
   while (I != E) {
@@ -2108,9 +2121,19 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
   if (HasCheckPredicate)
     OS << "  const FeatureBitset &Bits = STI.getFeatureBits();\n";
   OS << "  using namespace llvm::MCD;\n";
+  OS << "  const uint8_t *Ptr = DecodeTable;\n";
+
+  if (SpecializeDecodersPerBitwidth) {
+    // Fail with a fatal error if decoder table's bitwidth does not match
+    // `InsnType` bitwidth.
+    OS << R"(
+  [[maybe_unused]] uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);
+  assert(InsnBitWidth<InsnType> == BitWidth &&
+         "Table and instruction bitwidth mismatch");
+)";
+  }
 
   OS << R"(
-  const uint8_t *Ptr = DecodeTable;
   uint64_t CurFieldValue = 0;
   DecodeStatus S = MCDisassembler::Success;
   while (true) {
@@ -2554,7 +2577,7 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
       //    across all decoder tables.
       //  - predicates are shared across all decoder tables.
       TableInfo.Table.clear();
-      TableBuilder.buildTable(FC);
+      TableBuilder.buildTable(FC, BitWidth);
 
       // Print the table to the output stream.
       OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,


        


More information about the llvm-commits mailing list