@@ -83,11 +83,12 @@ static cl::opt<bool> LargeTable(
8383 " in the table instead of the default 16 bits." ),
8484 cl::init(false ), cl::cat(DisassemblerEmitterCat));
8585
86- static cl::opt<bool > UseLambdaInDecodetoMCInst (
87- " use-lambda-in-decode-to-mcinst" ,
88- cl::desc (" Use a table of lambdas instead of a switch case in the\n "
89- " generated `decodeToMCInst` function. Helps improve compile time\n "
90- " of the generated code." ),
86+ static cl::opt<bool > UseFnTableInDecodetoMCInst (
87+ " use-fn-table-in-decode-to-mcinst" ,
88+ cl::desc (
89+ " Use a table of function pointers instead of a switch case in the\n "
90+ " generated `decodeToMCInst` function. Helps improve compile time\n "
91+ " of the generated code." ),
9192 cl::init(false ), cl::cat(DisassemblerEmitterCat));
9293
9394STATISTIC (NumEncodings, " Number of encodings considered" );
@@ -1073,53 +1074,57 @@ void DecoderEmitter::emitPredicateFunction(formatted_raw_ostream &OS,
10731074void DecoderEmitter::emitDecoderFunction (formatted_raw_ostream &OS,
10741075 DecoderSet &Decoders,
10751076 indent Indent) const {
1076- // The decoder function is just a big switch statement based on the
1077- // input decoder index.
1078- OS << Indent << " template <typename InsnType>\n " ;
1079- OS << Indent << " static DecodeStatus decodeToMCInst(DecodeStatus S,"
1080- << " unsigned Idx, InsnType insn, MCInst &MI,\n " ;
1081- OS << Indent << " uint64_t "
1082- << " Address, const MCDisassembler *Decoder, bool &DecodeComplete) {\n " ;
1083- Indent += 2 ;
1084- OS << Indent << " DecodeComplete = true;\n " ;
1077+ // The decoder function is just a big switch statement or a table of function
1078+ // pointers based on the input decoder index.
1079+
10851080 // TODO: When InsnType is large, using uint64_t limits all fields to 64 bits
10861081 // It would be better for emitBinaryParser to use a 64-bit tmp whenever
10871082 // possible but fall back to an InsnType-sized tmp for truly large fields.
1088- OS << Indent
1089- << " using TmpType = "
1090- " std::conditional_t<std::is_integral<InsnType>::"
1091- " value, InsnType, uint64_t>;\n " ;
1092-
1093- if (UseLambdaInDecodetoMCInst) {
1094- // Emit one lambda for each case first.
1083+ StringRef TmpTypeDecl =
1084+ " using TmpType = std::conditional_t<std::is_integral<InsnType>::value, "
1085+ " InsnType, uint64_t>;\n " ;
1086+ StringRef DecodeParams =
1087+ " DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const "
1088+ " MCDisassembler *Decoder, bool &DecodeComplete" ;
1089+
1090+ if (UseFnTableInDecodetoMCInst) {
1091+ // Emit a function for each case first.
10951092 for (const auto &[Index, Decoder] : enumerate(Decoders)) {
1096- OS << Indent << " auto decodeLambda " << Index << " = [](DecodeStatus S, \n "
1097- << Indent << " InsnType insn, MCInst &MI, \n "
1098- << Indent << " uint64_t Address, \n "
1099- << Indent << " const MCDisassembler *Decoder, \n "
1100- << Indent << " bool &DecodeComplete) { \n " ;
1101- OS << Indent + 2 << " [[maybe_unused]] TmpType tmp;\n " ;
1093+ OS << Indent << " template <typename InsnType> \n " ;
1094+ OS << Indent << " DecodeStatus decodeFn " << Index << " ( " << DecodeParams
1095+ << " ) { \n " ;
1096+ Indent += 2 ;
1097+ OS << Indent << TmpTypeDecl ;
1098+ OS << Indent << " [[maybe_unused]] TmpType tmp;\n " ;
11021099 OS << Decoder;
1103- OS << Indent + 2 << " return S;\n " ;
1104- OS << Indent << " };\n " ;
1100+ OS << Indent << " return S;\n " ;
1101+ Indent -= 2 ;
1102+ OS << Indent << " }\n\n " ;
11051103 }
1106- // Build a table of lambdas.
1104+ }
11071105
1108- OS << R"(
1109- using LambdaTy =
1110- function_ref<DecodeStatus(DecodeStatus, InsnType, MCInst &, uint64_t,
1111- const MCDisassembler *, bool &)>;
1112- )" ;
1113- OS << Indent << " const static LambdaTy decodeLambdaTable[] = {\n " ;
1106+ OS << Indent << " // Handling " << Decoders.size () << " cases.\n " ;
1107+ OS << Indent << " template <typename InsnType>\n " ;
1108+ OS << Indent << " static DecodeStatus decodeToMCInst(unsigned Idx, "
1109+ << DecodeParams << " ) {\n " ;
1110+ Indent += 2 ;
1111+ OS << Indent << " DecodeComplete = true;\n " ;
1112+
1113+ if (UseFnTableInDecodetoMCInst) {
1114+ // Build a table of function pointers.
1115+ OS << Indent << " using DecodeFnTy = DecodeStatus (*)(" << DecodeParams
1116+ << " );\n " ;
1117+ OS << Indent << " static constexpr DecodeFnTy decodeFnTable[] = {\n " ;
11141118 for (size_t Index : llvm::seq (Decoders.size ()))
1115- OS << Indent + 2 << " decodeLambda " << Index << " ,\n " ;
1119+ OS << Indent + 2 << " decodeFn " << Index << " ,\n " ;
11161120 OS << Indent << " };\n " ;
11171121 OS << Indent << " if (Idx >= " << Decoders.size () << " )\n " ;
11181122 OS << Indent + 2 << " llvm_unreachable(\" Invalid index!\" );\n " ;
11191123 OS << Indent
1120- << " return decodeLambdaTable [Idx](S, insn, MI, Address, Decoder, "
1124+ << " return decodeFnTable [Idx](S, insn, MI, Address, Decoder, "
11211125 " DecodeComplete);\n " ;
11221126 } else {
1127+ OS << Indent << TmpTypeDecl;
11231128 OS << Indent << " TmpType tmp;\n " ;
11241129 OS << Indent << " switch (Idx) {\n " ;
11251130 OS << Indent << " default: llvm_unreachable(\" Invalid index!\" );\n " ;
@@ -1306,7 +1311,8 @@ std::pair<unsigned, bool> FilterChooser::getDecoderIndex(DecoderSet &Decoders,
13061311 // FIXME: emitDecoder() function can take a buffer directly rather than
13071312 // a stream.
13081313 raw_svector_ostream S (Decoder);
1309- bool HasCompleteDecoder = emitDecoder (S, indent (4 ), Opc);
1314+ indent Indent (UseFnTableInDecodetoMCInst ? 2 : 4 );
1315+ bool HasCompleteDecoder = emitDecoder (S, Indent, Opc);
13101316
13111317 // Using the full decoder string as the key value here is a bit
13121318 // heavyweight, but is effective. If the string comparisons become a
@@ -2410,7 +2416,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
24102416 << " makeUp(insn, Len);" ;
24112417 }
24122418 OS << R"(
2413- S = decodeToMCInst(S, DecodeIdx , insn, MI, Address, DisAsm, DecodeComplete);
2419+ S = decodeToMCInst(DecodeIdx, S , insn, MI, Address, DisAsm, DecodeComplete);
24142420 assert(DecodeComplete);
24152421
24162422 LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
@@ -2432,7 +2438,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
24322438 MCInst TmpMI;
24332439 TmpMI.setOpcode(Opc);
24342440 bool DecodeComplete;
2435- S = decodeToMCInst(S, DecodeIdx , insn, TmpMI, Address, DisAsm, DecodeComplete);
2441+ S = decodeToMCInst(DecodeIdx, S , insn, TmpMI, Address, DisAsm, DecodeComplete);
24362442 LLVM_DEBUG(dbgs() << Loc << ": OPC_TryDecode: opcode " << Opc
24372443 << ", using decoder " << DecodeIdx << ": ");
24382444
0 commit comments