xref: /llvm-project/llvm/utils/TableGen/X86MnemonicTables.cpp (revision 74335fb7ae7731a57a163524aeffd93911b50a46)
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