//==- X86MnemonicTables.cpp - Generate mnemonic extraction tables. -*- C++ -*-// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This tablegen backend is responsible for emitting tables that group // instructions by their mnemonic name wrt AsmWriter Variant (e.g. isADD, etc). // //===----------------------------------------------------------------------===// #include "Common/CodeGenInstruction.h" #include "Common/CodeGenTarget.h" #include "X86RecognizableInstr.h" #include "llvm/TableGen/CodeGenHelpers.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" using namespace llvm; namespace { class X86MnemonicTablesEmitter { const CodeGenTarget Target; public: X86MnemonicTablesEmitter(const RecordKeeper &R) : Target(R) {} // Output X86 mnemonic tables. void run(raw_ostream &OS); }; } // namespace void X86MnemonicTablesEmitter::run(raw_ostream &OS) { emitSourceFileHeader("X86 Mnemonic tables", OS); const Record *AsmWriter = Target.getAsmWriter(); unsigned Variant = AsmWriter->getValueAsInt("Variant"); // Hold all instructions grouped by mnemonic. StringMap> MnemonicToCGInstrMap; for (const CodeGenInstruction *I : Target.getInstructions()) { const Record *Def = I->TheDef; // Filter non-X86 instructions. if (!Def->isSubClassOf("X86Inst")) continue; X86Disassembler::RecognizableInstrBase RI(*I); if (!RI.shouldBeEmitted()) continue; if ( // Non-parsable instruction defs contain prefix as part of AsmString. Def->getValueAsString("AsmVariantName") == "NonParsable" || // Skip prefix byte. RI.Form == X86Local::PrefixByte) continue; std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant); MnemonicToCGInstrMap[Mnemonic].push_back(I); } { IfDefEmitter IfDef(OS, "GET_X86_MNEMONIC_TABLES_H"); NamespaceEmitter NS(OS, "llvm::X86"); for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) OS << "bool is" << Mnemonic << "(unsigned Opcode);\n"; } { IfDefEmitter IfDef(OS, "GET_X86_MNEMONIC_TABLES_CPP"); NamespaceEmitter NS(OS, "llvm::X86"); for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) { OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n"; const auto &Mnemonics = MnemonicToCGInstrMap[Mnemonic]; if (Mnemonics.size() == 1) { const CodeGenInstruction *CGI = Mnemonics.front(); OS << " return Opcode == " << CGI->getName() << ";\n}\n\n"; } else { OS << " switch (Opcode) {\n"; for (const CodeGenInstruction *CGI : Mnemonics) OS << " case " << CGI->getName() << ":\n"; OS << " return true;\n }\n return false;\n}\n\n"; } } } } static TableGen::Emitter::OptClass X("gen-x86-mnemonic-tables", "Generate X86 mnemonic tables");