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/CodeGenHelpers.h"
18#include "llvm/TableGen/Record.h"
19#include "llvm/TableGen/TableGenBackend.h"
20
21using namespace llvm;
22
23namespace {
24
25class X86MnemonicTablesEmitter {
26 const CodeGenTarget Target;
27
28public:
29 X86MnemonicTablesEmitter(const RecordKeeper &R) : Target(R) {}
30
31 // Output X86 mnemonic tables.
32 void run(raw_ostream &OS);
33};
34} // namespace
35
36void X86MnemonicTablesEmitter::run(raw_ostream &OS) {
37 emitSourceFileHeader(Desc: "X86 Mnemonic tables", OS);
38 const Record *AsmWriter = Target.getAsmWriter();
39 unsigned Variant = AsmWriter->getValueAsInt(FieldName: "Variant");
40
41 // Hold all instructions grouped by mnemonic.
42 StringMap<SmallVector<const CodeGenInstruction *, 0>> MnemonicToCGInstrMap;
43
44 for (const CodeGenInstruction *I : Target.getInstructions()) {
45 const Record *Def = I->TheDef;
46 // Filter non-X86 instructions.
47 if (!Def->isSubClassOf(Name: "X86Inst"))
48 continue;
49 X86Disassembler::RecognizableInstrBase RI(*I);
50 if (!RI.shouldBeEmitted())
51 continue;
52 if ( // Non-parsable instruction defs contain prefix as part of AsmString.
53 Def->getValueAsString(FieldName: "AsmVariantName") == "NonParsable" ||
54 // Skip prefix byte.
55 RI.Form == X86Local::PrefixByte)
56 continue;
57 std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant);
58 MnemonicToCGInstrMap[Mnemonic].push_back(Elt: I);
59 }
60
61 {
62 IfDefEmitter IfDef(OS, "GET_X86_MNEMONIC_TABLES_H");
63 NamespaceEmitter NS(OS, "llvm::X86");
64 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys())
65 OS << "bool is" << Mnemonic << "(unsigned Opcode);\n";
66 }
67
68 {
69 IfDefEmitter IfDef(OS, "GET_X86_MNEMONIC_TABLES_CPP");
70 NamespaceEmitter NS(OS, "llvm::X86");
71 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) {
72 OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n";
73 const auto &Mnemonics = MnemonicToCGInstrMap[Mnemonic];
74 if (Mnemonics.size() == 1) {
75 const CodeGenInstruction *CGI = Mnemonics.front();
76 OS << " return Opcode == " << CGI->getName() << ";\n}\n\n";
77 } else {
78 OS << " switch (Opcode) {\n";
79 for (const CodeGenInstruction *CGI : Mnemonics)
80 OS << " case " << CGI->getName() << ":\n";
81 OS << " return true;\n }\n return false;\n}\n\n";
82 }
83 }
84 }
85}
86
87static TableGen::Emitter::OptClass<X86MnemonicTablesEmitter>
88 X("gen-x86-mnemonic-tables", "Generate X86 mnemonic tables");
89