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