xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/X86MnemonicTables.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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