diff --git a/llvm/docs/TableGen/BackEnds.rst b/llvm/docs/TableGen/BackEnds.rst --- a/llvm/docs/TableGen/BackEnds.rst +++ b/llvm/docs/TableGen/BackEnds.rst @@ -257,6 +257,12 @@ **Purpose**: This X86 specific tablegen backend emits tables that map EVEX encoded instructions to their VEX encoded identical instruction. +GenPPCInstrMapping +------------------ + +**Purpose**: This PowerPC specific tablegen backend generates the table mapping +instruction opcode to mnemonics in assembly with other information. + Clang BackEnds ============== diff --git a/llvm/lib/Target/PowerPC/CMakeLists.txt b/llvm/lib/Target/PowerPC/CMakeLists.txt --- a/llvm/lib/Target/PowerPC/CMakeLists.txt +++ b/llvm/lib/Target/PowerPC/CMakeLists.txt @@ -15,6 +15,7 @@ tablegen(LLVM PPCGenExegesis.inc -gen-exegesis) tablegen(LLVM PPCGenRegisterBank.inc -gen-register-bank) tablegen(LLVM PPCGenGlobalISel.inc -gen-global-isel) +tablegen(LLVM PPCGenInstrMapping.inc -gen-ppc-instr-mapping) add_public_tablegen_target(PowerPCCommonTableGen) diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt --- a/llvm/utils/TableGen/CMakeLists.txt +++ b/llvm/utils/TableGen/CMakeLists.txt @@ -38,6 +38,7 @@ OptEmitter.cpp OptParserEmitter.cpp OptRSTEmitter.cpp + PPCInstrMappingTableEmitter.cpp PredicateExpander.cpp PseudoLoweringEmitter.cpp RISCVCompressInstEmitter.cpp diff --git a/llvm/utils/TableGen/PPCInstrMappingTableEmitter.cpp b/llvm/utils/TableGen/PPCInstrMappingTableEmitter.cpp new file mode 100644 --- /dev/null +++ b/llvm/utils/TableGen/PPCInstrMappingTableEmitter.cpp @@ -0,0 +1,72 @@ +//===------- PPCInstrMappingTableEmitter.cpp - PowerPC backend---*- 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 the mapping between +// instruction opcode and assembly mnemonics for PowerPC target. +// +//===----------------------------------------------------------------------===// +#include "CodeGenTarget.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/JSON.h" +#include "llvm/TableGen/Record.h" + +using namespace llvm; + +namespace { + +class PPCInstrMappingEmitter { + CodeGenTarget Target; +public: + PPCInstrMappingEmitter(RecordKeeper &R) : Target(R) {} + // run - Generate the mapping tables. + void run(formatted_raw_ostream &OS); +}; + +static std::string parseMnemonic(StringRef Name) { + // What we get now is the full asm string, and we need to get the first token + // that separated by space, which is the instruction mnemonic. We have to + // strip the '\n' as some instruction asm string contains the '\n'. + // TODO - use asm parser to get the mnemonic. + return (std::string)Name.split(' ').first.split('\n').first.split('\t').first; +} + +void PPCInstrMappingEmitter::run(formatted_raw_ostream &OS) { + ArrayRef NumberedInstructions = + Target.getInstructionsByEnumValue(); + + json::OStream J(OS, 2); + J.array([&] { + for (const CodeGenInstruction *Inst : NumberedInstructions) { + std::string Mnemonic = parseMnemonic(Inst->AsmString); + if (!StringRef(Mnemonic).empty()) { + J.object([&] { + const Record *Rec = Inst->TheDef; + J.attribute("Opcode", Rec->getName()); + J.attribute("Mnemonic", Mnemonic); + J.attribute("OpNum", Inst->Operands.size() - Inst->Operands.NumDefs); + J.attribute("hasNoSchedulingInfo", + Rec->getValueAsBit("hasNoSchedulingInfo")); + J.attributeArray("Predicates", [&] { + ListInit *Preds = Rec->getValueAsListInit("Predicates"); + for (auto Pred : *Preds) + J.value(Pred->getAsString()); + }); + }); + } + } + }); +} + +} // end anonymous namespace + +namespace llvm { + +void EmitPPCInstrMapping(RecordKeeper &RK, raw_ostream &o) { + formatted_raw_ostream OS(o); + PPCInstrMappingEmitter(RK).run(OS); +} +} // namespace llvm diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp --- a/llvm/utils/TableGen/TableGen.cpp +++ b/llvm/utils/TableGen/TableGen.cpp @@ -57,6 +57,7 @@ GenAutomata, GenDirectivesEnumDecl, GenDirectivesEnumImpl, + GenPPCInstrMapping, }; namespace llvm { @@ -138,7 +139,10 @@ clEnumValN(GenDirectivesEnumDecl, "gen-directive-decl", "Generate directive related declaration code (header file)"), clEnumValN(GenDirectivesEnumImpl, "gen-directive-impl", - "Generate directive related implementation code"))); + "Generate directive related implementation code"), + clEnumValN(GenPPCInstrMapping, "gen-ppc-instr-mapping", + "Generate PowerPC instruction opcode to assembly mnemonics " + "mapping tables"))); cl::OptionCategory PrintEnumsCat("Options for -print-enums"); cl::opt Class("class", cl::desc("Print Enum list for this class"), @@ -272,6 +276,9 @@ case GenDirectivesEnumImpl: EmitDirectivesImpl(Records, OS); break; + case GenPPCInstrMapping: + EmitPPCInstrMapping(Records, OS); + break; } return false; diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h --- a/llvm/utils/TableGen/TableGenBackends.h +++ b/llvm/utils/TableGen/TableGenBackends.h @@ -93,6 +93,7 @@ void EmitAutomata(RecordKeeper &RK, raw_ostream &OS); void EmitDirectivesDecl(RecordKeeper &RK, raw_ostream &OS); void EmitDirectivesImpl(RecordKeeper &RK, raw_ostream &OS); +void EmitPPCInstrMapping(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace