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 const CodeGenTarget Target; 26 27 public: 28 X86MnemonicTablesEmitter(const 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 const 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 for (const CodeGenInstruction *I : Target.getInstructionsByEnumValue()) { 44 const Record *Def = I->TheDef; 45 // Filter non-X86 instructions. 46 if (!Def->isSubClassOf("X86Inst")) 47 continue; 48 X86Disassembler::RecognizableInstrBase RI(*I); 49 if (!RI.shouldBeEmitted()) 50 continue; 51 if ( // Non-parsable instruction defs contain prefix as part of AsmString 52 Def->getValueAsString("AsmVariantName") == "NonParsable" || 53 // Skip prefix byte 54 RI.Form == X86Local::PrefixByte) 55 continue; 56 std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant); 57 MnemonicToCGInstrMap[Mnemonic].push_back(I); 58 } 59 60 OS << "#ifdef GET_X86_MNEMONIC_TABLES_H\n"; 61 OS << "#undef GET_X86_MNEMONIC_TABLES_H\n\n"; 62 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) 63 OS << "bool is" << Mnemonic << "(unsigned Opcode);\n"; 64 OS << "#endif // GET_X86_MNEMONIC_TABLES_H\n\n"; 65 66 OS << "#ifdef GET_X86_MNEMONIC_TABLES_CPP\n"; 67 OS << "#undef GET_X86_MNEMONIC_TABLES_CPP\n\n"; 68 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) { 69 OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n"; 70 auto Mnemonics = MnemonicToCGInstrMap[Mnemonic]; 71 if (Mnemonics.size() == 1) { 72 const CodeGenInstruction *CGI = *Mnemonics.begin(); 73 OS << "\treturn Opcode == " << CGI->TheDef->getName() << ";\n}\n\n"; 74 } else { 75 OS << "\tswitch (Opcode) {\n"; 76 for (const CodeGenInstruction *CGI : Mnemonics) { 77 OS << "\tcase " << CGI->TheDef->getName() << ":\n"; 78 } 79 OS << "\t\treturn true;\n\t}\n\treturn false;\n}\n\n"; 80 } 81 } 82 OS << "#endif // GET_X86_MNEMONIC_TABLES_CPP\n\n"; 83 OS << "} // end namespace X86\n} // end namespace llvm"; 84 } 85 86 } // namespace 87 88 static TableGen::Emitter::OptClass<X86MnemonicTablesEmitter> 89 X("gen-x86-mnemonic-tables", "Generate X86 mnemonic tables"); 90