1*81ad6265SDimitry Andric //==- X86MnemonicTables.cpp - Generate mnemonic extraction tables. -*- C++ -*-// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // This tablegen backend is responsible for emitting tables that group 10*81ad6265SDimitry Andric // instructions by their mnemonic name wrt AsmWriter Variant (e.g. isADD, etc). 11*81ad6265SDimitry Andric // 12*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 13*81ad6265SDimitry Andric 14*81ad6265SDimitry Andric #include "CodeGenInstruction.h" 15*81ad6265SDimitry Andric #include "CodeGenTarget.h" 16*81ad6265SDimitry Andric #include "X86RecognizableInstr.h" 17*81ad6265SDimitry Andric #include "llvm/TableGen/Error.h" 18*81ad6265SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 19*81ad6265SDimitry Andric 20*81ad6265SDimitry Andric using namespace llvm; 21*81ad6265SDimitry Andric 22*81ad6265SDimitry Andric namespace { 23*81ad6265SDimitry Andric 24*81ad6265SDimitry Andric class X86MnemonicTablesEmitter { 25*81ad6265SDimitry Andric CodeGenTarget Target; 26*81ad6265SDimitry Andric 27*81ad6265SDimitry Andric public: 28*81ad6265SDimitry Andric X86MnemonicTablesEmitter(RecordKeeper &R) : Target(R) {} 29*81ad6265SDimitry Andric 30*81ad6265SDimitry Andric // Output X86 mnemonic tables. 31*81ad6265SDimitry Andric void run(raw_ostream &OS); 32*81ad6265SDimitry Andric }; 33*81ad6265SDimitry Andric 34*81ad6265SDimitry Andric void X86MnemonicTablesEmitter::run(raw_ostream &OS) { 35*81ad6265SDimitry Andric emitSourceFileHeader("X86 Mnemonic tables", OS); 36*81ad6265SDimitry Andric OS << "namespace llvm {\nnamespace X86 {\n\n"; 37*81ad6265SDimitry Andric Record *AsmWriter = Target.getAsmWriter(); 38*81ad6265SDimitry Andric unsigned Variant = AsmWriter->getValueAsInt("Variant"); 39*81ad6265SDimitry Andric 40*81ad6265SDimitry Andric // Hold all instructions grouped by mnemonic 41*81ad6265SDimitry Andric StringMap<SmallVector<const CodeGenInstruction *, 0>> MnemonicToCGInstrMap; 42*81ad6265SDimitry Andric 43*81ad6265SDimitry Andric ArrayRef<const CodeGenInstruction *> NumberedInstructions = 44*81ad6265SDimitry Andric Target.getInstructionsByEnumValue(); 45*81ad6265SDimitry Andric for (const CodeGenInstruction *I : NumberedInstructions) { 46*81ad6265SDimitry Andric const Record *Def = I->TheDef; 47*81ad6265SDimitry Andric // Filter non-X86 instructions. 48*81ad6265SDimitry Andric if (!Def->isSubClassOf("X86Inst")) 49*81ad6265SDimitry Andric continue; 50*81ad6265SDimitry Andric X86Disassembler::RecognizableInstrBase RI(*I); 51*81ad6265SDimitry Andric if (!RI.shouldBeEmitted()) 52*81ad6265SDimitry Andric continue; 53*81ad6265SDimitry Andric if ( // Non-parsable instruction defs contain prefix as part of AsmString 54*81ad6265SDimitry Andric Def->getValueAsString("AsmVariantName") == "NonParsable" || 55*81ad6265SDimitry Andric // Skip prefix byte 56*81ad6265SDimitry Andric RI.Form == X86Local::PrefixByte) 57*81ad6265SDimitry Andric continue; 58*81ad6265SDimitry Andric std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant); 59*81ad6265SDimitry Andric MnemonicToCGInstrMap[Mnemonic].push_back(I); 60*81ad6265SDimitry Andric } 61*81ad6265SDimitry Andric 62*81ad6265SDimitry Andric OS << "#ifdef GET_X86_MNEMONIC_TABLES_H\n"; 63*81ad6265SDimitry Andric OS << "#undef GET_X86_MNEMONIC_TABLES_H\n\n"; 64*81ad6265SDimitry Andric for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) 65*81ad6265SDimitry Andric OS << "bool is" << Mnemonic << "(unsigned Opcode);\n"; 66*81ad6265SDimitry Andric OS << "#endif // GET_X86_MNEMONIC_TABLES_H\n\n"; 67*81ad6265SDimitry Andric 68*81ad6265SDimitry Andric OS << "#ifdef GET_X86_MNEMONIC_TABLES_CPP\n"; 69*81ad6265SDimitry Andric OS << "#undef GET_X86_MNEMONIC_TABLES_CPP\n\n"; 70*81ad6265SDimitry Andric for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) { 71*81ad6265SDimitry Andric OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n"; 72*81ad6265SDimitry Andric auto Mnemonics = MnemonicToCGInstrMap[Mnemonic]; 73*81ad6265SDimitry Andric if (Mnemonics.size() == 1) { 74*81ad6265SDimitry Andric const CodeGenInstruction *CGI = *Mnemonics.begin(); 75*81ad6265SDimitry Andric OS << "\treturn Opcode == " << CGI->TheDef->getName() << ";\n}\n\n"; 76*81ad6265SDimitry Andric } else { 77*81ad6265SDimitry Andric OS << "\tswitch (Opcode) {\n"; 78*81ad6265SDimitry Andric for (const CodeGenInstruction *CGI : Mnemonics) { 79*81ad6265SDimitry Andric OS << "\tcase " << CGI->TheDef->getName() << ":\n"; 80*81ad6265SDimitry Andric } 81*81ad6265SDimitry Andric OS << "\t\treturn true;\n\t}\n\treturn false;\n}\n\n"; 82*81ad6265SDimitry Andric } 83*81ad6265SDimitry Andric } 84*81ad6265SDimitry Andric OS << "#endif // GET_X86_MNEMONIC_TABLES_CPP\n\n"; 85*81ad6265SDimitry Andric OS << "} // end namespace X86\n} // end namespace llvm"; 86*81ad6265SDimitry Andric } 87*81ad6265SDimitry Andric 88*81ad6265SDimitry Andric } // namespace 89*81ad6265SDimitry Andric 90*81ad6265SDimitry Andric namespace llvm { 91*81ad6265SDimitry Andric void EmitX86MnemonicTables(RecordKeeper &RK, raw_ostream &OS) { 92*81ad6265SDimitry Andric X86MnemonicTablesEmitter(RK).run(OS); 93*81ad6265SDimitry Andric } 94*81ad6265SDimitry Andric } // namespace llvm 95