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 +// CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeInstruction +// CHECK-SPECIALIZE-NO-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); +// CHECK-SPECIALIZE-NO-TABLE-NEXT: assert(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: assert(InsnBitWidth == 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 == 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 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,