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