aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/DecoderEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/DecoderEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/DecoderEmitter.cpp115
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"