Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/InstrInfoEmitter.cpp
35258 views
//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend is responsible for emitting a description of the target9// instruction set for the code generator.10//11//===----------------------------------------------------------------------===//1213#include "Basic/SequenceToOffsetTable.h"14#include "Common/CodeGenDAGPatterns.h"15#include "Common/CodeGenInstruction.h"16#include "Common/CodeGenSchedule.h"17#include "Common/CodeGenTarget.h"18#include "Common/PredicateExpander.h"19#include "Common/SubtargetFeatureInfo.h"20#include "Common/Types.h"21#include "TableGenBackends.h"22#include "llvm/ADT/ArrayRef.h"23#include "llvm/ADT/STLExtras.h"24#include "llvm/ADT/SmallVector.h"25#include "llvm/ADT/StringExtras.h"26#include "llvm/Support/Casting.h"27#include "llvm/Support/raw_ostream.h"28#include "llvm/TableGen/Error.h"29#include "llvm/TableGen/Record.h"30#include "llvm/TableGen/TableGenBackend.h"31#include <cassert>32#include <cstdint>33#include <iterator>34#include <map>35#include <string>36#include <utility>37#include <vector>3839using namespace llvm;4041cl::OptionCategory InstrInfoEmitterCat("Options for -gen-instr-info");42static cl::opt<bool> ExpandMIOperandInfo(43"instr-info-expand-mi-operand-info",44cl::desc("Expand operand's MIOperandInfo DAG into suboperands"),45cl::cat(InstrInfoEmitterCat), cl::init(true));4647namespace {4849class InstrInfoEmitter {50RecordKeeper &Records;51CodeGenDAGPatterns CDP;52const CodeGenSchedModels &SchedModels;5354public:55InstrInfoEmitter(RecordKeeper &R)56: Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {}5758// run - Output the instruction set description.59void run(raw_ostream &OS);6061private:62void emitEnums(raw_ostream &OS);6364typedef std::vector<std::string> OperandInfoTy;65typedef std::vector<OperandInfoTy> OperandInfoListTy;66typedef std::map<OperandInfoTy, unsigned> OperandInfoMapTy;6768/// The keys of this map are maps which have OpName enum values as their keys69/// and instruction operand indices as their values. The values of this map70/// are lists of instruction names.71typedef std::map<std::map<unsigned, unsigned>, std::vector<std::string>>72OpNameMapTy;73typedef std::map<std::string, unsigned>::iterator StrUintMapIter;7475/// Generate member functions in the target-specific GenInstrInfo class.76///77/// This method is used to custom expand TIIPredicate definitions.78/// See file llvm/Target/TargetInstPredicates.td for a description of what is79/// a TIIPredicate and how to use it.80void emitTIIHelperMethods(raw_ostream &OS, StringRef TargetName,81bool ExpandDefinition = true);8283/// Expand TIIPredicate definitions to functions that accept a const MCInst84/// reference.85void emitMCIIHelperMethods(raw_ostream &OS, StringRef TargetName);8687/// Write verifyInstructionPredicates methods.88void emitFeatureVerifier(raw_ostream &OS, const CodeGenTarget &Target);89void emitRecord(const CodeGenInstruction &Inst, unsigned Num,90Record *InstrInfo,91std::map<std::vector<Record *>, unsigned> &EL,92const OperandInfoMapTy &OperandInfo, raw_ostream &OS);93void emitOperandTypeMappings(94raw_ostream &OS, const CodeGenTarget &Target,95ArrayRef<const CodeGenInstruction *> NumberedInstructions);96void97initOperandMapData(ArrayRef<const CodeGenInstruction *> NumberedInstructions,98StringRef Namespace,99std::map<std::string, unsigned> &Operands,100OpNameMapTy &OperandMap);101void emitOperandNameMappings(102raw_ostream &OS, const CodeGenTarget &Target,103ArrayRef<const CodeGenInstruction *> NumberedInstructions);104105void emitLogicalOperandSizeMappings(106raw_ostream &OS, StringRef Namespace,107ArrayRef<const CodeGenInstruction *> NumberedInstructions);108void emitLogicalOperandTypeMappings(109raw_ostream &OS, StringRef Namespace,110ArrayRef<const CodeGenInstruction *> NumberedInstructions);111112// Operand information.113unsigned CollectOperandInfo(OperandInfoListTy &OperandInfoList,114OperandInfoMapTy &OperandInfoMap);115void EmitOperandInfo(raw_ostream &OS, OperandInfoListTy &OperandInfoList);116OperandInfoTy GetOperandInfo(const CodeGenInstruction &Inst);117};118119} // end anonymous namespace120121//===----------------------------------------------------------------------===//122// Operand Info Emission.123//===----------------------------------------------------------------------===//124125InstrInfoEmitter::OperandInfoTy126InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {127OperandInfoTy Result;128129for (auto &Op : Inst.Operands) {130// Handle aggregate operands and normal operands the same way by expanding131// either case into a list of operands for this op.132std::vector<CGIOperandList::OperandInfo> OperandList;133134// This might be a multiple operand thing. Targets like X86 have135// registers in their multi-operand operands. It may also be an anonymous136// operand, which has a single operand, but no declared class for the137// operand.138DagInit *MIOI = Op.MIOperandInfo;139140if (!MIOI || MIOI->getNumArgs() == 0) {141// Single, anonymous, operand.142OperandList.push_back(Op);143} else {144for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {145OperandList.push_back(Op);146147auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef();148OperandList.back().Rec = OpR;149}150}151152for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {153Record *OpR = OperandList[j].Rec;154std::string Res;155156if (OpR->isSubClassOf("RegisterOperand"))157OpR = OpR->getValueAsDef("RegClass");158if (OpR->isSubClassOf("RegisterClass"))159Res += getQualifiedName(OpR) + "RegClassID, ";160else if (OpR->isSubClassOf("PointerLikeRegClass"))161Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";162else163// -1 means the operand does not have a fixed register class.164Res += "-1, ";165166// Fill in applicable flags.167Res += "0";168169// Ptr value whose register class is resolved via callback.170if (OpR->isSubClassOf("PointerLikeRegClass"))171Res += "|(1<<MCOI::LookupPtrRegClass)";172173// Predicate operands. Check to see if the original unexpanded operand174// was of type PredicateOp.175if (Op.Rec->isSubClassOf("PredicateOp"))176Res += "|(1<<MCOI::Predicate)";177178// Optional def operands. Check to see if the original unexpanded operand179// was of type OptionalDefOperand.180if (Op.Rec->isSubClassOf("OptionalDefOperand"))181Res += "|(1<<MCOI::OptionalDef)";182183// Branch target operands. Check to see if the original unexpanded184// operand was of type BranchTargetOperand.185if (Op.Rec->isSubClassOf("BranchTargetOperand"))186Res += "|(1<<MCOI::BranchTarget)";187188// Fill in operand type.189Res += ", ";190assert(!Op.OperandType.empty() && "Invalid operand type.");191Res += Op.OperandType;192193// Fill in constraint info.194Res += ", ";195196const CGIOperandList::ConstraintInfo &Constraint = Op.Constraints[j];197if (Constraint.isNone())198Res += "0";199else if (Constraint.isEarlyClobber())200Res += "MCOI_EARLY_CLOBBER";201else {202assert(Constraint.isTied());203Res += "MCOI_TIED_TO(" + utostr(Constraint.getTiedOperand()) + ")";204}205206Result.push_back(Res);207}208}209210return Result;211}212213unsigned214InstrInfoEmitter::CollectOperandInfo(OperandInfoListTy &OperandInfoList,215OperandInfoMapTy &OperandInfoMap) {216const CodeGenTarget &Target = CDP.getTargetInfo();217unsigned Offset = 0;218for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {219OperandInfoTy OperandInfo = GetOperandInfo(*Inst);220if (OperandInfoMap.insert({OperandInfo, Offset}).second) {221OperandInfoList.push_back(OperandInfo);222Offset += OperandInfo.size();223}224}225return Offset;226}227228void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,229OperandInfoListTy &OperandInfoList) {230unsigned Offset = 0;231for (auto &OperandInfo : OperandInfoList) {232OS << " /* " << Offset << " */";233for (auto &Info : OperandInfo)234OS << " { " << Info << " },";235OS << '\n';236Offset += OperandInfo.size();237}238}239240/// Initialize data structures for generating operand name mappings.241///242/// \param Operands [out] A map used to generate the OpName enum with operand243/// names as its keys and operand enum values as its values.244/// \param OperandMap [out] A map for representing the operand name mappings for245/// each instructions. This is used to generate the OperandMap table as246/// well as the getNamedOperandIdx() function.247void InstrInfoEmitter::initOperandMapData(248ArrayRef<const CodeGenInstruction *> NumberedInstructions,249StringRef Namespace, std::map<std::string, unsigned> &Operands,250OpNameMapTy &OperandMap) {251unsigned NumOperands = 0;252for (const CodeGenInstruction *Inst : NumberedInstructions) {253if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))254continue;255std::map<unsigned, unsigned> OpList;256for (const auto &Info : Inst->Operands) {257StrUintMapIter I = Operands.find(Info.Name);258259if (I == Operands.end()) {260I = Operands.insert(Operands.begin(), std::pair<std::string, unsigned>(261Info.Name, NumOperands++));262}263OpList[I->second] = Info.MIOperandNo;264}265OperandMap[OpList].push_back(Namespace.str() +266"::" + Inst->TheDef->getName().str());267}268}269270/// Generate a table and function for looking up the indices of operands by271/// name.272///273/// This code generates:274/// - An enum in the llvm::TargetNamespace::OpName namespace, with one entry275/// for each operand name.276/// - A 2-dimensional table called OperandMap for mapping OpName enum values to277/// operand indices.278/// - A function called getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)279/// for looking up the operand index for an instruction, given a value from280/// OpName enum281void InstrInfoEmitter::emitOperandNameMappings(282raw_ostream &OS, const CodeGenTarget &Target,283ArrayRef<const CodeGenInstruction *> NumberedInstructions) {284StringRef Namespace = Target.getInstNamespace();285std::string OpNameNS = "OpName";286// Map of operand names to their enumeration value. This will be used to287// generate the OpName enum.288std::map<std::string, unsigned> Operands;289OpNameMapTy OperandMap;290291initOperandMapData(NumberedInstructions, Namespace, Operands, OperandMap);292293OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n";294OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n";295OS << "namespace llvm {\n";296OS << "namespace " << Namespace << " {\n";297OS << "namespace " << OpNameNS << " {\n";298OS << "enum {\n";299for (const auto &Op : Operands)300OS << " " << Op.first << " = " << Op.second << ",\n";301302OS << " OPERAND_LAST";303OS << "\n};\n";304OS << "} // end namespace OpName\n";305OS << "} // end namespace " << Namespace << "\n";306OS << "} // end namespace llvm\n";307OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n";308309OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n";310OS << "#undef GET_INSTRINFO_NAMED_OPS\n";311OS << "namespace llvm {\n";312OS << "namespace " << Namespace << " {\n";313OS << "LLVM_READONLY\n";314OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n";315if (!Operands.empty()) {316OS << " static const int16_t OperandMap [][" << Operands.size()317<< "] = {\n";318for (const auto &Entry : OperandMap) {319const std::map<unsigned, unsigned> &OpList = Entry.first;320OS << "{";321322// Emit a row of the OperandMap table323for (unsigned i = 0, e = Operands.size(); i != e; ++i)324OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", ";325326OS << "},\n";327}328OS << "};\n";329330OS << " switch(Opcode) {\n";331unsigned TableIndex = 0;332for (const auto &Entry : OperandMap) {333for (const std::string &Name : Entry.second)334OS << " case " << Name << ":\n";335336OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n";337}338OS << " default: return -1;\n";339OS << " }\n";340} else {341// There are no operands, so no need to emit anything342OS << " return -1;\n";343}344OS << "}\n";345OS << "} // end namespace " << Namespace << "\n";346OS << "} // end namespace llvm\n";347OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n";348}349350/// Generate an enum for all the operand types for this target, under the351/// llvm::TargetNamespace::OpTypes namespace.352/// Operand types are all definitions derived of the Operand Target.td class.353void InstrInfoEmitter::emitOperandTypeMappings(354raw_ostream &OS, const CodeGenTarget &Target,355ArrayRef<const CodeGenInstruction *> NumberedInstructions) {356357StringRef Namespace = Target.getInstNamespace();358std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand");359std::vector<Record *> RegisterOperands =360Records.getAllDerivedDefinitions("RegisterOperand");361std::vector<Record *> RegisterClasses =362Records.getAllDerivedDefinitions("RegisterClass");363364OS << "#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";365OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";366OS << "namespace llvm {\n";367OS << "namespace " << Namespace << " {\n";368OS << "namespace OpTypes {\n";369OS << "enum OperandType {\n";370371unsigned EnumVal = 0;372for (const std::vector<Record *> *RecordsToAdd :373{&Operands, &RegisterOperands, &RegisterClasses}) {374for (const Record *Op : *RecordsToAdd) {375if (!Op->isAnonymous())376OS << " " << Op->getName() << " = " << EnumVal << ",\n";377++EnumVal;378}379}380381OS << " OPERAND_TYPE_LIST_END"382<< "\n};\n";383OS << "} // end namespace OpTypes\n";384OS << "} // end namespace " << Namespace << "\n";385OS << "} // end namespace llvm\n";386OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";387388OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n";389OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n";390OS << "namespace llvm {\n";391OS << "namespace " << Namespace << " {\n";392OS << "LLVM_READONLY\n";393OS << "static int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n";394auto getInstrName = [&](int I) -> StringRef {395return NumberedInstructions[I]->TheDef->getName();396};397// TODO: Factor out duplicate operand lists to compress the tables.398if (!NumberedInstructions.empty()) {399std::vector<int> OperandOffsets;400std::vector<Record *> OperandRecords;401int CurrentOffset = 0;402for (const CodeGenInstruction *Inst : NumberedInstructions) {403OperandOffsets.push_back(CurrentOffset);404for (const auto &Op : Inst->Operands) {405const DagInit *MIOI = Op.MIOperandInfo;406if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) {407// Single, anonymous, operand.408OperandRecords.push_back(Op.Rec);409++CurrentOffset;410} else {411for (Init *Arg : MIOI->getArgs()) {412OperandRecords.push_back(cast<DefInit>(Arg)->getDef());413++CurrentOffset;414}415}416}417}418419// Emit the table of offsets (indexes) into the operand type table.420// Size the unsigned integer offset to save space.421assert(OperandRecords.size() <= UINT32_MAX &&422"Too many operands for offset table");423OS << " static const " << getMinimalTypeForRange(OperandRecords.size());424OS << " Offsets[] = {\n";425for (int I = 0, E = OperandOffsets.size(); I != E; ++I) {426OS << " /* " << getInstrName(I) << " */\n";427OS << " " << OperandOffsets[I] << ",\n";428}429OS << " };\n";430431// Add an entry for the end so that we don't need to special case it below.432OperandOffsets.push_back(OperandRecords.size());433434// Emit the actual operand types in a flat table.435// Size the signed integer operand type to save space.436assert(EnumVal <= INT16_MAX &&437"Too many operand types for operand types table");438OS << "\n using namespace OpTypes;\n";439OS << " static";440OS << ((EnumVal <= INT8_MAX) ? " const int8_t" : " const int16_t");441OS << " OpcodeOperandTypes[] = {\n ";442for (int I = 0, E = OperandRecords.size(), CurOffset = 0; I != E; ++I) {443// We print each Opcode's operands in its own row.444if (I == OperandOffsets[CurOffset]) {445OS << "\n /* " << getInstrName(CurOffset) << " */\n ";446while (OperandOffsets[++CurOffset] == I)447OS << "/* " << getInstrName(CurOffset) << " */\n ";448}449Record *OpR = OperandRecords[I];450if ((OpR->isSubClassOf("Operand") ||451OpR->isSubClassOf("RegisterOperand") ||452OpR->isSubClassOf("RegisterClass")) &&453!OpR->isAnonymous())454OS << OpR->getName();455else456OS << -1;457OS << ", ";458}459OS << "\n };\n";460461OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n";462} else {463OS << " llvm_unreachable(\"No instructions defined\");\n";464}465OS << "}\n";466OS << "} // end namespace " << Namespace << "\n";467OS << "} // end namespace llvm\n";468OS << "#endif // GET_INSTRINFO_OPERAND_TYPE\n\n";469470OS << "#ifdef GET_INSTRINFO_MEM_OPERAND_SIZE\n";471OS << "#undef GET_INSTRINFO_MEM_OPERAND_SIZE\n";472OS << "namespace llvm {\n";473OS << "namespace " << Namespace << " {\n";474OS << "LLVM_READONLY\n";475OS << "static int getMemOperandSize(int OpType) {\n";476OS << " switch (OpType) {\n";477std::map<int, SmallVector<StringRef, 0>> SizeToOperandName;478for (const Record *Op : Operands) {479if (!Op->isSubClassOf("X86MemOperand"))480continue;481if (int Size = Op->getValueAsInt("Size"))482SizeToOperandName[Size].push_back(Op->getName());483}484OS << " default: return 0;\n";485for (const auto &KV : SizeToOperandName) {486for (const StringRef &OperandName : KV.second)487OS << " case OpTypes::" << OperandName << ":\n";488OS << " return " << KV.first << ";\n\n";489}490OS << " }\n}\n";491OS << "} // end namespace " << Namespace << "\n";492OS << "} // end namespace llvm\n";493OS << "#endif // GET_INSTRINFO_MEM_OPERAND_SIZE\n\n";494}495496void InstrInfoEmitter::emitLogicalOperandSizeMappings(497raw_ostream &OS, StringRef Namespace,498ArrayRef<const CodeGenInstruction *> NumberedInstructions) {499std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap;500501std::map<unsigned, std::vector<std::string>> InstMap;502503size_t LogicalOpListSize = 0U;504std::vector<unsigned> LogicalOpList;505for (const auto *Inst : NumberedInstructions) {506if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))507continue;508509LogicalOpList.clear();510llvm::transform(Inst->Operands, std::back_inserter(LogicalOpList),511[](const CGIOperandList::OperandInfo &Op) -> unsigned {512auto *MIOI = Op.MIOperandInfo;513if (!MIOI || MIOI->getNumArgs() == 0)514return 1;515return MIOI->getNumArgs();516});517LogicalOpListSize = std::max(LogicalOpList.size(), LogicalOpListSize);518519auto I =520LogicalOpSizeMap.insert({LogicalOpList, LogicalOpSizeMap.size()}).first;521InstMap[I->second].push_back(522(Namespace + "::" + Inst->TheDef->getName()).str());523}524525OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n";526OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n";527OS << "namespace llvm {\n";528OS << "namespace " << Namespace << " {\n";529OS << "LLVM_READONLY static unsigned\n";530OS << "getLogicalOperandSize(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";531if (!InstMap.empty()) {532std::vector<const std::vector<unsigned> *> LogicalOpSizeList(533LogicalOpSizeMap.size());534for (auto &P : LogicalOpSizeMap) {535LogicalOpSizeList[P.second] = &P.first;536}537OS << " static const unsigned SizeMap[][" << LogicalOpListSize538<< "] = {\n";539for (auto &R : LogicalOpSizeList) {540const auto &Row = *R;541OS << " {";542int i;543for (i = 0; i < static_cast<int>(Row.size()); ++i) {544OS << Row[i] << ", ";545}546for (; i < static_cast<int>(LogicalOpListSize); ++i) {547OS << "0, ";548}549OS << "}, ";550OS << "\n";551}552OS << " };\n";553554OS << " switch (Opcode) {\n";555OS << " default: return LogicalOpIdx;\n";556for (auto &P : InstMap) {557auto OpMapIdx = P.first;558const auto &Insts = P.second;559for (const auto &Inst : Insts) {560OS << " case " << Inst << ":\n";561}562OS << " return SizeMap[" << OpMapIdx << "][LogicalOpIdx];\n";563}564OS << " }\n";565} else {566OS << " return LogicalOpIdx;\n";567}568OS << "}\n";569570OS << "LLVM_READONLY static inline unsigned\n";571OS << "getLogicalOperandIdx(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";572OS << " auto S = 0U;\n";573OS << " for (auto i = 0U; i < LogicalOpIdx; ++i)\n";574OS << " S += getLogicalOperandSize(Opcode, i);\n";575OS << " return S;\n";576OS << "}\n";577578OS << "} // end namespace " << Namespace << "\n";579OS << "} // end namespace llvm\n";580OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n\n";581}582583void InstrInfoEmitter::emitLogicalOperandTypeMappings(584raw_ostream &OS, StringRef Namespace,585ArrayRef<const CodeGenInstruction *> NumberedInstructions) {586std::map<std::vector<std::string>, unsigned> LogicalOpTypeMap;587588std::map<unsigned, std::vector<std::string>> InstMap;589590size_t OpTypeListSize = 0U;591std::vector<std::string> LogicalOpTypeList;592for (const auto *Inst : NumberedInstructions) {593if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))594continue;595596LogicalOpTypeList.clear();597for (const auto &Op : Inst->Operands) {598auto *OpR = Op.Rec;599if ((OpR->isSubClassOf("Operand") ||600OpR->isSubClassOf("RegisterOperand") ||601OpR->isSubClassOf("RegisterClass")) &&602!OpR->isAnonymous()) {603LogicalOpTypeList.push_back(604(Namespace + "::OpTypes::" + Op.Rec->getName()).str());605} else {606LogicalOpTypeList.push_back("-1");607}608}609OpTypeListSize = std::max(LogicalOpTypeList.size(), OpTypeListSize);610611auto I =612LogicalOpTypeMap.insert({LogicalOpTypeList, LogicalOpTypeMap.size()})613.first;614InstMap[I->second].push_back(615(Namespace + "::" + Inst->TheDef->getName()).str());616}617618OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n";619OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n";620OS << "namespace llvm {\n";621OS << "namespace " << Namespace << " {\n";622OS << "LLVM_READONLY static int\n";623OS << "getLogicalOperandType(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";624if (!InstMap.empty()) {625std::vector<const std::vector<std::string> *> LogicalOpTypeList(626LogicalOpTypeMap.size());627for (auto &P : LogicalOpTypeMap) {628LogicalOpTypeList[P.second] = &P.first;629}630OS << " static const int TypeMap[][" << OpTypeListSize << "] = {\n";631for (int r = 0, rs = LogicalOpTypeList.size(); r < rs; ++r) {632const auto &Row = *LogicalOpTypeList[r];633OS << " {";634int i, s = Row.size();635for (i = 0; i < s; ++i) {636if (i > 0)637OS << ", ";638OS << Row[i];639}640for (; i < static_cast<int>(OpTypeListSize); ++i) {641if (i > 0)642OS << ", ";643OS << "-1";644}645OS << "}";646if (r != rs - 1)647OS << ",";648OS << "\n";649}650OS << " };\n";651652OS << " switch (Opcode) {\n";653OS << " default: return -1;\n";654for (auto &P : InstMap) {655auto OpMapIdx = P.first;656const auto &Insts = P.second;657for (const auto &Inst : Insts) {658OS << " case " << Inst << ":\n";659}660OS << " return TypeMap[" << OpMapIdx << "][LogicalOpIdx];\n";661}662OS << " }\n";663} else {664OS << " return -1;\n";665}666OS << "}\n";667OS << "} // end namespace " << Namespace << "\n";668OS << "} // end namespace llvm\n";669OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n\n";670}671672void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,673StringRef TargetName) {674RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate");675676OS << "#ifdef GET_INSTRINFO_MC_HELPER_DECLS\n";677OS << "#undef GET_INSTRINFO_MC_HELPER_DECLS\n\n";678679OS << "namespace llvm {\n";680OS << "class MCInst;\n";681OS << "class FeatureBitset;\n\n";682683OS << "namespace " << TargetName << "_MC {\n\n";684685for (const Record *Rec : TIIPredicates) {686OS << "bool " << Rec->getValueAsString("FunctionName")687<< "(const MCInst &MI);\n";688}689690OS << "void verifyInstructionPredicates(unsigned Opcode, const FeatureBitset "691"&Features);\n";692693OS << "\n} // end namespace " << TargetName << "_MC\n";694OS << "} // end namespace llvm\n\n";695696OS << "#endif // GET_INSTRINFO_MC_HELPER_DECLS\n\n";697698OS << "#ifdef GET_INSTRINFO_MC_HELPERS\n";699OS << "#undef GET_INSTRINFO_MC_HELPERS\n\n";700701OS << "namespace llvm {\n";702OS << "namespace " << TargetName << "_MC {\n\n";703704PredicateExpander PE(TargetName);705PE.setExpandForMC(true);706707for (const Record *Rec : TIIPredicates) {708OS << "bool " << Rec->getValueAsString("FunctionName");709OS << "(const MCInst &MI) {\n";710711OS.indent(PE.getIndentLevel() * 2);712PE.expandStatement(OS, Rec->getValueAsDef("Body"));713OS << "\n}\n\n";714}715716OS << "} // end namespace " << TargetName << "_MC\n";717OS << "} // end namespace llvm\n\n";718719OS << "#endif // GET_GENISTRINFO_MC_HELPERS\n\n";720}721722static std::string723getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {724std::string Name = "CEFBS";725for (const auto &Feature : FeatureBitset)726Name += ("_" + Feature->getName()).str();727return Name;728}729730void InstrInfoEmitter::emitFeatureVerifier(raw_ostream &OS,731const CodeGenTarget &Target) {732const auto &All = SubtargetFeatureInfo::getAll(Records);733std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;734SubtargetFeatures.insert(All.begin(), All.end());735736OS << "#if (defined(ENABLE_INSTR_PREDICATE_VERIFIER) && !defined(NDEBUG)) "737<< "||\\\n"738<< " defined(GET_AVAILABLE_OPCODE_CHECKER)\n"739<< "#define GET_COMPUTE_FEATURES\n"740<< "#endif\n";741OS << "#ifdef GET_COMPUTE_FEATURES\n"742<< "#undef GET_COMPUTE_FEATURES\n"743<< "namespace llvm {\n"744<< "namespace " << Target.getName() << "_MC {\n\n";745746// Emit the subtarget feature enumeration.747SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,748OS);749// Emit the available features compute function.750OS << "inline ";751SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(752Target.getName(), "", "computeAvailableFeatures", SubtargetFeatures, OS);753754std::vector<std::vector<Record *>> FeatureBitsets;755for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {756FeatureBitsets.emplace_back();757for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {758const auto &I = SubtargetFeatures.find(Predicate);759if (I != SubtargetFeatures.end())760FeatureBitsets.back().push_back(I->second.TheDef);761}762}763764llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,765const std::vector<Record *> &B) {766if (A.size() < B.size())767return true;768if (A.size() > B.size())769return false;770for (auto Pair : zip(A, B)) {771if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())772return true;773if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())774return false;775}776return false;777});778FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end());779OS << "inline FeatureBitset computeRequiredFeatures(unsigned Opcode) {\n"780<< " enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"781<< " CEFBS_None,\n";782for (const auto &FeatureBitset : FeatureBitsets) {783if (FeatureBitset.empty())784continue;785OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";786}787OS << " };\n\n"788<< " static constexpr FeatureBitset FeatureBitsets[] = {\n"789<< " {}, // CEFBS_None\n";790for (const auto &FeatureBitset : FeatureBitsets) {791if (FeatureBitset.empty())792continue;793OS << " {";794for (const auto &Feature : FeatureBitset) {795const auto &I = SubtargetFeatures.find(Feature);796assert(I != SubtargetFeatures.end() && "Didn't import predicate?");797OS << I->second.getEnumBitName() << ", ";798}799OS << "},\n";800}801OS << " };\n"802<< " static constexpr " << getMinimalTypeForRange(FeatureBitsets.size())803<< " RequiredFeaturesRefs[] = {\n";804unsigned InstIdx = 0;805for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {806OS << " CEFBS";807unsigned NumPredicates = 0;808for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {809const auto &I = SubtargetFeatures.find(Predicate);810if (I != SubtargetFeatures.end()) {811OS << '_' << I->second.TheDef->getName();812NumPredicates++;813}814}815if (!NumPredicates)816OS << "_None";817OS << ", // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";818InstIdx++;819}820OS << " };\n\n"821<< " assert(Opcode < " << InstIdx << ");\n"822<< " return FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n"823<< "}\n\n";824825OS << "} // end namespace " << Target.getName() << "_MC\n"826<< "} // end namespace llvm\n"827<< "#endif // GET_COMPUTE_FEATURES\n\n";828829OS << "#ifdef GET_AVAILABLE_OPCODE_CHECKER\n"830<< "#undef GET_AVAILABLE_OPCODE_CHECKER\n"831<< "namespace llvm {\n"832<< "namespace " << Target.getName() << "_MC {\n";833OS << "bool isOpcodeAvailable("834<< "unsigned Opcode, const FeatureBitset &Features) {\n"835<< " FeatureBitset AvailableFeatures = "836<< "computeAvailableFeatures(Features);\n"837<< " FeatureBitset RequiredFeatures = "838<< "computeRequiredFeatures(Opcode);\n"839<< " FeatureBitset MissingFeatures =\n"840<< " (AvailableFeatures & RequiredFeatures) ^\n"841<< " RequiredFeatures;\n"842<< " return !MissingFeatures.any();\n"843<< "}\n";844OS << "} // end namespace " << Target.getName() << "_MC\n"845<< "} // end namespace llvm\n"846<< "#endif // GET_AVAILABLE_OPCODE_CHECKER\n\n";847848OS << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n"849<< "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n"850<< "#include <sstream>\n\n";851852OS << "namespace llvm {\n";853OS << "namespace " << Target.getName() << "_MC {\n\n";854855// Emit the name table for error messages.856OS << "#ifndef NDEBUG\n";857SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS);858OS << "#endif // NDEBUG\n\n";859860// Emit the predicate verifier.861OS << "void verifyInstructionPredicates(\n"862<< " unsigned Opcode, const FeatureBitset &Features) {\n"863<< "#ifndef NDEBUG\n";864OS << " FeatureBitset AvailableFeatures = "865"computeAvailableFeatures(Features);\n";866OS << " FeatureBitset RequiredFeatures = "867<< "computeRequiredFeatures(Opcode);\n";868OS << " FeatureBitset MissingFeatures =\n"869<< " (AvailableFeatures & RequiredFeatures) ^\n"870<< " RequiredFeatures;\n"871<< " if (MissingFeatures.any()) {\n"872<< " std::ostringstream Msg;\n"873<< " Msg << \"Attempting to emit \" << &" << Target.getName()874<< "InstrNameData[" << Target.getName() << "InstrNameIndices[Opcode]]\n"875<< " << \" instruction but the \";\n"876<< " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n"877<< " if (MissingFeatures.test(i))\n"878<< " Msg << SubtargetFeatureNames[i] << \" \";\n"879<< " Msg << \"predicate(s) are not met\";\n"880<< " report_fatal_error(Msg.str().c_str());\n"881<< " }\n"882<< "#endif // NDEBUG\n";883OS << "}\n";884OS << "} // end namespace " << Target.getName() << "_MC\n";885OS << "} // end namespace llvm\n";886OS << "#endif // ENABLE_INSTR_PREDICATE_VERIFIER\n\n";887}888889void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS,890StringRef TargetName,891bool ExpandDefinition) {892RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate");893if (TIIPredicates.empty())894return;895896PredicateExpander PE(TargetName);897PE.setExpandForMC(false);898899for (const Record *Rec : TIIPredicates) {900OS << (ExpandDefinition ? "" : "static ") << "bool ";901if (ExpandDefinition)902OS << TargetName << "InstrInfo::";903OS << Rec->getValueAsString("FunctionName");904OS << "(const MachineInstr &MI)";905if (!ExpandDefinition) {906OS << ";\n";907continue;908}909910OS << " {\n";911OS.indent(PE.getIndentLevel() * 2);912PE.expandStatement(OS, Rec->getValueAsDef("Body"));913OS << "\n}\n\n";914}915}916917//===----------------------------------------------------------------------===//918// Main Output.919//===----------------------------------------------------------------------===//920921// run - Emit the main instruction description records for the target...922void InstrInfoEmitter::run(raw_ostream &OS) {923emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);924emitEnums(OS);925926CodeGenTarget &Target = CDP.getTargetInfo();927const std::string &TargetName = std::string(Target.getName());928Record *InstrInfo = Target.getInstructionSet();929930// Collect all of the operand info records.931Records.startTimer("Collect operand info");932OperandInfoListTy OperandInfoList;933OperandInfoMapTy OperandInfoMap;934unsigned OperandInfoSize =935CollectOperandInfo(OperandInfoList, OperandInfoMap);936937// Collect all of the instruction's implicit uses and defs.938Records.startTimer("Collect uses/defs");939std::map<std::vector<Record *>, unsigned> EmittedLists;940std::vector<std::vector<Record *>> ImplicitLists;941unsigned ImplicitListSize = 0;942for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {943std::vector<Record *> ImplicitOps = II->ImplicitUses;944llvm::append_range(ImplicitOps, II->ImplicitDefs);945if (EmittedLists.insert({ImplicitOps, ImplicitListSize}).second) {946ImplicitLists.push_back(ImplicitOps);947ImplicitListSize += ImplicitOps.size();948}949}950951ArrayRef<const CodeGenInstruction *> NumberedInstructions =952Target.getInstructionsByEnumValue();953OS << "#if defined(GET_INSTRINFO_MC_DESC) || "954"defined(GET_INSTRINFO_CTOR_DTOR)\n";955OS << "namespace llvm {\n\n";956957OS << "struct " << TargetName << "InstrTable {\n";958OS << " MCInstrDesc Insts[" << NumberedInstructions.size() << "];\n";959OS << " static_assert(alignof(MCInstrDesc) >= alignof(MCOperandInfo), "960"\"Unwanted padding between Insts and OperandInfo\");\n";961OS << " MCOperandInfo OperandInfo[" << OperandInfoSize << "];\n";962OS << " static_assert(alignof(MCOperandInfo) >= alignof(MCPhysReg), "963"\"Unwanted padding between OperandInfo and ImplicitOps\");\n";964OS << " MCPhysReg ImplicitOps[" << std::max(ImplicitListSize, 1U) << "];\n";965OS << "};\n\n";966967OS << "} // end namespace llvm\n";968OS << "#endif // defined(GET_INSTRINFO_MC_DESC) || "969"defined(GET_INSTRINFO_CTOR_DTOR)\n\n";970971OS << "#ifdef GET_INSTRINFO_MC_DESC\n";972OS << "#undef GET_INSTRINFO_MC_DESC\n";973OS << "namespace llvm {\n\n";974975// Emit all of the MCInstrDesc records in reverse ENUM ordering.976Records.startTimer("Emit InstrDesc records");977OS << "static_assert(sizeof(MCOperandInfo) % sizeof(MCPhysReg) == 0);\n";978OS << "static constexpr unsigned " << TargetName << "ImpOpBase = sizeof "979<< TargetName << "InstrTable::OperandInfo / (sizeof(MCPhysReg));\n\n";980981OS << "extern const " << TargetName << "InstrTable " << TargetName982<< "Descs = {\n {\n";983SequenceToOffsetTable<std::string> InstrNames;984unsigned Num = NumberedInstructions.size();985for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) {986// Keep a list of the instruction names.987InstrNames.add(std::string(Inst->TheDef->getName()));988// Emit the record into the table.989emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoMap, OS);990}991992OS << " }, {\n";993994// Emit all of the operand info records.995Records.startTimer("Emit operand info");996EmitOperandInfo(OS, OperandInfoList);997998OS << " }, {\n";9991000// Emit all of the instruction's implicit uses and defs.1001Records.startTimer("Emit uses/defs");1002for (auto &List : ImplicitLists) {1003OS << " /* " << EmittedLists[List] << " */";1004for (auto &Reg : List)1005OS << ' ' << getQualifiedName(Reg) << ',';1006OS << '\n';1007}10081009OS << " }\n};\n\n";10101011// Emit the array of instruction names.1012Records.startTimer("Emit instruction names");1013InstrNames.layout();1014InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName +1015"InstrNameData[]");10161017OS << "extern const unsigned " << TargetName << "InstrNameIndices[] = {";1018Num = 0;1019for (const CodeGenInstruction *Inst : NumberedInstructions) {1020// Newline every eight entries.1021if (Num % 8 == 0)1022OS << "\n ";1023OS << InstrNames.get(std::string(Inst->TheDef->getName())) << "U, ";1024++Num;1025}1026OS << "\n};\n\n";10271028bool HasDeprecationFeatures =1029llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {1030return !Inst->HasComplexDeprecationPredicate &&1031!Inst->DeprecatedReason.empty();1032});1033if (HasDeprecationFeatures) {1034OS << "extern const uint8_t " << TargetName1035<< "InstrDeprecationFeatures[] = {";1036Num = 0;1037for (const CodeGenInstruction *Inst : NumberedInstructions) {1038if (Num % 8 == 0)1039OS << "\n ";1040if (!Inst->HasComplexDeprecationPredicate &&1041!Inst->DeprecatedReason.empty())1042OS << Target.getInstNamespace() << "::" << Inst->DeprecatedReason1043<< ", ";1044else1045OS << "uint8_t(-1), ";1046++Num;1047}1048OS << "\n};\n\n";1049}10501051bool HasComplexDeprecationInfos =1052llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {1053return Inst->HasComplexDeprecationPredicate;1054});1055if (HasComplexDeprecationInfos) {1056OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName1057<< "InstrComplexDeprecationInfos[] = {";1058Num = 0;1059for (const CodeGenInstruction *Inst : NumberedInstructions) {1060if (Num % 8 == 0)1061OS << "\n ";1062if (Inst->HasComplexDeprecationPredicate)1063// Emit a function pointer to the complex predicate method.1064OS << "&get" << Inst->DeprecatedReason << "DeprecationInfo, ";1065else1066OS << "nullptr, ";1067++Num;1068}1069OS << "\n};\n\n";1070}10711072// MCInstrInfo initialization routine.1073Records.startTimer("Emit initialization routine");1074OS << "static inline void Init" << TargetName1075<< "MCInstrInfo(MCInstrInfo *II) {\n";1076OS << " II->InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName1077<< "InstrNameIndices, " << TargetName << "InstrNameData, ";1078if (HasDeprecationFeatures)1079OS << TargetName << "InstrDeprecationFeatures, ";1080else1081OS << "nullptr, ";1082if (HasComplexDeprecationInfos)1083OS << TargetName << "InstrComplexDeprecationInfos, ";1084else1085OS << "nullptr, ";1086OS << NumberedInstructions.size() << ");\n}\n\n";10871088OS << "} // end namespace llvm\n";10891090OS << "#endif // GET_INSTRINFO_MC_DESC\n\n";10911092// Create a TargetInstrInfo subclass to hide the MC layer initialization.1093OS << "#ifdef GET_INSTRINFO_HEADER\n";1094OS << "#undef GET_INSTRINFO_HEADER\n";10951096std::string ClassName = TargetName + "GenInstrInfo";1097OS << "namespace llvm {\n";1098OS << "struct " << ClassName << " : public TargetInstrInfo {\n"1099<< " explicit " << ClassName1100<< "(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u, "1101"unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u);\n"1102<< " ~" << ClassName << "() override = default;\n";11031104OS << "\n};\n} // end namespace llvm\n";11051106OS << "#endif // GET_INSTRINFO_HEADER\n\n";11071108OS << "#ifdef GET_INSTRINFO_HELPER_DECLS\n";1109OS << "#undef GET_INSTRINFO_HELPER_DECLS\n\n";1110emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ false);1111OS << "\n";1112OS << "#endif // GET_INSTRINFO_HELPER_DECLS\n\n";11131114OS << "#ifdef GET_INSTRINFO_HELPERS\n";1115OS << "#undef GET_INSTRINFO_HELPERS\n\n";1116emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ true);1117OS << "#endif // GET_INSTRINFO_HELPERS\n\n";11181119OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n";1120OS << "#undef GET_INSTRINFO_CTOR_DTOR\n";11211122OS << "namespace llvm {\n";1123OS << "extern const " << TargetName << "InstrTable " << TargetName1124<< "Descs;\n";1125OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";1126OS << "extern const char " << TargetName << "InstrNameData[];\n";1127if (HasDeprecationFeatures)1128OS << "extern const uint8_t " << TargetName1129<< "InstrDeprecationFeatures[];\n";1130if (HasComplexDeprecationInfos)1131OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName1132<< "InstrComplexDeprecationInfos[];\n";1133OS << ClassName << "::" << ClassName1134<< "(unsigned CFSetupOpcode, unsigned CFDestroyOpcode, unsigned "1135"CatchRetOpcode, unsigned ReturnOpcode)\n"1136<< " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, "1137"ReturnOpcode) {\n"1138<< " InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName1139<< "InstrNameIndices, " << TargetName << "InstrNameData, ";1140if (HasDeprecationFeatures)1141OS << TargetName << "InstrDeprecationFeatures, ";1142else1143OS << "nullptr, ";1144if (HasComplexDeprecationInfos)1145OS << TargetName << "InstrComplexDeprecationInfos, ";1146else1147OS << "nullptr, ";1148OS << NumberedInstructions.size() << ");\n}\n";1149OS << "} // end namespace llvm\n";11501151OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";11521153Records.startTimer("Emit operand name mappings");1154emitOperandNameMappings(OS, Target, NumberedInstructions);11551156Records.startTimer("Emit operand type mappings");1157emitOperandTypeMappings(OS, Target, NumberedInstructions);11581159Records.startTimer("Emit logical operand size mappings");1160emitLogicalOperandSizeMappings(OS, TargetName, NumberedInstructions);11611162Records.startTimer("Emit logical operand type mappings");1163emitLogicalOperandTypeMappings(OS, TargetName, NumberedInstructions);11641165Records.startTimer("Emit helper methods");1166emitMCIIHelperMethods(OS, TargetName);11671168Records.startTimer("Emit verifier methods");1169emitFeatureVerifier(OS, Target);1170}11711172void InstrInfoEmitter::emitRecord(1173const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo,1174std::map<std::vector<Record *>, unsigned> &EmittedLists,1175const OperandInfoMapTy &OperandInfoMap, raw_ostream &OS) {1176int MinOperands = 0;1177if (!Inst.Operands.empty())1178// Each logical operand can be multiple MI operands.1179MinOperands =1180Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands;1181// Even the logical output operand may be multiple MI operands.1182int DefOperands = 0;1183if (Inst.Operands.NumDefs) {1184auto &Opnd = Inst.Operands[Inst.Operands.NumDefs - 1];1185DefOperands = Opnd.MIOperandNo + Opnd.MINumOperands;1186}11871188OS << " { ";1189OS << Num << ",\t" << MinOperands << ",\t" << DefOperands << ",\t"1190<< Inst.TheDef->getValueAsInt("Size") << ",\t"1191<< SchedModels.getSchedClassIdx(Inst) << ",\t";11921193CodeGenTarget &Target = CDP.getTargetInfo();11941195// Emit the implicit use/def list...1196OS << Inst.ImplicitUses.size() << ",\t" << Inst.ImplicitDefs.size() << ",\t";1197std::vector<Record *> ImplicitOps = Inst.ImplicitUses;1198llvm::append_range(ImplicitOps, Inst.ImplicitDefs);1199OS << Target.getName() << "ImpOpBase + " << EmittedLists[ImplicitOps]1200<< ",\t";12011202// Emit the operand info offset.1203OperandInfoTy OperandInfo = GetOperandInfo(Inst);1204OS << OperandInfoMap.find(OperandInfo)->second << ",\t0";12051206// Emit all of the target independent flags...1207if (Inst.isPreISelOpcode)1208OS << "|(1ULL<<MCID::PreISelOpcode)";1209if (Inst.isPseudo)1210OS << "|(1ULL<<MCID::Pseudo)";1211if (Inst.isMeta)1212OS << "|(1ULL<<MCID::Meta)";1213if (Inst.isReturn)1214OS << "|(1ULL<<MCID::Return)";1215if (Inst.isEHScopeReturn)1216OS << "|(1ULL<<MCID::EHScopeReturn)";1217if (Inst.isBranch)1218OS << "|(1ULL<<MCID::Branch)";1219if (Inst.isIndirectBranch)1220OS << "|(1ULL<<MCID::IndirectBranch)";1221if (Inst.isCompare)1222OS << "|(1ULL<<MCID::Compare)";1223if (Inst.isMoveImm)1224OS << "|(1ULL<<MCID::MoveImm)";1225if (Inst.isMoveReg)1226OS << "|(1ULL<<MCID::MoveReg)";1227if (Inst.isBitcast)1228OS << "|(1ULL<<MCID::Bitcast)";1229if (Inst.isAdd)1230OS << "|(1ULL<<MCID::Add)";1231if (Inst.isTrap)1232OS << "|(1ULL<<MCID::Trap)";1233if (Inst.isSelect)1234OS << "|(1ULL<<MCID::Select)";1235if (Inst.isBarrier)1236OS << "|(1ULL<<MCID::Barrier)";1237if (Inst.hasDelaySlot)1238OS << "|(1ULL<<MCID::DelaySlot)";1239if (Inst.isCall)1240OS << "|(1ULL<<MCID::Call)";1241if (Inst.canFoldAsLoad)1242OS << "|(1ULL<<MCID::FoldableAsLoad)";1243if (Inst.mayLoad)1244OS << "|(1ULL<<MCID::MayLoad)";1245if (Inst.mayStore)1246OS << "|(1ULL<<MCID::MayStore)";1247if (Inst.mayRaiseFPException)1248OS << "|(1ULL<<MCID::MayRaiseFPException)";1249if (Inst.isPredicable)1250OS << "|(1ULL<<MCID::Predicable)";1251if (Inst.isConvertibleToThreeAddress)1252OS << "|(1ULL<<MCID::ConvertibleTo3Addr)";1253if (Inst.isCommutable)1254OS << "|(1ULL<<MCID::Commutable)";1255if (Inst.isTerminator)1256OS << "|(1ULL<<MCID::Terminator)";1257if (Inst.isReMaterializable)1258OS << "|(1ULL<<MCID::Rematerializable)";1259if (Inst.isNotDuplicable)1260OS << "|(1ULL<<MCID::NotDuplicable)";1261if (Inst.Operands.hasOptionalDef)1262OS << "|(1ULL<<MCID::HasOptionalDef)";1263if (Inst.usesCustomInserter)1264OS << "|(1ULL<<MCID::UsesCustomInserter)";1265if (Inst.hasPostISelHook)1266OS << "|(1ULL<<MCID::HasPostISelHook)";1267if (Inst.Operands.isVariadic)1268OS << "|(1ULL<<MCID::Variadic)";1269if (Inst.hasSideEffects)1270OS << "|(1ULL<<MCID::UnmodeledSideEffects)";1271if (Inst.isAsCheapAsAMove)1272OS << "|(1ULL<<MCID::CheapAsAMove)";1273if (!Target.getAllowRegisterRenaming() || Inst.hasExtraSrcRegAllocReq)1274OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)";1275if (!Target.getAllowRegisterRenaming() || Inst.hasExtraDefRegAllocReq)1276OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)";1277if (Inst.isRegSequence)1278OS << "|(1ULL<<MCID::RegSequence)";1279if (Inst.isExtractSubreg)1280OS << "|(1ULL<<MCID::ExtractSubreg)";1281if (Inst.isInsertSubreg)1282OS << "|(1ULL<<MCID::InsertSubreg)";1283if (Inst.isConvergent)1284OS << "|(1ULL<<MCID::Convergent)";1285if (Inst.variadicOpsAreDefs)1286OS << "|(1ULL<<MCID::VariadicOpsAreDefs)";1287if (Inst.isAuthenticated)1288OS << "|(1ULL<<MCID::Authenticated)";12891290// Emit all of the target-specific flags...1291BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");1292if (!TSF)1293PrintFatalError(Inst.TheDef->getLoc(), "no TSFlags?");1294uint64_t Value = 0;1295for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {1296if (const auto *Bit = dyn_cast<BitInit>(TSF->getBit(i)))1297Value |= uint64_t(Bit->getValue()) << i;1298else1299PrintFatalError(Inst.TheDef->getLoc(),1300"Invalid TSFlags bit in " + Inst.TheDef->getName());1301}1302OS << ", 0x";1303OS.write_hex(Value);1304OS << "ULL";13051306OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";1307}13081309// emitEnums - Print out enum values for all of the instructions.1310void InstrInfoEmitter::emitEnums(raw_ostream &OS) {1311OS << "#ifdef GET_INSTRINFO_ENUM\n";1312OS << "#undef GET_INSTRINFO_ENUM\n";13131314OS << "namespace llvm {\n\n";13151316const CodeGenTarget &Target = CDP.getTargetInfo();13171318// We must emit the PHI opcode first...1319StringRef Namespace = Target.getInstNamespace();13201321if (Namespace.empty())1322PrintFatalError("No instructions defined!");13231324OS << "namespace " << Namespace << " {\n";1325OS << " enum {\n";1326unsigned Num = 0;1327for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue())1328OS << " " << Inst->TheDef->getName()1329<< "\t= " << (Num = Target.getInstrIntValue(Inst->TheDef)) << ",\n";1330OS << " INSTRUCTION_LIST_END = " << Num + 1 << "\n";1331OS << " };\n\n";1332OS << "} // end namespace " << Namespace << "\n";1333OS << "} // end namespace llvm\n";1334OS << "#endif // GET_INSTRINFO_ENUM\n\n";13351336OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n";1337OS << "#undef GET_INSTRINFO_SCHED_ENUM\n";1338OS << "namespace llvm {\n\n";1339OS << "namespace " << Namespace << " {\n";1340OS << "namespace Sched {\n";1341OS << " enum {\n";1342Num = 0;1343for (const auto &Class : SchedModels.explicit_classes())1344OS << " " << Class.Name << "\t= " << Num++ << ",\n";1345OS << " SCHED_LIST_END = " << Num << "\n";1346OS << " };\n";1347OS << "} // end namespace Sched\n";1348OS << "} // end namespace " << Namespace << "\n";1349OS << "} // end namespace llvm\n";13501351OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n";1352}13531354static void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {1355RK.startTimer("Analyze DAG patterns");1356InstrInfoEmitter(RK).run(OS);1357RK.startTimer("Emit map table");1358EmitMapTable(RK, OS);1359}13601361static TableGen::Emitter::Opt X("gen-instr-info", EmitInstrInfo,1362"Generate instruction descriptions");136313641365