181ad6265SDimitry Andric //==- X86MnemonicTables.cpp - Generate mnemonic extraction tables. -*- C++ -*-// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This tablegen backend is responsible for emitting tables that group 1081ad6265SDimitry Andric // instructions by their mnemonic name wrt AsmWriter Variant (e.g. isADD, etc). 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 14*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h" 15*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 1681ad6265SDimitry Andric #include "X86RecognizableInstr.h" 1706c3fb27SDimitry Andric #include "llvm/TableGen/Record.h" 1881ad6265SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 1981ad6265SDimitry Andric 2081ad6265SDimitry Andric using namespace llvm; 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric namespace { 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric class X86MnemonicTablesEmitter { 2581ad6265SDimitry Andric CodeGenTarget Target; 2681ad6265SDimitry Andric 2781ad6265SDimitry Andric public: 2881ad6265SDimitry Andric X86MnemonicTablesEmitter(RecordKeeper &R) : Target(R) {} 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric // Output X86 mnemonic tables. 3181ad6265SDimitry Andric void run(raw_ostream &OS); 3281ad6265SDimitry Andric }; 3381ad6265SDimitry Andric 3481ad6265SDimitry Andric void X86MnemonicTablesEmitter::run(raw_ostream &OS) { 3581ad6265SDimitry Andric emitSourceFileHeader("X86 Mnemonic tables", OS); 3681ad6265SDimitry Andric OS << "namespace llvm {\nnamespace X86 {\n\n"; 3781ad6265SDimitry Andric Record *AsmWriter = Target.getAsmWriter(); 3881ad6265SDimitry Andric unsigned Variant = AsmWriter->getValueAsInt("Variant"); 3981ad6265SDimitry Andric 4081ad6265SDimitry Andric // Hold all instructions grouped by mnemonic 4181ad6265SDimitry Andric StringMap<SmallVector<const CodeGenInstruction *, 0>> MnemonicToCGInstrMap; 4281ad6265SDimitry Andric 4381ad6265SDimitry Andric ArrayRef<const CodeGenInstruction *> NumberedInstructions = 4481ad6265SDimitry Andric Target.getInstructionsByEnumValue(); 4581ad6265SDimitry Andric for (const CodeGenInstruction *I : NumberedInstructions) { 4681ad6265SDimitry Andric const Record *Def = I->TheDef; 4781ad6265SDimitry Andric // Filter non-X86 instructions. 4881ad6265SDimitry Andric if (!Def->isSubClassOf("X86Inst")) 4981ad6265SDimitry Andric continue; 5081ad6265SDimitry Andric X86Disassembler::RecognizableInstrBase RI(*I); 5181ad6265SDimitry Andric if (!RI.shouldBeEmitted()) 5281ad6265SDimitry Andric continue; 5381ad6265SDimitry Andric if ( // Non-parsable instruction defs contain prefix as part of AsmString 5481ad6265SDimitry Andric Def->getValueAsString("AsmVariantName") == "NonParsable" || 5581ad6265SDimitry Andric // Skip prefix byte 5681ad6265SDimitry Andric RI.Form == X86Local::PrefixByte) 5781ad6265SDimitry Andric continue; 5881ad6265SDimitry Andric std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant); 5981ad6265SDimitry Andric MnemonicToCGInstrMap[Mnemonic].push_back(I); 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric OS << "#ifdef GET_X86_MNEMONIC_TABLES_H\n"; 6381ad6265SDimitry Andric OS << "#undef GET_X86_MNEMONIC_TABLES_H\n\n"; 6481ad6265SDimitry Andric for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) 6581ad6265SDimitry Andric OS << "bool is" << Mnemonic << "(unsigned Opcode);\n"; 6681ad6265SDimitry Andric OS << "#endif // GET_X86_MNEMONIC_TABLES_H\n\n"; 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric OS << "#ifdef GET_X86_MNEMONIC_TABLES_CPP\n"; 6981ad6265SDimitry Andric OS << "#undef GET_X86_MNEMONIC_TABLES_CPP\n\n"; 7081ad6265SDimitry Andric for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) { 7181ad6265SDimitry Andric OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n"; 7281ad6265SDimitry Andric auto Mnemonics = MnemonicToCGInstrMap[Mnemonic]; 7381ad6265SDimitry Andric if (Mnemonics.size() == 1) { 7481ad6265SDimitry Andric const CodeGenInstruction *CGI = *Mnemonics.begin(); 7581ad6265SDimitry Andric OS << "\treturn Opcode == " << CGI->TheDef->getName() << ";\n}\n\n"; 7681ad6265SDimitry Andric } else { 7781ad6265SDimitry Andric OS << "\tswitch (Opcode) {\n"; 7881ad6265SDimitry Andric for (const CodeGenInstruction *CGI : Mnemonics) { 7981ad6265SDimitry Andric OS << "\tcase " << CGI->TheDef->getName() << ":\n"; 8081ad6265SDimitry Andric } 8181ad6265SDimitry Andric OS << "\t\treturn true;\n\t}\n\treturn false;\n}\n\n"; 8281ad6265SDimitry Andric } 8381ad6265SDimitry Andric } 8481ad6265SDimitry Andric OS << "#endif // GET_X86_MNEMONIC_TABLES_CPP\n\n"; 8581ad6265SDimitry Andric OS << "} // end namespace X86\n} // end namespace llvm"; 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric 8881ad6265SDimitry Andric } // namespace 8981ad6265SDimitry Andric 9006c3fb27SDimitry Andric static TableGen::Emitter::OptClass<X86MnemonicTablesEmitter> 9106c3fb27SDimitry Andric X("gen-x86-mnemonic-tables", "Generate X86 mnemonic tables"); 92