From 300a2f8d4542492957178344820044f78050d9fc Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Wed, 3 Sep 2025 11:56:11 -0700 Subject: [PATCH 1/4] [LLVM][MC][DecoderEmitter] Encode BitWidth at the start of the table --- .../DecoderEmitterBitwidthSpecialization.td | 22 ++++++++++--- llvm/utils/TableGen/DecoderEmitter.cpp | 32 +++++++++++++++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td b/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td index b4142e983ef77..701f5ce430bc0 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 +// CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeInstruction +// CHECK-SPECIALIZE-NO-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); +// CHECK-SPECIALIZE-NO-TABLE-NEXT: if (InsnBitWidth != 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 +// CHECK-SPECIALIZE-TABLE-NEXT: decodeInstruction +// CHECK-SPECIALIZE-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); +// CHECK-SPECIALIZE-TABLE-NEXT: if (InsnBitWidth != BitWidth) diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index fcaf433918092..8479e228d38cd 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 early return 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,22 @@ 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) { + // Return early if the decoder table's bitwidth does not match `InsnType` + // bitwidth. + OS << R"( + uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); + if (InsnBitWidth != BitWidth) { + LLVM_DEBUG({ + dbgs() << "Mismatch between table bitwidth and instruction bitwidth"; + }); + return MCDisassembler::Fail; + })"; + } OS << R"( - const uint8_t *Ptr = DecodeTable; uint64_t CurFieldValue = 0; DecodeStatus S = MCDisassembler::Success; while (true) { @@ -2554,7 +2580,7 @@ template 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, From 6b3caa710a4c33b071ad5ad5620cc6393d6e314d Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Wed, 3 Sep 2025 14:46:37 -0700 Subject: [PATCH 2/4] Make mismatch a fatal error --- llvm/utils/TableGen/DecoderEmitter.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 8479e228d38cd..6e866d816d2cb 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -779,7 +779,7 @@ unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS, }; // The first entry when specializing decoders per bitwidth is the bitwidth. - // This will be used for early return in `decodeInstruction`. + // This will be used for additional checks in `decodeInstruction`. if (SpecializeDecodersPerBitwidth) { OS << "/* 0 */"; OS.PadToColumn(14); @@ -2124,16 +2124,13 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, OS << " const uint8_t *Ptr = DecodeTable;\n"; if (SpecializeDecodersPerBitwidth) { - // Return early if the decoder table's bitwidth does not match `InsnType` - // bitwidth. + // Fail with a fatal error if decoder table's bitwidth does not match + // `InsnType` bitwidth. OS << R"( uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); - if (InsnBitWidth != BitWidth) { - LLVM_DEBUG({ - dbgs() << "Mismatch between table bitwidth and instruction bitwidth"; - }); - return MCDisassembler::Fail; - })"; + if (InsnBitWidth != BitWidth) + llvm_unreachable("Table and instruction bitwidth mismatch"); +)"; } OS << R"( From 1535051753d2a2cf1435a238eda9802e12518036 Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Wed, 3 Sep 2025 15:06:22 -0700 Subject: [PATCH 3/4] Use assert instead of llvm_unreachable --- llvm/utils/TableGen/DecoderEmitter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 6e866d816d2cb..2b06cfc7c3138 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -2127,9 +2127,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, // Fail with a fatal error if decoder table's bitwidth does not match // `InsnType` bitwidth. OS << R"( - uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); - if (InsnBitWidth != BitWidth) - llvm_unreachable("Table and instruction bitwidth mismatch"); + [[maybe_unused]] uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); + assert(InsnBitWidth == BitWidth && + "Table and instruction bitwidth mismatch"); )"; } From 34be441c09041703515e448e00f70d549364b01a Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Wed, 3 Sep 2025 15:22:52 -0700 Subject: [PATCH 4/4] Fix lit test --- llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td b/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td index 701f5ce430bc0..c656616a62451 100644 --- a/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td +++ b/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td @@ -132,7 +132,7 @@ def Inst3 : Instruction16Bit<3> { // CHECK-SPECIALIZE-NO-TABLE-LABEL: template // CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeInstruction // CHECK-SPECIALIZE-NO-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); -// CHECK-SPECIALIZE-NO-TABLE-NEXT: if (InsnBitWidth != BitWidth) +// CHECK-SPECIALIZE-NO-TABLE-NEXT: assert(InsnBitWidth == BitWidth && // ----------------------------------------------------------------------------- // Per bitwidth specialization with function table. @@ -186,4 +186,4 @@ def Inst3 : Instruction16Bit<3> { // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: decodeInstruction // CHECK-SPECIALIZE-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); -// CHECK-SPECIALIZE-TABLE-NEXT: if (InsnBitWidth != BitWidth) +// CHECK-SPECIALIZE-TABLE-NEXT: assert(InsnBitWidth == BitWidth &&