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
20using namespace llvm;
21
22namespace {
23
24class X86MnemonicTablesEmitter {
25 const CodeGenTarget Target;
26
27public:
28 X86MnemonicTablesEmitter(const RecordKeeper &R) : Target(R) {}
29
30 // Output X86 mnemonic tables.
31 void run(raw_ostream &OS);
32};
33
34void X86MnemonicTablesEmitter::run(raw_ostream &OS) {
35 emitSourceFileHeader(Desc: "X86 Mnemonic tables", OS);
36 OS << "namespace llvm {\nnamespace X86 {\n\n";
37 const Record *AsmWriter = Target.getAsmWriter();
38 unsigned Variant = AsmWriter->getValueAsInt(FieldName: "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(Name: "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(FieldName: "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(Elt: 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
88static TableGen::Emitter::OptClass<X86MnemonicTablesEmitter>
89 X("gen-x86-mnemonic-tables", "Generate X86 mnemonic tables");
90