diff options
Diffstat (limited to 'llvm/utils/TableGen/DecoderEmitter.cpp')
-rw-r--r-- | llvm/utils/TableGen/DecoderEmitter.cpp | 115 |
1 files changed, 65 insertions, 50 deletions
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 9c6015c..0735702 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -32,8 +32,10 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" @@ -76,6 +78,12 @@ static cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates( "significantly reducing Table Duplications")), cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat)); +static cl::opt<uint32_t> + NumToSkipSizeInBytes("num-to-skip-size", + cl::desc("number of bytes to use for num-to-skip " + "entries in the decoder table (2 or 3)"), + cl::init(2), cl::cat(DisassemblerEmitterCat)); + STATISTIC(NumEncodings, "Number of encodings considered"); STATISTIC(NumEncodingsLackingDisasm, "Number of encodings without disassembler info"); @@ -130,10 +138,29 @@ struct DecoderTable : public std::vector<uint8_t> { // in the table for patching. size_t insertNumToSkip() { size_t Size = size(); - insert(end(), 3, 0); + insert(end(), NumToSkipSizeInBytes, 0); return Size; } + + void patchNumToSkip(size_t FixupIdx, uint32_t DestIdx) { + // Calculate the distance from the byte following the fixup entry byte + // to the destination. The Target is calculated from after the + // `NumToSkipSizeInBytes`-byte NumToSkip entry itself, so subtract + // `NumToSkipSizeInBytes` from the displacement here to account for that. + assert(DestIdx > FixupIdx + NumToSkipSizeInBytes && + "Expecting a forward jump in the decoding table"); + uint32_t Delta = DestIdx - FixupIdx - NumToSkipSizeInBytes; + if (!isUIntN(8 * NumToSkipSizeInBytes, Delta)) + PrintFatalError( + "disassembler decoding table too large, try --num-to-skip-size=3"); + + (*this)[FixupIdx] = static_cast<uint8_t>(Delta); + (*this)[FixupIdx + 1] = static_cast<uint8_t>(Delta >> 8); + if (NumToSkipSizeInBytes == 3) + (*this)[FixupIdx + 2] = static_cast<uint8_t>(Delta >> 16); + } }; + struct DecoderTableInfo { DecoderTable Table; FixupScopeList FixupStack; @@ -690,19 +717,8 @@ static void resolveTableFixups(DecoderTable &Table, const FixupList &Fixups, uint32_t DestIdx) { // Any NumToSkip fixups in the current scope can resolve to the // current location. - for (uint32_t FixupIdx : reverse(Fixups)) { - // Calculate the distance from the byte following the fixup entry byte - // to the destination. The Target is calculated from after the 24-bit - // NumToSkip entry itself, so subtract three from the displacement here - // to account for that. - uint32_t Delta = DestIdx - FixupIdx - 3; - // Our NumToSkip entries are 24-bits. Make sure our table isn't too - // big. - assert(isUInt<24>(Delta)); - Table[FixupIdx] = (uint8_t)Delta; - Table[FixupIdx + 1] = (uint8_t)(Delta >> 8); - Table[FixupIdx + 2] = (uint8_t)(Delta >> 16); - } + for (uint32_t FixupIdx : Fixups) + Table.patchNumToSkip(FixupIdx, DestIdx); } // Emit table entries to decode instructions given a segment or segments @@ -759,15 +775,9 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { Delegate->emitTableEntries(TableInfo); // Now that we've emitted the body of the handler, update the NumToSkip - // of the filter itself to be able to skip forward when false. Subtract - // three as to account for the width of the NumToSkip field itself. - if (PrevFilter) { - uint32_t NumToSkip = Table.size() - PrevFilter - 3; - assert(isUInt<24>(NumToSkip) && "disassembler decoding table too large!"); - Table[PrevFilter] = (uint8_t)NumToSkip; - Table[PrevFilter + 1] = (uint8_t)(NumToSkip >> 8); - Table[PrevFilter + 2] = (uint8_t)(NumToSkip >> 16); - } + // of the filter itself to be able to skip forward when false. + if (PrevFilter) + Table.patchNumToSkip(PrevFilter, Table.size()); } // If there is no fallthrough, then the final filter should get fixed @@ -814,7 +824,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, OS << (unsigned)*I++ << ", "; }; - // Emit 24-bit numtoskip value to OS, returning the NumToSkip value. + // Emit `NumToSkipSizeInBytes`-byte numtoskip value to OS, returning the + // NumToSkip value. auto emitNumToSkip = [](DecoderTable::const_iterator &I, formatted_raw_ostream &OS) { uint8_t Byte = *I++; @@ -823,9 +834,11 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, Byte = *I++; OS << (unsigned)Byte << ", "; NumToSkip |= Byte << 8; - Byte = *I++; - OS << (unsigned)(Byte) << ", "; - NumToSkip |= Byte << 16; + if (NumToSkipSizeInBytes == 3) { + Byte = *I++; + OS << (unsigned)(Byte) << ", "; + NumToSkip |= Byte << 16; + } return NumToSkip; }; @@ -867,7 +880,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, // The filter value is ULEB128 encoded. emitULEB128(I, OS); - // 24-bit numtoskip value. + // numtoskip value. uint32_t NumToSkip = emitNumToSkip(I, OS); OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; break; @@ -883,7 +896,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, // ULEB128 encoded field value. emitULEB128(I, OS); - // 24-bit numtoskip value. + // numtoskip value. uint32_t NumToSkip = emitNumToSkip(I, OS); OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; break; @@ -893,7 +906,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, OS << Indent << "MCD::OPC_CheckPredicate, "; emitULEB128(I, OS); - // 24-bit numtoskip value. + // numtoskip value. uint32_t NumToSkip = emitNumToSkip(I, OS); OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; break; @@ -925,7 +938,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, // Fallthrough for OPC_TryDecode. - // 24-bit numtoskip value. + // numtoskip value. uint32_t NumToSkip = emitNumToSkip(I, OS); OS << "// Opcode: " << NumberedEncodings[EncodingID] @@ -1411,9 +1424,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, TableInfo.Table.push_back(NumBits); TableInfo.Table.insertULEB128(Ilnd.FieldVal); - // The fixup is always 24-bits, so go ahead and allocate the space - // in the table so all our relative position calculations work OK even - // before we fully resolve the real value here. + // Allocate space in the table for fixup (NumToSkipSizeInBytes) so all + // our relative position calculations work OK even before we fully + // resolve the real value here. // Push location for NumToSkip backpatching. TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip()); @@ -2157,7 +2170,18 @@ insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits) // decodeInstruction(). static void emitDecodeInstruction(formatted_raw_ostream &OS, bool IsVarLenInst) { + OS << formatv("\nconstexpr unsigned NumToSkipSizeInBytes = {};\n", + NumToSkipSizeInBytes); + OS << R"( +inline unsigned decodeNumToSkip(const uint8_t *&Ptr) { + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + if constexpr (NumToSkipSizeInBytes == 3) + NumToSkip |= (*Ptr++) << 16; + return NumToSkip; +} + template <typename InsnType> static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, InsnType insn, uint64_t Address, @@ -2195,10 +2219,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, // Decode the field value. uint64_t Val = decodeULEB128AndIncUnsafe(++Ptr); bool Failed = Val != CurFieldValue; - // NumToSkip is a plain 24-bit integer. - unsigned NumToSkip = *Ptr++; - NumToSkip |= (*Ptr++) << 8; - NumToSkip |= (*Ptr++) << 16; + unsigned NumToSkip = decodeNumToSkip(Ptr); // Perform the filter operation. if (Failed) @@ -2222,10 +2243,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen); Ptr += PtrLen; bool Failed = ExpectedValue != FieldValue; - // NumToSkip is a plain 24-bit integer. - unsigned NumToSkip = *Ptr++; - NumToSkip |= (*Ptr++) << 8; - NumToSkip |= (*Ptr++) << 16; + unsigned NumToSkip = decodeNumToSkip(Ptr); // If the actual and expected values don't match, skip. if (Failed) @@ -2240,10 +2258,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, case MCD::OPC_CheckPredicate: { // Decode the Predicate Index value. unsigned PIdx = decodeULEB128AndIncUnsafe(++Ptr); - // NumToSkip is a plain 24-bit integer. - unsigned NumToSkip = *Ptr++; - NumToSkip |= (*Ptr++) << 8; - NumToSkip |= (*Ptr++) << 16; + unsigned NumToSkip = decodeNumToSkip(Ptr); // Check the predicate. bool Failed = !checkDecoderPredicate(PIdx, Bits); if (Failed) @@ -2278,10 +2293,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, // Decode the Opcode value. unsigned Opc = decodeULEB128AndIncUnsafe(++Ptr); unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr); - // NumToSkip is a plain 24-bit integer. - unsigned NumToSkip = *Ptr++; - NumToSkip |= (*Ptr++) << 8; - NumToSkip |= (*Ptr++) << 16; + unsigned NumToSkip = decodeNumToSkip(Ptr); // Perform the decode operation. MCInst TmpMI; @@ -2406,6 +2418,9 @@ handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr, // Emits disassembler code for instruction decoding. void DecoderEmitter::run(raw_ostream &o) { + if (NumToSkipSizeInBytes != 2 && NumToSkipSizeInBytes != 3) + PrintFatalError("Invalid value for num-to-skip-size, must be 2 or 3"); + formatted_raw_ostream OS(o); OS << R"( #include "llvm/MC/MCInst.h" |