[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