blob: b9c40659a07fe717c569b5c24314dafb4f9be8c8 [file] [log] [blame] [edit]
//==- X86MnemonicTables.cpp - Generate mnemonic extraction tables. -*- C++ -*-//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting tables that group
// instructions by their mnemonic name wrt AsmWriter Variant (e.g. isADD, etc).
//
//===----------------------------------------------------------------------===//
#include "Common/CodeGenInstruction.h"
#include "Common/CodeGenTarget.h"
#include "X86RecognizableInstr.h"
#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
using namespace llvm;
namespace {
class X86MnemonicTablesEmitter {
const CodeGenTarget Target;
public:
X86MnemonicTablesEmitter(const RecordKeeper &R) : Target(R) {}
// Output X86 mnemonic tables.
void run(raw_ostream &OS);
};
} // namespace
void X86MnemonicTablesEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("X86 Mnemonic tables", OS);
const Record *AsmWriter = Target.getAsmWriter();
unsigned Variant = AsmWriter->getValueAsInt("Variant");
// Hold all instructions grouped by mnemonic.
StringMap<SmallVector<const CodeGenInstruction *, 0>> MnemonicToCGInstrMap;
for (const CodeGenInstruction *I : Target.getInstructions()) {
const Record *Def = I->TheDef;
// Filter non-X86 instructions.
if (!Def->isSubClassOf("X86Inst"))
continue;
X86Disassembler::RecognizableInstrBase RI(*I);
if (!RI.shouldBeEmitted())
continue;
if ( // Non-parsable instruction defs contain prefix as part of AsmString.
Def->getValueAsString("AsmVariantName") == "NonParsable" ||
// Skip prefix byte.
RI.Form == X86Local::PrefixByte)
continue;
std::string Mnemonic = X86Disassembler::getMnemonic(I, Variant);
MnemonicToCGInstrMap[Mnemonic].push_back(I);
}
{
IfDefEmitter IfDef(OS, "GET_X86_MNEMONIC_TABLES_H");
NamespaceEmitter NS(OS, "llvm::X86");
for (StringRef Mnemonic : MnemonicToCGInstrMap.keys())
OS << "bool is" << Mnemonic << "(unsigned Opcode);\n";
}
{
IfDefEmitter IfDef(OS, "GET_X86_MNEMONIC_TABLES_CPP");
NamespaceEmitter NS(OS, "llvm::X86");
for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) {
OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n";
const auto &Mnemonics = MnemonicToCGInstrMap[Mnemonic];
if (Mnemonics.size() == 1) {
const CodeGenInstruction *CGI = Mnemonics.front();
OS << " return Opcode == " << CGI->getName() << ";\n}\n\n";
} else {
OS << " switch (Opcode) {\n";
for (const CodeGenInstruction *CGI : Mnemonics)
OS << " case " << CGI->getName() << ":\n";
OS << " return true;\n }\n return false;\n}\n\n";
}
}
}
}
static TableGen::Emitter::OptClass<X86MnemonicTablesEmitter>
X("gen-x86-mnemonic-tables", "Generate X86 mnemonic tables");