3232#include " llvm/Support/CommandLine.h"
3333#include " llvm/Support/Debug.h"
3434#include " llvm/Support/ErrorHandling.h"
35+ #include " llvm/Support/FormatVariadic.h"
3536#include " llvm/Support/FormattedStream.h"
3637#include " llvm/Support/LEB128.h"
38+ #include " llvm/Support/MathExtras.h"
3739#include " llvm/Support/raw_ostream.h"
3840#include " llvm/TableGen/Error.h"
3941#include " llvm/TableGen/Record.h"
@@ -76,6 +78,12 @@ static cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates(
7678 " significantly reducing Table Duplications" )),
7779 cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat));
7880
81+ static cl::opt<uint32_t >
82+ NumToSkipSizeInBytes (" num-to-skip-size" ,
83+ cl::desc (" number of bytes to use for num-to-skip "
84+ " entries in the decoder table (2 or 3)" ),
85+ cl::init(2 ), cl::cat(DisassemblerEmitterCat));
86+
7987STATISTIC (NumEncodings, " Number of encodings considered" );
8088STATISTIC (NumEncodingsLackingDisasm,
8189 " Number of encodings without disassembler info" );
@@ -130,9 +138,20 @@ struct DecoderTable : public std::vector<uint8_t> {
130138 // in the table for patching.
131139 size_t insertNumToSkip () {
132140 size_t Size = size ();
133- insert (end (), 3 , 0 );
141+ insert (end (), NumToSkipSizeInBytes , 0 );
134142 return Size;
135143 }
144+
145+ void patchNumToSkip (size_t FixupIdx, uint32_t Value) {
146+ if (!isUIntN (8 * NumToSkipSizeInBytes, Value))
147+ PrintFatalError (
148+ " disassembler decoding table too large, try --num-to-skip-size=3" );
149+
150+ (*this )[FixupIdx] = static_cast <uint8_t >(Value);
151+ (*this )[FixupIdx + 1 ] = static_cast <uint8_t >(Value >> 8 );
152+ if (NumToSkipSizeInBytes == 3 )
153+ (*this )[FixupIdx + 2 ] = static_cast <uint8_t >(Value >> 16 );
154+ }
136155};
137156struct DecoderTableInfo {
138157 DecoderTable Table;
@@ -692,16 +711,11 @@ static void resolveTableFixups(DecoderTable &Table, const FixupList &Fixups,
692711 // current location.
693712 for (uint32_t FixupIdx : reverse (Fixups)) {
694713 // Calculate the distance from the byte following the fixup entry byte
695- // to the destination. The Target is calculated from after the 24-bit
696- // NumToSkip entry itself, so subtract three from the displacement here
697- // to account for that.
698- uint32_t Delta = DestIdx - FixupIdx - 3 ;
699- // Our NumToSkip entries are 24-bits. Make sure our table isn't too
700- // big.
701- assert (isUInt<24 >(Delta));
702- Table[FixupIdx] = (uint8_t )Delta;
703- Table[FixupIdx + 1 ] = (uint8_t )(Delta >> 8 );
704- Table[FixupIdx + 2 ] = (uint8_t )(Delta >> 16 );
714+ // to the destination. The Target is calculated from after the
715+ // `NumToSkipSizeInBytes`-byte NumToSkip entry itself, so subtract
716+ // `NumToSkipSizeInBytes` from the displacement here to account for that.
717+ uint32_t Delta = DestIdx - FixupIdx - NumToSkipSizeInBytes;
718+ Table.patchNumToSkip (FixupIdx, Delta);
705719 }
706720}
707721
@@ -760,13 +774,11 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
760774
761775 // Now that we've emitted the body of the handler, update the NumToSkip
762776 // of the filter itself to be able to skip forward when false. Subtract
763- // three as to account for the width of the NumToSkip field itself.
777+ // `NumToSkipSizeInBytes` as to account for the width of the NumToSkip
778+ // field itself.
764779 if (PrevFilter) {
765- uint32_t NumToSkip = Table.size () - PrevFilter - 3 ;
766- assert (isUInt<24 >(NumToSkip) && " disassembler decoding table too large!" );
767- Table[PrevFilter] = (uint8_t )NumToSkip;
768- Table[PrevFilter + 1 ] = (uint8_t )(NumToSkip >> 8 );
769- Table[PrevFilter + 2 ] = (uint8_t )(NumToSkip >> 16 );
780+ uint32_t NumToSkip = Table.size () - PrevFilter - NumToSkipSizeInBytes;
781+ Table.patchNumToSkip (PrevFilter, NumToSkip);
770782 }
771783 }
772784
@@ -814,7 +826,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
814826 OS << (unsigned )*I++ << " , " ;
815827 };
816828
817- // Emit 24-bit numtoskip value to OS, returning the NumToSkip value.
829+ // Emit `NumToSkipSizeInBytes`-byte numtoskip value to OS, returning the
830+ // NumToSkip value.
818831 auto emitNumToSkip = [](DecoderTable::const_iterator &I,
819832 formatted_raw_ostream &OS) {
820833 uint8_t Byte = *I++;
@@ -823,9 +836,11 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
823836 Byte = *I++;
824837 OS << (unsigned )Byte << " , " ;
825838 NumToSkip |= Byte << 8 ;
826- Byte = *I++;
827- OS << (unsigned )(Byte) << " , " ;
828- NumToSkip |= Byte << 16 ;
839+ if (NumToSkipSizeInBytes == 3 ) {
840+ Byte = *I++;
841+ OS << (unsigned )(Byte) << " , " ;
842+ NumToSkip |= Byte << 16 ;
843+ }
829844 return NumToSkip;
830845 };
831846
@@ -867,7 +882,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
867882 // The filter value is ULEB128 encoded.
868883 emitULEB128 (I, OS);
869884
870- // 24-bit numtoskip value.
885+ // numtoskip value.
871886 uint32_t NumToSkip = emitNumToSkip (I, OS);
872887 OS << " // Skip to: " << ((I - Table.begin ()) + NumToSkip) << " \n " ;
873888 break ;
@@ -883,7 +898,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
883898 // ULEB128 encoded field value.
884899 emitULEB128 (I, OS);
885900
886- // 24-bit numtoskip value.
901+ // numtoskip value.
887902 uint32_t NumToSkip = emitNumToSkip (I, OS);
888903 OS << " // Skip to: " << ((I - Table.begin ()) + NumToSkip) << " \n " ;
889904 break ;
@@ -893,7 +908,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
893908 OS << Indent << " MCD::OPC_CheckPredicate, " ;
894909 emitULEB128 (I, OS);
895910
896- // 24-bit numtoskip value.
911+ // numtoskip value.
897912 uint32_t NumToSkip = emitNumToSkip (I, OS);
898913 OS << " // Skip to: " << ((I - Table.begin ()) + NumToSkip) << " \n " ;
899914 break ;
@@ -925,7 +940,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
925940
926941 // Fallthrough for OPC_TryDecode.
927942
928- // 24-bit numtoskip value.
943+ // numtoskip value.
929944 uint32_t NumToSkip = emitNumToSkip (I, OS);
930945
931946 OS << " // Opcode: " << NumberedEncodings[EncodingID]
@@ -1411,9 +1426,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14111426 TableInfo.Table .push_back (NumBits);
14121427 TableInfo.Table .insertULEB128 (Ilnd.FieldVal );
14131428
1414- // The fixup is always 24-bits, so go ahead and allocate the space
1415- // in the table so all our relative position calculations work OK even
1416- // before we fully resolve the real value here.
1429+ // Allocate space in the table for fixup (NumToSkipSizeInBytes) so all
1430+ // our relative position calculations work OK even before we fully
1431+ // resolve the real value here.
14171432
14181433 // Push location for NumToSkip backpatching.
14191434 TableInfo.FixupStack .back ().push_back (TableInfo.Table .insertNumToSkip ());
@@ -2157,7 +2172,18 @@ insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits)
21572172// decodeInstruction().
21582173static void emitDecodeInstruction (formatted_raw_ostream &OS,
21592174 bool IsVarLenInst) {
2175+ OS << formatv (" \n constexpr unsigned NumToSkipSizeInBytes = {};\n " ,
2176+ NumToSkipSizeInBytes);
2177+
21602178 OS << R"(
2179+ inline unsigned decodeNumToSkip(const uint8_t *&Ptr) {
2180+ unsigned NumToSkip = *Ptr++;
2181+ NumToSkip |= (*Ptr++) << 8;
2182+ if constexpr (NumToSkipSizeInBytes == 3)
2183+ NumToSkip |= (*Ptr++) << 16;
2184+ return NumToSkip;
2185+ }
2186+
21612187template <typename InsnType>
21622188static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
21632189 InsnType insn, uint64_t Address,
@@ -2195,10 +2221,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
21952221 // Decode the field value.
21962222 uint64_t Val = decodeULEB128AndIncUnsafe(++Ptr);
21972223 bool Failed = Val != CurFieldValue;
2198- // NumToSkip is a plain 24-bit integer.
2199- unsigned NumToSkip = *Ptr++;
2200- NumToSkip |= (*Ptr++) << 8;
2201- NumToSkip |= (*Ptr++) << 16;
2224+ unsigned NumToSkip = decodeNumToSkip(Ptr);
22022225
22032226 // Perform the filter operation.
22042227 if (Failed)
@@ -2222,10 +2245,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
22222245 uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);
22232246 Ptr += PtrLen;
22242247 bool Failed = ExpectedValue != FieldValue;
2225- // NumToSkip is a plain 24-bit integer.
2226- unsigned NumToSkip = *Ptr++;
2227- NumToSkip |= (*Ptr++) << 8;
2228- NumToSkip |= (*Ptr++) << 16;
2248+ unsigned NumToSkip = decodeNumToSkip(Ptr);
22292249
22302250 // If the actual and expected values don't match, skip.
22312251 if (Failed)
@@ -2240,10 +2260,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
22402260 case MCD::OPC_CheckPredicate: {
22412261 // Decode the Predicate Index value.
22422262 unsigned PIdx = decodeULEB128AndIncUnsafe(++Ptr);
2243- // NumToSkip is a plain 24-bit integer.
2244- unsigned NumToSkip = *Ptr++;
2245- NumToSkip |= (*Ptr++) << 8;
2246- NumToSkip |= (*Ptr++) << 16;
2263+ unsigned NumToSkip = decodeNumToSkip(Ptr);
22472264 // Check the predicate.
22482265 bool Failed = !checkDecoderPredicate(PIdx, Bits);
22492266 if (Failed)
@@ -2278,10 +2295,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
22782295 // Decode the Opcode value.
22792296 unsigned Opc = decodeULEB128AndIncUnsafe(++Ptr);
22802297 unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
2281- // NumToSkip is a plain 24-bit integer.
2282- unsigned NumToSkip = *Ptr++;
2283- NumToSkip |= (*Ptr++) << 8;
2284- NumToSkip |= (*Ptr++) << 16;
2298+ unsigned NumToSkip = decodeNumToSkip(Ptr);
22852299
22862300 // Perform the decode operation.
22872301 MCInst TmpMI;
@@ -2406,6 +2420,9 @@ handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr,
24062420
24072421// Emits disassembler code for instruction decoding.
24082422void DecoderEmitter::run (raw_ostream &o) {
2423+ if (NumToSkipSizeInBytes != 2 && NumToSkipSizeInBytes != 3 )
2424+ PrintFatalError (" Invalid value for num-to-skip-size, must be 2 or 3" );
2425+
24092426 formatted_raw_ostream OS (o);
24102427 OS << R"(
24112428#include "llvm/MC/MCInst.h"
0 commit comments