1456 lines · cpp
1//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// This tablegen backend is responsible for emitting a description of the target10// instruction set for the code generator.11//12//===----------------------------------------------------------------------===//13 14#include "Basic/SequenceToOffsetTable.h"15#include "Common/CodeGenDAGPatterns.h"16#include "Common/CodeGenInstruction.h"17#include "Common/CodeGenRegisters.h"18#include "Common/CodeGenSchedule.h"19#include "Common/CodeGenTarget.h"20#include "Common/PredicateExpander.h"21#include "Common/SubtargetFeatureInfo.h"22#include "Common/Types.h"23#include "TableGenBackends.h"24#include "llvm/ADT/ArrayRef.h"25#include "llvm/ADT/STLExtras.h"26#include "llvm/ADT/SmallVector.h"27#include "llvm/ADT/StringExtras.h"28#include "llvm/Support/Casting.h"29#include "llvm/Support/Format.h"30#include "llvm/Support/SourceMgr.h"31#include "llvm/Support/raw_ostream.h"32#include "llvm/TableGen/CodeGenHelpers.h"33#include "llvm/TableGen/Error.h"34#include "llvm/TableGen/Record.h"35#include "llvm/TableGen/TGTimer.h"36#include "llvm/TableGen/TableGenBackend.h"37#include <cassert>38#include <cstdint>39#include <iterator>40#include <map>41#include <string>42#include <utility>43#include <vector>44 45using namespace llvm;46 47static cl::OptionCategory InstrInfoEmitterCat("Options for -gen-instr-info");48static cl::opt<bool> ExpandMIOperandInfo(49 "instr-info-expand-mi-operand-info",50 cl::desc("Expand operand's MIOperandInfo DAG into suboperands"),51 cl::cat(InstrInfoEmitterCat), cl::init(true));52 53namespace {54 55class InstrInfoEmitter {56 const RecordKeeper &Records;57 const CodeGenDAGPatterns CDP;58 const CodeGenSchedModels &SchedModels;59 60public:61 InstrInfoEmitter(const RecordKeeper &R)62 : Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {}63 64 // run - Output the instruction set description.65 void run(raw_ostream &OS);66 67private:68 void emitEnums(raw_ostream &OS,69 ArrayRef<const CodeGenInstruction *> NumberedInstructions);70 71 using OperandInfoTy = std::vector<std::string>;72 using OperandInfoListTy = std::vector<OperandInfoTy>;73 using OperandInfoMapTy = std::map<OperandInfoTy, unsigned>;74 75 DenseMap<const CodeGenInstruction *, const CodeGenInstruction *>76 TargetSpecializedPseudoInsts;77 78 /// Compute mapping of opcodes which should have their definitions overridden79 /// by a target version.80 void buildTargetSpecializedPseudoInstsMap();81 82 /// Generate member functions in the target-specific GenInstrInfo class.83 ///84 /// This method is used to custom expand TIIPredicate definitions.85 /// See file llvm/Target/TargetInstPredicates.td for a description of what is86 /// a TIIPredicate and how to use it.87 void emitTIIHelperMethods(raw_ostream &OS, StringRef TargetName,88 bool ExpandDefinition = true);89 90 /// Expand TIIPredicate definitions to functions that accept a const MCInst91 /// reference.92 void emitMCIIHelperMethods(raw_ostream &OS, StringRef TargetName);93 94 /// Write verifyInstructionPredicates methods.95 void emitFeatureVerifier(raw_ostream &OS, const CodeGenTarget &Target);96 void emitRecord(const CodeGenInstruction &Inst, unsigned Num,97 const Record *InstrInfo,98 std::map<std::vector<const Record *>, unsigned> &EL,99 const OperandInfoMapTy &OperandInfo, raw_ostream &OS);100 void emitOperandTypeMappings(101 raw_ostream &OS, const CodeGenTarget &Target,102 ArrayRef<const CodeGenInstruction *> NumberedInstructions);103 void emitOperandNameMappings(104 raw_ostream &OS, const CodeGenTarget &Target,105 ArrayRef<const CodeGenInstruction *> TargetInstructions);106 void emitLogicalOperandSizeMappings(107 raw_ostream &OS, StringRef Namespace,108 ArrayRef<const CodeGenInstruction *> TargetInstructions);109 110 // Operand information.111 unsigned CollectOperandInfo(OperandInfoListTy &OperandInfoList,112 OperandInfoMapTy &OperandInfoMap);113 void EmitOperandInfo(raw_ostream &OS, OperandInfoListTy &OperandInfoList);114 OperandInfoTy GetOperandInfo(const CodeGenInstruction &Inst);115};116 117} // end anonymous namespace118 119//===----------------------------------------------------------------------===//120// Operand Info Emission.121//===----------------------------------------------------------------------===//122 123InstrInfoEmitter::OperandInfoTy124InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {125 OperandInfoTy Result;126 StringRef Namespace = CDP.getTargetInfo().getInstNamespace();127 128 for (auto &Op : Inst.Operands) {129 // Handle aggregate operands and normal operands the same way by expanding130 // either case into a list of operands for this op.131 std::vector<CGIOperandList::OperandInfo> OperandList;132 133 // This might be a multiple operand thing. Targets like X86 have registers134 // in their multi-operand operands. It may also be an anonymous operand,135 // which has a single operand, but no declared class for the operand.136 const DagInit *MIOI = Op.MIOperandInfo;137 138 if (!MIOI || MIOI->getNumArgs() == 0) {139 // Single, anonymous, operand.140 OperandList.push_back(Op);141 } else {142 for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {143 OperandList.push_back(Op);144 145 auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef();146 OperandList.back().Rec = OpR;147 }148 }149 150 for (const auto &[OpInfo, Constraint] :151 zip_equal(OperandList, Op.Constraints)) {152 const Record *OpR = OpInfo.Rec;153 std::string Res;154 155 if (OpR->isSubClassOf("RegisterOperand"))156 OpR = OpR->getValueAsDef("RegClass");157 158 if (OpR->isSubClassOf("RegClassByHwMode")) {159 Res += Namespace;160 Res += "::";161 Res += OpR->getName();162 Res += ", ";163 } else if (OpR->isSubClassOf("RegisterClass"))164 Res += getQualifiedName(OpR) + "RegClassID, ";165 else if (OpR->isSubClassOf("PointerLikeRegClass")) {166 if (Inst.isPseudo) {167 // TODO: Verify this is a fixed pseudo168 PrintError(Inst.TheDef,169 "missing target override for pseudoinstruction "170 "using PointerLikeRegClass");171 PrintNote(OpR->getLoc(),172 "target should define equivalent instruction "173 "with RegisterClassLike replacement; (use "174 "RemapAllTargetPseudoPointerOperands?)");175 } else {176 PrintError(Inst.TheDef,177 "non-pseudoinstruction user of PointerLikeRegClass");178 }179 } else180 // -1 means the operand does not have a fixed register class.181 Res += "-1, ";182 183 // Fill in applicable flags.184 Res += "0";185 186 if (OpR->isSubClassOf("RegClassByHwMode"))187 Res += "|(1<<MCOI::LookupRegClassByHwMode)";188 189 // Predicate operands. Check to see if the original unexpanded operand190 // was of type PredicateOp.191 if (Op.Rec->isSubClassOf("PredicateOp"))192 Res += "|(1<<MCOI::Predicate)";193 194 // Optional def operands. Check to see if the original unexpanded operand195 // was of type OptionalDefOperand.196 if (Op.Rec->isSubClassOf("OptionalDefOperand"))197 Res += "|(1<<MCOI::OptionalDef)";198 199 // Branch target operands. Check to see if the original unexpanded200 // operand was of type BranchTargetOperand.201 if (Op.Rec->isSubClassOf("BranchTargetOperand"))202 Res += "|(1<<MCOI::BranchTarget)";203 204 // Fill in operand type.205 Res += ", ";206 assert(!Op.OperandType.empty() && "Invalid operand type.");207 Res += Op.OperandType;208 209 // Fill in constraint info.210 Res += ", ";211 212 if (Constraint.isNone()) {213 Res += "0";214 } else if (Constraint.isEarlyClobber()) {215 Res += "MCOI_EARLY_CLOBBER";216 } else {217 assert(Constraint.isTied());218 Res += "MCOI_TIED_TO(" + utostr(Constraint.getTiedOperand()) + ")";219 }220 221 Result.push_back(Res);222 }223 }224 225 return Result;226}227 228unsigned229InstrInfoEmitter::CollectOperandInfo(OperandInfoListTy &OperandInfoList,230 OperandInfoMapTy &OperandInfoMap) {231 const CodeGenTarget &Target = CDP.getTargetInfo();232 unsigned Offset = 0;233 for (const CodeGenInstruction *Inst : Target.getInstructions()) {234 auto OverrideEntry = TargetSpecializedPseudoInsts.find(Inst);235 if (OverrideEntry != TargetSpecializedPseudoInsts.end())236 Inst = OverrideEntry->second;237 238 OperandInfoTy OperandInfo = GetOperandInfo(*Inst);239 if (OperandInfoMap.try_emplace(OperandInfo, Offset).second) {240 OperandInfoList.push_back(OperandInfo);241 Offset += OperandInfo.size();242 }243 }244 return Offset;245}246 247void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,248 OperandInfoListTy &OperandInfoList) {249 unsigned Offset = 0;250 for (auto &OperandInfo : OperandInfoList) {251 OS << " /* " << Offset << " */";252 for (auto &Info : OperandInfo)253 OS << " { " << Info << " },";254 OS << '\n';255 Offset += OperandInfo.size();256 }257}258 259static void emitGetInstructionIndexForOpLookup(260 raw_ostream &OS, const MapVector<SmallVector<int>, unsigned> &OperandMap,261 ArrayRef<unsigned> InstructionIndex) {262 StringRef Type = OperandMap.size() <= UINT8_MAX + 1 ? "uint8_t" : "uint16_t";263 OS << "LLVM_READONLY static " << Type264 << " getInstructionIndexForOpLookup(uint16_t Opcode) {\n"265 " static constexpr "266 << Type << " InstructionIndex[] = {";267 for (auto [TableIndex, Entry] : enumerate(InstructionIndex))268 OS << (TableIndex % 16 == 0 ? "\n " : " ") << Entry << ',';269 OS << "\n };\n"270 " return InstructionIndex[Opcode];\n"271 "}\n";272}273 274static void275emitGetNamedOperandIdx(raw_ostream &OS,276 const MapVector<SmallVector<int>, unsigned> &OperandMap,277 unsigned MaxOperandNo, unsigned NumOperandNames) {278 OS << "LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, OpName "279 "Name) {\n";280 OS << " assert(Name != OpName::NUM_OPERAND_NAMES);\n";281 if (!NumOperandNames) {282 // There are no operands, so no need to emit anything283 OS << " return -1;\n}\n";284 return;285 }286 assert(MaxOperandNo <= INT16_MAX &&287 "Too many operands for the operand name -> index table");288 StringRef Type = MaxOperandNo <= INT8_MAX ? "int8_t" : "int16_t";289 OS << " static constexpr " << Type << " OperandMap[][" << NumOperandNames290 << "] = {\n";291 for (const auto &[OpList, _] : OperandMap) {292 // Emit a row of the OperandMap table.293 OS << " {";294 for (unsigned ID = 0; ID < NumOperandNames; ++ID)295 OS << (ID < OpList.size() ? OpList[ID] : -1) << ", ";296 OS << "},\n";297 }298 OS << " };\n";299 300 OS << " unsigned InstrIdx = getInstructionIndexForOpLookup(Opcode);\n"301 " return OperandMap[InstrIdx][(unsigned)Name];\n"302 "}\n";303}304 305static void306emitGetOperandIdxName(raw_ostream &OS,307 const MapVector<StringRef, unsigned> &OperandNameToID,308 const MapVector<SmallVector<int>, unsigned> &OperandMap,309 unsigned MaxNumOperands, unsigned NumOperandNames) {310 OS << "LLVM_READONLY OpName getOperandIdxName(uint16_t Opcode, int16_t Idx) "311 "{\n";312 OS << " assert(Idx >= 0 && Idx < " << MaxNumOperands << ");\n";313 if (!MaxNumOperands) {314 // There are no operands, so no need to emit anything315 OS << " return -1;\n}\n";316 return;317 }318 OS << " static constexpr OpName OperandMap[][" << MaxNumOperands319 << "] = {\n";320 for (const auto &[OpList, _] : OperandMap) {321 SmallVector<unsigned> IDs(MaxNumOperands, NumOperandNames);322 for (const auto &[ID, Idx] : enumerate(OpList)) {323 if (Idx >= 0)324 IDs[Idx] = ID;325 }326 // Emit a row of the OperandMap table. Map operand indices to enum values.327 OS << " {";328 for (unsigned ID : IDs) {329 if (ID == NumOperandNames)330 OS << "OpName::NUM_OPERAND_NAMES, ";331 else332 OS << "OpName::" << OperandNameToID.getArrayRef()[ID].first << ", ";333 }334 OS << "},\n";335 }336 OS << " };\n";337 338 OS << " unsigned InstrIdx = getInstructionIndexForOpLookup(Opcode);\n"339 " return OperandMap[InstrIdx][(unsigned)Idx];\n"340 "}\n";341}342 343/// Generate a table and function for looking up the indices of operands by344/// name.345///346/// This code generates:347/// - An enum in the llvm::TargetNamespace::OpName namespace, with one entry348/// for each operand name.349/// - A 2-dimensional table for mapping OpName enum values to operand indices.350/// - A function called getNamedOperandIdx(uint16_t Opcode, OpName Name)351/// for looking up the operand index for an instruction, given a value from352/// OpName enum353/// - A 2-dimensional table for mapping operand indices to OpName enum values.354/// - A function called getOperandIdxName(uint16_t Opcode, int16_t Idx)355/// for looking up the OpName enum for an instruction, given the operand356/// index. This is the inverse of getNamedOperandIdx().357///358/// Fixed/Predefined instructions do not have UseNamedOperandTable enabled, so359/// we can just skip them. Hence accept just the TargetInstructions.360void InstrInfoEmitter::emitOperandNameMappings(361 raw_ostream &OS, const CodeGenTarget &Target,362 ArrayRef<const CodeGenInstruction *> TargetInstructions) {363 // Map of operand names to their ID.364 MapVector<StringRef, unsigned> OperandNameToID;365 366 /// A key in this map is a vector mapping OpName ID values to instruction367 /// operand indices or -1 (but without any trailing -1 values which will be368 /// added later). The corresponding value in this map is the index of that row369 /// in the emitted OperandMap table. This map helps to unique entries among370 /// instructions that have identical OpName -> Operand index mapping.371 MapVector<SmallVector<int>, unsigned> OperandMap;372 373 // Max operand index seen.374 unsigned MaxOperandNo = 0;375 376 // Fixed/Predefined instructions do not have UseNamedOperandTable enabled, so377 // add a dummy map entry for them.378 OperandMap.try_emplace({}, 0);379 unsigned FirstTargetVal = TargetInstructions.front()->EnumVal;380 SmallVector<unsigned> InstructionIndex(FirstTargetVal, 0);381 for (const CodeGenInstruction *Inst : TargetInstructions) {382 if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) {383 InstructionIndex.push_back(0);384 continue;385 }386 SmallVector<int> OpList;387 for (const auto &Info : Inst->Operands) {388 unsigned ID =389 OperandNameToID.try_emplace(Info.Name, OperandNameToID.size())390 .first->second;391 OpList.resize(std::max((unsigned)OpList.size(), ID + 1), -1);392 OpList[ID] = Info.MIOperandNo;393 MaxOperandNo = std::max(MaxOperandNo, Info.MIOperandNo);394 }395 auto [It, Inserted] =396 OperandMap.try_emplace(std::move(OpList), OperandMap.size());397 InstructionIndex.push_back(It->second);398 }399 400 const size_t NumOperandNames = OperandNameToID.size();401 const unsigned MaxNumOperands = MaxOperandNo + 1;402 403 const SmallString<32> Namespace({"llvm::", Target.getInstNamespace()});404 {405 IfDefEmitter IfDef(OS, "GET_INSTRINFO_OPERAND_ENUM");406 NamespaceEmitter NS(OS, Namespace);407 408 assert(NumOperandNames <= UINT16_MAX &&409 "Too many operands for the operand index -> name table");410 StringRef EnumType = getMinimalTypeForRange(NumOperandNames);411 OS << "enum class OpName : " << EnumType << " {\n";412 for (const auto &[Op, I] : OperandNameToID)413 OS << " " << Op << " = " << I << ",\n";414 OS << " NUM_OPERAND_NAMES = " << NumOperandNames << ",\n";415 OS << "}; // enum class OpName\n\n";416 417 OS << "LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, OpName "418 "Name);\n";419 OS << "LLVM_READONLY OpName getOperandIdxName(uint16_t Opcode, int16_t "420 "Idx);\n";421 }422 423 {424 IfDefEmitter IfDef(OS, "GET_INSTRINFO_NAMED_OPS");425 NamespaceEmitter NS(OS, Namespace);426 emitGetInstructionIndexForOpLookup(OS, OperandMap, InstructionIndex);427 428 emitGetNamedOperandIdx(OS, OperandMap, MaxOperandNo, NumOperandNames);429 emitGetOperandIdxName(OS, OperandNameToID, OperandMap, MaxNumOperands,430 NumOperandNames);431 }432}433 434/// Generate an enum for all the operand types for this target, under the435/// llvm::TargetNamespace::OpTypes namespace.436/// Operand types are all definitions derived of the Operand Target.td class.437///438void InstrInfoEmitter::emitOperandTypeMappings(439 raw_ostream &OS, const CodeGenTarget &Target,440 ArrayRef<const CodeGenInstruction *> NumberedInstructions) {441 StringRef Namespace = Target.getInstNamespace();442 443 // These generated functions are used only by the X86 target444 // (in bolt/lib/Target/X86/X86MCPlusBuilder.cpp). So emit them only445 // for X86.446 if (Namespace != "X86")447 return;448 449 ArrayRef<const Record *> Operands =450 Records.getAllDerivedDefinitions("Operand");451 ArrayRef<const Record *> RegisterOperands =452 Records.getAllDerivedDefinitions("RegisterOperand");453 ArrayRef<const Record *> RegisterClasses =454 Records.getAllDerivedDefinitions("RegisterClass");455 456 unsigned EnumVal = 0;457 458 {459 IfDefEmitter IfDef(OS, "GET_INSTRINFO_OPERAND_TYPES_ENUM");460 NamespaceEmitter NS(OS, ("llvm::" + Namespace + "::OpTypes").str());461 OS << "enum OperandType {\n";462 463 for (ArrayRef<const Record *> RecordsToAdd :464 {Operands, RegisterOperands, RegisterClasses}) {465 for (const Record *Op : RecordsToAdd) {466 if (!Op->isAnonymous())467 OS << " " << Op->getName() << " = " << EnumVal << ",\n";468 ++EnumVal;469 }470 }471 472 OS << " OPERAND_TYPE_LIST_END" << "\n};\n";473 }474 475 {476 IfDefEmitter IfDef(OS, "GET_INSTRINFO_OPERAND_TYPE");477 NamespaceEmitter NS(OS, ("llvm::" + Namespace).str());478 OS << "LLVM_READONLY\n";479 OS << "static int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n";480 auto getInstrName = [&](int I) -> StringRef {481 return NumberedInstructions[I]->getName();482 };483 // TODO: Factor out duplicate operand lists to compress the tables.484 std::vector<size_t> OperandOffsets;485 std::vector<const Record *> OperandRecords;486 size_t CurrentOffset = 0;487 for (const CodeGenInstruction *Inst : NumberedInstructions) {488 OperandOffsets.push_back(CurrentOffset);489 for (const auto &Op : Inst->Operands) {490 const DagInit *MIOI = Op.MIOperandInfo;491 if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) {492 // Single, anonymous, operand.493 OperandRecords.push_back(Op.Rec);494 ++CurrentOffset;495 } else {496 for (const Init *Arg : MIOI->getArgs()) {497 OperandRecords.push_back(cast<DefInit>(Arg)->getDef());498 ++CurrentOffset;499 }500 }501 }502 }503 504 // Emit the table of offsets (indexes) into the operand type table.505 // Size the unsigned integer offset to save space.506 assert(OperandRecords.size() <= UINT32_MAX &&507 "Too many operands for offset table");508 OS << " static constexpr "509 << getMinimalTypeForRange(OperandRecords.size());510 OS << " Offsets[] = {\n";511 for (const auto &[Idx, Offset] : enumerate(OperandOffsets))512 OS << " " << Offset << ", // " << getInstrName(Idx) << '\n';513 OS << " };\n";514 515 // Add an entry for the end so that we don't need to special case it below.516 OperandOffsets.push_back(OperandRecords.size());517 518 // Emit the actual operand types in a flat table.519 // Size the signed integer operand type to save space.520 assert(EnumVal <= INT16_MAX &&521 "Too many operand types for operand types table");522 OS << "\n using namespace OpTypes;\n";523 OS << " static";524 OS << (EnumVal <= INT8_MAX ? " constexpr int8_t" : " constexpr int16_t");525 OS << " OpcodeOperandTypes[] = {";526 size_t CurOffset = 0;527 for (auto [Idx, OpR] : enumerate(OperandRecords)) {528 // We print each Opcode's operands in its own row.529 if (Idx == OperandOffsets[CurOffset]) {530 OS << "\n /* " << getInstrName(CurOffset) << " */\n ";531 while (OperandOffsets[++CurOffset] == Idx)532 OS << "/* " << getInstrName(CurOffset) << " */\n ";533 }534 if ((OpR->isSubClassOf("Operand") ||535 OpR->isSubClassOf("RegisterOperand") ||536 OpR->isSubClassOf("RegisterClass")) &&537 !OpR->isAnonymous())538 OS << OpR->getName();539 else540 OS << -1;541 OS << ", ";542 }543 OS << "\n };\n";544 545 OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n";546 OS << "}\n";547 }548 549 {550 IfDefEmitter IfDef(OS, "GET_INSTRINFO_MEM_OPERAND_SIZE");551 NamespaceEmitter NS(OS, ("llvm::" + Namespace).str());552 553 OS << "LLVM_READONLY\n";554 OS << "static int getMemOperandSize(int OpType) {\n";555 OS << " switch (OpType) {\n";556 std::map<int, SmallVector<StringRef, 0>> SizeToOperandName;557 for (const Record *Op : Operands) {558 if (!Op->isSubClassOf("X86MemOperand"))559 continue;560 if (int Size = Op->getValueAsInt("Size"))561 SizeToOperandName[Size].push_back(Op->getName());562 }563 OS << " default: return 0;\n";564 for (const auto &[Size, OperandNames] : SizeToOperandName) {565 for (const StringRef &OperandName : OperandNames)566 OS << " case OpTypes::" << OperandName << ":\n";567 OS << " return " << Size << ";\n\n";568 }569 OS << " }\n}\n";570 }571}572 573// Fixed/Predefined instructions do not have UseLogicalOperandMappings574// enabled, so we can just skip them. Hence accept TargetInstructions.575void InstrInfoEmitter::emitLogicalOperandSizeMappings(576 raw_ostream &OS, StringRef Namespace,577 ArrayRef<const CodeGenInstruction *> TargetInstructions) {578 std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap;579 std::map<unsigned, std::vector<std::string>> InstMap;580 581 size_t LogicalOpListSize = 0U;582 std::vector<unsigned> LogicalOpList;583 584 for (const auto *Inst : TargetInstructions) {585 if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))586 continue;587 588 LogicalOpList.clear();589 llvm::transform(Inst->Operands, std::back_inserter(LogicalOpList),590 [](const CGIOperandList::OperandInfo &Op) -> unsigned {591 auto *MIOI = Op.MIOperandInfo;592 if (!MIOI || MIOI->getNumArgs() == 0)593 return 1;594 return MIOI->getNumArgs();595 });596 LogicalOpListSize = std::max(LogicalOpList.size(), LogicalOpListSize);597 598 auto I =599 LogicalOpSizeMap.try_emplace(LogicalOpList, LogicalOpSizeMap.size())600 .first;601 InstMap[I->second].push_back((Namespace + "::" + Inst->getName()).str());602 }603 604 IfDefEmitter IfDef(OS, "GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP");605 NamespaceEmitter NS(OS, ("llvm::" + Namespace).str());606 OS << "LLVM_READONLY static unsigned\n";607 OS << "getLogicalOperandSize(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";608 if (!InstMap.empty()) {609 std::vector<const std::vector<unsigned> *> LogicalOpSizeList(610 LogicalOpSizeMap.size());611 for (auto &P : LogicalOpSizeMap) {612 LogicalOpSizeList[P.second] = &P.first;613 }614 OS << " static const unsigned SizeMap[][" << LogicalOpListSize615 << "] = {\n";616 for (auto &R : LogicalOpSizeList) {617 const auto &Row = *R;618 OS << " {";619 int i;620 for (i = 0; i < static_cast<int>(Row.size()); ++i) {621 OS << Row[i] << ", ";622 }623 for (; i < static_cast<int>(LogicalOpListSize); ++i) {624 OS << "0, ";625 }626 OS << "}, \n";627 }628 OS << " };\n";629 630 OS << " switch (Opcode) {\n";631 OS << " default: return LogicalOpIdx;\n";632 for (auto &P : InstMap) {633 auto OpMapIdx = P.first;634 const auto &Insts = P.second;635 for (const auto &Inst : Insts) {636 OS << " case " << Inst << ":\n";637 }638 OS << " return SizeMap[" << OpMapIdx << "][LogicalOpIdx];\n";639 }640 OS << " }\n";641 } else {642 OS << " return LogicalOpIdx;\n";643 }644 OS << "}\n";645 646 OS << "LLVM_READONLY static inline unsigned\n";647 OS << "getLogicalOperandIdx(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";648 OS << " auto S = 0U;\n";649 OS << " for (auto i = 0U; i < LogicalOpIdx; ++i)\n";650 OS << " S += getLogicalOperandSize(Opcode, i);\n";651 OS << " return S;\n";652 OS << "}\n";653}654 655void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,656 StringRef TargetName) {657 ArrayRef<const Record *> TIIPredicates =658 Records.getAllDerivedDefinitions("TIIPredicate");659 660 {661 IfDefEmitter IfDef(OS, "GET_INSTRINFO_MC_HELPER_DECLS");662 NamespaceEmitter LlvmNS(OS, "llvm");663 OS << "class MCInst;\n";664 OS << "class FeatureBitset;\n\n";665 666 NamespaceEmitter TargetNS(OS, (TargetName + "_MC").str());667 for (const Record *Rec : TIIPredicates)668 OS << "bool " << Rec->getValueAsString("FunctionName")669 << "(const MCInst &MI);\n";670 671 OS << "void verifyInstructionPredicates(unsigned Opcode, const "672 "FeatureBitset "673 "&Features);\n";674 }675 676 {677 IfDefEmitter IfDef(OS, "GET_INSTRINFO_MC_HELPERS");678 NamespaceEmitter NS(OS, ("llvm::" + TargetName + "_MC").str());679 680 PredicateExpander PE(TargetName);681 PE.setExpandForMC(true);682 683 for (const Record *Rec : TIIPredicates) {684 OS << "bool " << Rec->getValueAsString("FunctionName");685 OS << "(const MCInst &MI) {\n";686 687 OS << PE.getIndent();688 PE.expandStatement(OS, Rec->getValueAsDef("Body"));689 OS << "\n}\n\n";690 }691 }692}693 694static std::string695getNameForFeatureBitset(ArrayRef<const Record *> FeatureBitset) {696 std::string Name = "CEFBS";697 for (const Record *Feature : FeatureBitset)698 Name += ("_" + Feature->getName()).str();699 return Name;700}701 702void InstrInfoEmitter::emitFeatureVerifier(raw_ostream &OS,703 const CodeGenTarget &Target) {704 const auto &All = SubtargetFeatureInfo::getAll(Records);705 SubtargetFeatureInfoMap SubtargetFeatures;706 SubtargetFeatures.insert(All.begin(), All.end());707 708 OS << "#if (defined(ENABLE_INSTR_PREDICATE_VERIFIER) && !defined(NDEBUG)) "709 << "||\\\n"710 << " defined(GET_AVAILABLE_OPCODE_CHECKER)\n"711 << "#define GET_COMPUTE_FEATURES\n"712 << "#endif\n";713 std::string Namespace = ("llvm::" + Target.getName() + "_MC").str();714 {715 IfDefEmitter IfDef(OS, "GET_COMPUTE_FEATURES");716 NamespaceEmitter NS(OS, Namespace);717 718 // Emit the subtarget feature enumeration.719 SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,720 OS);721 // Emit the available features compute function.722 OS << "inline ";723 SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(724 Target.getName(), "", "computeAvailableFeatures", SubtargetFeatures,725 OS);726 727 std::vector<std::vector<const Record *>> FeatureBitsets;728 for (const CodeGenInstruction *Inst : Target.getInstructions()) {729 FeatureBitsets.emplace_back();730 for (const Record *Predicate :731 Inst->TheDef->getValueAsListOfDefs("Predicates")) {732 const auto &I = SubtargetFeatures.find(Predicate);733 if (I != SubtargetFeatures.end())734 FeatureBitsets.back().push_back(I->second.TheDef);735 }736 }737 738 llvm::sort(FeatureBitsets, [&](ArrayRef<const Record *> A,739 ArrayRef<const Record *> B) {740 if (A.size() < B.size())741 return true;742 if (A.size() > B.size())743 return false;744 for (auto Pair : zip(A, B)) {745 if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())746 return true;747 if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())748 return false;749 }750 return false;751 });752 FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end());753 OS << "inline FeatureBitset computeRequiredFeatures(unsigned Opcode) {\n"754 << " enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"755 << " CEFBS_None,\n";756 for (const auto &FeatureBitset : FeatureBitsets) {757 if (FeatureBitset.empty())758 continue;759 OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";760 }761 OS << " };\n\n"762 << " static constexpr FeatureBitset FeatureBitsets[] = {\n"763 << " {}, // CEFBS_None\n";764 for (const auto &FeatureBitset : FeatureBitsets) {765 if (FeatureBitset.empty())766 continue;767 OS << " {";768 for (const auto &Feature : FeatureBitset) {769 const auto &I = SubtargetFeatures.find(Feature);770 assert(I != SubtargetFeatures.end() && "Didn't import predicate?");771 OS << I->second.getEnumBitName() << ", ";772 }773 OS << "},\n";774 }775 OS << " };\n"776 << " static constexpr " << getMinimalTypeForRange(FeatureBitsets.size())777 << " RequiredFeaturesRefs[] = {\n";778 ArrayRef<const CodeGenInstruction *> NumberedInstructions =779 Target.getInstructions();780 for (const CodeGenInstruction *Inst : NumberedInstructions) {781 OS << " CEFBS";782 unsigned NumPredicates = 0;783 for (const Record *Predicate :784 Inst->TheDef->getValueAsListOfDefs("Predicates")) {785 const auto &I = SubtargetFeatures.find(Predicate);786 if (I != SubtargetFeatures.end()) {787 OS << '_' << I->second.TheDef->getName();788 NumPredicates++;789 }790 }791 if (!NumPredicates)792 OS << "_None";793 OS << ", // " << Inst->getName() << '\n';794 }795 OS << " };\n\n"796 << " assert(Opcode < " << NumberedInstructions.size() << ");\n"797 << " return FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n"798 << "}\n\n";799 } // end scope for GET_COMPUTE_FEATURES800 801 {802 IfDefEmitter IfDef(OS, "GET_AVAILABLE_OPCODE_CHECKER");803 NamespaceEmitter NS(OS, Namespace);804 OS << "bool isOpcodeAvailable("805 << "unsigned Opcode, const FeatureBitset &Features) {\n"806 << " FeatureBitset AvailableFeatures = "807 << "computeAvailableFeatures(Features);\n"808 << " FeatureBitset RequiredFeatures = "809 << "computeRequiredFeatures(Opcode);\n"810 << " FeatureBitset MissingFeatures =\n"811 << " (AvailableFeatures & RequiredFeatures) ^\n"812 << " RequiredFeatures;\n"813 << " return !MissingFeatures.any();\n"814 << "}\n";815 }816 817 {818 IfDefEmitter IfDef(OS, "ENABLE_INSTR_PREDICATE_VERIFIER");819 OS << "#include <sstream>\n\n";820 NamespaceEmitter NS(OS, Namespace);821 // Emit the name table for error messages.822 OS << "#ifndef NDEBUG\n";823 SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS);824 OS << "#endif // NDEBUG\n\n";825 // Emit the predicate verifier.826 OS << "void verifyInstructionPredicates(\n"827 << " unsigned Opcode, const FeatureBitset &Features) {\n"828 << "#ifndef NDEBUG\n";829 OS << " FeatureBitset AvailableFeatures = "830 "computeAvailableFeatures(Features);\n";831 OS << " FeatureBitset RequiredFeatures = "832 << "computeRequiredFeatures(Opcode);\n";833 OS << " FeatureBitset MissingFeatures =\n"834 << " (AvailableFeatures & RequiredFeatures) ^\n"835 << " RequiredFeatures;\n"836 << " if (MissingFeatures.any()) {\n"837 << " std::ostringstream Msg;\n"838 << " Msg << \"Attempting to emit \" << &" << Target.getName()839 << "InstrNameData[" << Target.getName() << "InstrNameIndices[Opcode]]\n"840 << " << \" instruction but the \";\n"841 << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n"842 << " if (MissingFeatures.test(i))\n"843 << " Msg << SubtargetFeatureNames[i] << \" \";\n"844 << " Msg << \"predicate(s) are not met\";\n"845 << " report_fatal_error(Msg.str().c_str());\n"846 << " }\n"847 << "#endif // NDEBUG\n";848 OS << "}\n";849 }850}851 852void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS,853 StringRef TargetName,854 bool ExpandDefinition) {855 ArrayRef<const Record *> TIIPredicates =856 Records.getAllDerivedDefinitions("TIIPredicate");857 if (TIIPredicates.empty())858 return;859 860 PredicateExpander PE(TargetName);861 PE.setExpandForMC(false);862 863 for (const Record *Rec : TIIPredicates) {864 OS << (ExpandDefinition ? "" : "static ") << "bool ";865 if (ExpandDefinition)866 OS << TargetName << "InstrInfo::";867 OS << Rec->getValueAsString("FunctionName");868 OS << "(const MachineInstr &MI)";869 if (!ExpandDefinition) {870 OS << ";\n";871 continue;872 }873 874 OS << " {\n";875 OS << PE.getIndent();876 PE.expandStatement(OS, Rec->getValueAsDef("Body"));877 OS << "\n}\n\n";878 }879}880 881void InstrInfoEmitter::buildTargetSpecializedPseudoInstsMap() {882 ArrayRef<const Record *> SpecializedInsts = Records.getAllDerivedDefinitions(883 "TargetSpecializedStandardPseudoInstruction");884 const CodeGenTarget &Target = CDP.getTargetInfo();885 886 for (const Record *SpecializedRec : SpecializedInsts) {887 const CodeGenInstruction &SpecializedInst =888 Target.getInstruction(SpecializedRec);889 const Record *BaseInstRec = SpecializedRec->getValueAsDef("Instruction");890 891 const CodeGenInstruction &BaseInst = Target.getInstruction(BaseInstRec);892 893 if (!TargetSpecializedPseudoInsts.insert({&BaseInst, &SpecializedInst})894 .second)895 PrintFatalError(SpecializedRec, "multiple overrides of '" +896 BaseInst.getName() + "' defined");897 }898}899 900//===----------------------------------------------------------------------===//901// Main Output.902//===----------------------------------------------------------------------===//903 904// run - Emit the main instruction description records for the target...905void InstrInfoEmitter::run(raw_ostream &OS) {906 TGTimer &Timer = Records.getTimer();907 Timer.startTimer("Analyze DAG patterns");908 909 emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);910 911 const CodeGenTarget &Target = CDP.getTargetInfo();912 ArrayRef<const CodeGenInstruction *> NumberedInstructions =913 Target.getInstructions();914 915 emitEnums(OS, NumberedInstructions);916 917 StringRef TargetName = Target.getName();918 const Record *InstrInfo = Target.getInstructionSet();919 920 // Collect all of the operand info records.921 Timer.startTimer("Collect operand info");922 buildTargetSpecializedPseudoInstsMap();923 924 OperandInfoListTy OperandInfoList;925 OperandInfoMapTy OperandInfoMap;926 unsigned OperandInfoSize =927 CollectOperandInfo(OperandInfoList, OperandInfoMap);928 929 // Collect all of the instruction's implicit uses and defs.930 // Also collect which features are enabled by instructions to control931 // emission of various mappings.932 933 bool HasUseLogicalOperandMappings = false;934 bool HasUseNamedOperandTable = false;935 936 Timer.startTimer("Collect uses/defs");937 std::map<std::vector<const Record *>, unsigned> EmittedLists;938 std::vector<std::vector<const Record *>> ImplicitLists;939 unsigned ImplicitListSize = 0;940 for (const CodeGenInstruction *Inst : NumberedInstructions) {941 HasUseLogicalOperandMappings |=942 Inst->TheDef->getValueAsBit("UseLogicalOperandMappings");943 HasUseNamedOperandTable |=944 Inst->TheDef->getValueAsBit("UseNamedOperandTable");945 946 std::vector<const Record *> ImplicitOps = Inst->ImplicitUses;947 llvm::append_range(ImplicitOps, Inst->ImplicitDefs);948 if (EmittedLists.try_emplace(ImplicitOps, ImplicitListSize).second) {949 ImplicitLists.push_back(ImplicitOps);950 ImplicitListSize += ImplicitOps.size();951 }952 }953 954 {955 IfGuardEmitter IfGuard(956 OS,957 "defined(GET_INSTRINFO_MC_DESC) || defined(GET_INSTRINFO_CTOR_DTOR)");958 NamespaceEmitter NS(OS, "llvm");959 960 OS << "struct " << TargetName << "InstrTable {\n";961 OS << " MCInstrDesc Insts[" << NumberedInstructions.size() << "];\n";962 OS << " static_assert(alignof(MCInstrDesc) >= alignof(MCOperandInfo), "963 "\"Unwanted padding between Insts and OperandInfo\");\n";964 OS << " MCOperandInfo OperandInfo[" << OperandInfoSize << "];\n";965 OS << " static_assert(alignof(MCOperandInfo) >= alignof(MCPhysReg), "966 "\"Unwanted padding between OperandInfo and ImplicitOps\");\n";967 OS << " MCPhysReg ImplicitOps[" << std::max(ImplicitListSize, 1U)968 << "];\n";969 OS << "};";970 }971 972 const CodeGenRegBank &RegBank = Target.getRegBank();973 const CodeGenHwModes &CGH = Target.getHwModes();974 unsigned NumModes = CGH.getNumModeIds();975 ArrayRef<const Record *> RegClassByHwMode = Target.getAllRegClassByHwMode();976 unsigned NumClassesByHwMode = RegClassByHwMode.size();977 978 bool HasDeprecationFeatures =979 llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {980 return !Inst->HasComplexDeprecationPredicate &&981 !Inst->DeprecatedReason.empty();982 });983 bool HasComplexDeprecationInfos =984 llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {985 return Inst->HasComplexDeprecationPredicate;986 });987 988 {989 IfDefEmitter IfDef(OS, "GET_INSTRINFO_MC_DESC");990 NamespaceEmitter LlvmNS(OS, "llvm");991 992 // Emit all of the MCInstrDesc records in reverse ENUM ordering.993 Timer.startTimer("Emit InstrDesc records");994 OS << "static_assert(sizeof(MCOperandInfo) % sizeof(MCPhysReg) == 0);\n";995 OS << "static constexpr unsigned " << TargetName << "ImpOpBase = sizeof "996 << TargetName << "InstrTable::OperandInfo / (sizeof(MCPhysReg));\n\n";997 998 OS << "extern const " << TargetName << "InstrTable " << TargetName999 << "Descs = {\n {\n";1000 SequenceToOffsetTable<StringRef> InstrNames;1001 unsigned Num = NumberedInstructions.size();1002 for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) {1003 // Keep a list of the instruction names.1004 InstrNames.add(Inst->getName());1005 1006 auto OverrideEntry = TargetSpecializedPseudoInsts.find(Inst);1007 if (OverrideEntry != TargetSpecializedPseudoInsts.end())1008 Inst = OverrideEntry->second;1009 1010 // Emit the record into the table.1011 emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoMap, OS);1012 }1013 1014 OS << " }, {\n";1015 1016 // Emit all of the operand info records.1017 Timer.startTimer("Emit operand info");1018 EmitOperandInfo(OS, OperandInfoList);1019 1020 OS << " }, {\n";1021 1022 // Emit all of the instruction's implicit uses and defs.1023 Timer.startTimer("Emit uses/defs");1024 for (auto &List : ImplicitLists) {1025 OS << " /* " << EmittedLists[List] << " */";1026 for (auto &Reg : List)1027 OS << ' ' << getQualifiedName(Reg) << ',';1028 OS << '\n';1029 }1030 1031 OS << " }\n};\n\n";1032 1033 // Emit the array of instruction names.1034 Timer.startTimer("Emit instruction names");1035 InstrNames.layout();1036 InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") +1037 TargetName + "InstrNameData[]");1038 OS << "extern const unsigned " << TargetName << "InstrNameIndices[] = {";1039 Num = 0;1040 for (const CodeGenInstruction *Inst : NumberedInstructions) {1041 // Newline every eight entries.1042 if (Num % 8 == 0)1043 OS << "\n ";1044 OS << InstrNames.get(Inst->getName()) << "U, ";1045 ++Num;1046 }1047 OS << "\n};\n\n";1048 1049 if (HasDeprecationFeatures) {1050 OS << "extern const uint8_t " << TargetName1051 << "InstrDeprecationFeatures[] = {";1052 Num = 0;1053 for (const CodeGenInstruction *Inst : NumberedInstructions) {1054 if (Num % 8 == 0)1055 OS << "\n ";1056 if (!Inst->HasComplexDeprecationPredicate &&1057 !Inst->DeprecatedReason.empty())1058 OS << Target.getInstNamespace() << "::" << Inst->DeprecatedReason1059 << ", ";1060 else1061 OS << "uint8_t(-1), ";1062 ++Num;1063 }1064 OS << "\n};\n\n";1065 }1066 1067 if (HasComplexDeprecationInfos) {1068 OS << "extern const MCInstrInfo::ComplexDeprecationPredicate "1069 << TargetName << "InstrComplexDeprecationInfos[] = {";1070 Num = 0;1071 for (const CodeGenInstruction *Inst : NumberedInstructions) {1072 if (Num % 8 == 0)1073 OS << "\n ";1074 if (Inst->HasComplexDeprecationPredicate)1075 // Emit a function pointer to the complex predicate method.1076 OS << "&get" << Inst->DeprecatedReason << "DeprecationInfo, ";1077 else1078 OS << "nullptr, ";1079 ++Num;1080 }1081 OS << "\n};\n\n";1082 }1083 1084 // MCInstrInfo initialization routine.1085 Timer.startTimer("Emit initialization routine");1086 1087 if (NumClassesByHwMode != 0) {1088 OS << "extern const int16_t " << TargetName << "RegClassByHwModeTables["1089 << NumModes << "][" << NumClassesByHwMode << "] = {\n";1090 1091 for (unsigned M = 0; M < NumModes; ++M) {1092 OS << " { // " << CGH.getModeName(M, /*IncludeDefault=*/true) << '\n';1093 for (unsigned I = 0; I != NumClassesByHwMode; ++I) {1094 const Record *Class = RegClassByHwMode[I];1095 const HwModeSelect &ModeSelect = CGH.getHwModeSelect(Class);1096 1097 auto FoundMode =1098 find_if(ModeSelect.Items, [=](const HwModeSelect::PairType P) {1099 return P.first == M;1100 });1101 1102 if (FoundMode == ModeSelect.Items.end()) {1103 // If a RegClassByHwMode doesn't have an entry corresponding to a1104 // mode, pad with default register class.1105 OS << indent(4) << "-1, // Missing mode entry\n";1106 } else {1107 const CodeGenRegisterClass *RegClass =1108 RegBank.getRegClass(FoundMode->second);1109 OS << indent(4) << RegClass->getQualifiedIdName() << ",\n";1110 }1111 }1112 1113 OS << " },\n";1114 }1115 1116 OS << "};\n\n";1117 }1118 1119 OS << "static inline void Init" << TargetName1120 << "MCInstrInfo(MCInstrInfo *II) {\n";1121 OS << " II->InitMCInstrInfo(" << TargetName << "Descs.Insts, "1122 << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, ";1123 if (HasDeprecationFeatures)1124 OS << TargetName << "InstrDeprecationFeatures, ";1125 else1126 OS << "nullptr, ";1127 if (HasComplexDeprecationInfos)1128 OS << TargetName << "InstrComplexDeprecationInfos, ";1129 else1130 OS << "nullptr, ";1131 OS << NumberedInstructions.size() << ", ";1132 1133 if (NumClassesByHwMode != 0) {1134 OS << '&' << TargetName << "RegClassByHwModeTables[0][0], "1135 << NumClassesByHwMode;1136 } else1137 OS << "nullptr, 0";1138 1139 OS << ");\n}\n\n";1140 } // end GET_INSTRINFO_MC_DESC scope.1141 1142 {1143 // Create a TargetInstrInfo subclass to hide the MC layer initialization.1144 IfDefEmitter IfDef(OS, "GET_INSTRINFO_HEADER");1145 {1146 NamespaceEmitter LlvmNS(OS, "llvm");1147 Twine ClassName = TargetName + "GenInstrInfo";1148 OS << "struct " << ClassName << " : public TargetInstrInfo {\n"1149 << " explicit " << ClassName1150 << "(const TargetSubtargetInfo &STI, const TargetRegisterInfo &TRI, "1151 "unsigned CFSetupOpcode = ~0u, "1152 "unsigned CFDestroyOpcode = ~0u, "1153 "unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u);\n"1154 << " ~" << ClassName << "() override = default;\n"1155 << "};\n";1156 } // end llvm namespace.1157 1158 OS << "\n";1159 NamespaceEmitter InstNS(OS, ("llvm::" + Target.getInstNamespace()).str());1160 for (const Record *R : Records.getAllDerivedDefinitions("Operand")) {1161 if (R->isAnonymous())1162 continue;1163 const DagInit *D = R->getValueAsDag("MIOperandInfo");1164 if (!D)1165 continue;1166 for (const auto &[Idx, Name] : enumerate(D->getArgNames())) {1167 if (Name)1168 OS << "constexpr unsigned SUBOP_" << R->getName() << "_"1169 << Name->getValue() << " = " << Idx << ";\n";1170 }1171 }1172 } // end GET_INSTRINFO_HEADER scope.1173 1174 {1175 IfDefEmitter IfDef(OS, "GET_INSTRINFO_HELPER_DECLS");1176 emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ false);1177 }1178 1179 {1180 IfDefEmitter IfDef(OS, "GET_INSTRINFO_HELPERS");1181 emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ true);1182 }1183 1184 {1185 IfDefEmitter IfDef(OS, "GET_INSTRINFO_CTOR_DTOR");1186 NamespaceEmitter LlvmNS(OS, "llvm");1187 OS << "extern const " << TargetName << "InstrTable " << TargetName1188 << "Descs;\n";1189 OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";1190 OS << "extern const char " << TargetName << "InstrNameData[];\n";1191 1192 if (NumClassesByHwMode != 0) {1193 OS << "extern const int16_t " << TargetName << "RegClassByHwModeTables["1194 << NumModes << "][" << NumClassesByHwMode << "];\n";1195 }1196 1197 if (HasDeprecationFeatures)1198 OS << "extern const uint8_t " << TargetName1199 << "InstrDeprecationFeatures[];\n";1200 if (HasComplexDeprecationInfos)1201 OS << "extern const MCInstrInfo::ComplexDeprecationPredicate "1202 << TargetName << "InstrComplexDeprecationInfos[];\n";1203 Twine ClassName = TargetName + "GenInstrInfo";1204 OS << ClassName << "::" << ClassName1205 << "(const TargetSubtargetInfo &STI, const TargetRegisterInfo &TRI, "1206 "unsigned CFSetupOpcode, unsigned "1207 "CFDestroyOpcode, unsigned CatchRetOpcode, unsigned ReturnOpcode)\n"1208 << " : TargetInstrInfo(TRI, CFSetupOpcode, CFDestroyOpcode, "1209 "CatchRetOpcode, "1210 "ReturnOpcode";1211 if (NumClassesByHwMode != 0)1212 OS << ", " << TargetName1213 << "RegClassByHwModeTables[STI.getHwMode(MCSubtargetInfo::HwMode_"1214 "RegInfo)]";1215 1216 OS << ") {\n"1217 << " InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName1218 << "InstrNameIndices, " << TargetName << "InstrNameData, ";1219 if (HasDeprecationFeatures)1220 OS << TargetName << "InstrDeprecationFeatures, ";1221 else1222 OS << "nullptr, ";1223 if (HasComplexDeprecationInfos)1224 OS << TargetName << "InstrComplexDeprecationInfos, ";1225 else1226 OS << "nullptr, ";1227 OS << NumberedInstructions.size();1228 1229 if (NumClassesByHwMode != 0) {1230 OS << ", &" << TargetName << "RegClassByHwModeTables[0][0], "1231 << NumClassesByHwMode;1232 }1233 1234 OS << ");\n"1235 "}\n";1236 } // end GET_INSTRINFO_CTOR_DTOR scope.1237 1238 ArrayRef<const CodeGenInstruction *> TargetInstructions =1239 Target.getTargetInstructions();1240 1241 if (HasUseNamedOperandTable) {1242 Timer.startTimer("Emit operand name mappings");1243 emitOperandNameMappings(OS, Target, TargetInstructions);1244 }1245 1246 Timer.startTimer("Emit operand type mappings");1247 emitOperandTypeMappings(OS, Target, NumberedInstructions);1248 1249 if (HasUseLogicalOperandMappings) {1250 Timer.startTimer("Emit logical operand size mappings");1251 emitLogicalOperandSizeMappings(OS, TargetName, TargetInstructions);1252 }1253 1254 Timer.startTimer("Emit helper methods");1255 emitMCIIHelperMethods(OS, TargetName);1256 1257 Timer.startTimer("Emit verifier methods");1258 emitFeatureVerifier(OS, Target);1259 1260 Timer.startTimer("Emit map table");1261 EmitMapTable(Records, OS);1262}1263 1264void InstrInfoEmitter::emitRecord(1265 const CodeGenInstruction &Inst, unsigned Num, const Record *InstrInfo,1266 std::map<std::vector<const Record *>, unsigned> &EmittedLists,1267 const OperandInfoMapTy &OperandInfoMap, raw_ostream &OS) {1268 int MinOperands = 0;1269 if (!Inst.Operands.empty())1270 // Each logical operand can be multiple MI operands.1271 MinOperands =1272 Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands;1273 // Even the logical output operand may be multiple MI operands.1274 int DefOperands = 0;1275 if (Inst.Operands.NumDefs) {1276 auto &Opnd = Inst.Operands[Inst.Operands.NumDefs - 1];1277 DefOperands = Opnd.MIOperandNo + Opnd.MINumOperands;1278 }1279 1280 OS << " { ";1281 OS << Num << ",\t" << MinOperands << ",\t" << DefOperands << ",\t"1282 << Inst.TheDef->getValueAsInt("Size") << ",\t"1283 << SchedModels.getSchedClassIdx(Inst) << ",\t";1284 1285 const CodeGenTarget &Target = CDP.getTargetInfo();1286 1287 // Emit the implicit use/def list...1288 OS << Inst.ImplicitUses.size() << ",\t" << Inst.ImplicitDefs.size() << ",\t";1289 std::vector<const Record *> ImplicitOps = Inst.ImplicitUses;1290 llvm::append_range(ImplicitOps, Inst.ImplicitDefs);1291 1292 // Emit the operand info offset.1293 OperandInfoTy OperandInfo = GetOperandInfo(Inst);1294 OS << OperandInfoMap.find(OperandInfo)->second << ",\t";1295 1296 // Emit implicit operand base.1297 OS << Target.getName() << "ImpOpBase + " << EmittedLists[ImplicitOps]1298 << ",\t0";1299 1300 // Emit all of the target independent flags...1301 if (Inst.isPreISelOpcode)1302 OS << "|(1ULL<<MCID::PreISelOpcode)";1303 if (Inst.isPseudo)1304 OS << "|(1ULL<<MCID::Pseudo)";1305 if (Inst.isMeta)1306 OS << "|(1ULL<<MCID::Meta)";1307 if (Inst.isReturn)1308 OS << "|(1ULL<<MCID::Return)";1309 if (Inst.isEHScopeReturn)1310 OS << "|(1ULL<<MCID::EHScopeReturn)";1311 if (Inst.isBranch)1312 OS << "|(1ULL<<MCID::Branch)";1313 if (Inst.isIndirectBranch)1314 OS << "|(1ULL<<MCID::IndirectBranch)";1315 if (Inst.isCompare)1316 OS << "|(1ULL<<MCID::Compare)";1317 if (Inst.isMoveImm)1318 OS << "|(1ULL<<MCID::MoveImm)";1319 if (Inst.isMoveReg)1320 OS << "|(1ULL<<MCID::MoveReg)";1321 if (Inst.isBitcast)1322 OS << "|(1ULL<<MCID::Bitcast)";1323 if (Inst.isAdd)1324 OS << "|(1ULL<<MCID::Add)";1325 if (Inst.isTrap)1326 OS << "|(1ULL<<MCID::Trap)";1327 if (Inst.isSelect)1328 OS << "|(1ULL<<MCID::Select)";1329 if (Inst.isBarrier)1330 OS << "|(1ULL<<MCID::Barrier)";1331 if (Inst.hasDelaySlot)1332 OS << "|(1ULL<<MCID::DelaySlot)";1333 if (Inst.isCall)1334 OS << "|(1ULL<<MCID::Call)";1335 if (Inst.canFoldAsLoad)1336 OS << "|(1ULL<<MCID::FoldableAsLoad)";1337 if (Inst.mayLoad)1338 OS << "|(1ULL<<MCID::MayLoad)";1339 if (Inst.mayStore)1340 OS << "|(1ULL<<MCID::MayStore)";1341 if (Inst.mayRaiseFPException)1342 OS << "|(1ULL<<MCID::MayRaiseFPException)";1343 if (Inst.isPredicable)1344 OS << "|(1ULL<<MCID::Predicable)";1345 if (Inst.isConvertibleToThreeAddress)1346 OS << "|(1ULL<<MCID::ConvertibleTo3Addr)";1347 if (Inst.isCommutable)1348 OS << "|(1ULL<<MCID::Commutable)";1349 if (Inst.isTerminator)1350 OS << "|(1ULL<<MCID::Terminator)";1351 if (Inst.isReMaterializable)1352 OS << "|(1ULL<<MCID::Rematerializable)";1353 if (Inst.isNotDuplicable)1354 OS << "|(1ULL<<MCID::NotDuplicable)";1355 if (Inst.Operands.hasOptionalDef)1356 OS << "|(1ULL<<MCID::HasOptionalDef)";1357 if (Inst.usesCustomInserter)1358 OS << "|(1ULL<<MCID::UsesCustomInserter)";1359 if (Inst.hasPostISelHook)1360 OS << "|(1ULL<<MCID::HasPostISelHook)";1361 if (Inst.Operands.isVariadic)1362 OS << "|(1ULL<<MCID::Variadic)";1363 if (Inst.hasSideEffects)1364 OS << "|(1ULL<<MCID::UnmodeledSideEffects)";1365 if (Inst.isAsCheapAsAMove)1366 OS << "|(1ULL<<MCID::CheapAsAMove)";1367 if (!Target.getAllowRegisterRenaming() || Inst.hasExtraSrcRegAllocReq)1368 OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)";1369 if (!Target.getAllowRegisterRenaming() || Inst.hasExtraDefRegAllocReq)1370 OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)";1371 if (Inst.isRegSequence)1372 OS << "|(1ULL<<MCID::RegSequence)";1373 if (Inst.isExtractSubreg)1374 OS << "|(1ULL<<MCID::ExtractSubreg)";1375 if (Inst.isInsertSubreg)1376 OS << "|(1ULL<<MCID::InsertSubreg)";1377 if (Inst.isConvergent)1378 OS << "|(1ULL<<MCID::Convergent)";1379 if (Inst.variadicOpsAreDefs)1380 OS << "|(1ULL<<MCID::VariadicOpsAreDefs)";1381 if (Inst.isAuthenticated)1382 OS << "|(1ULL<<MCID::Authenticated)";1383 1384 // Emit all of the target-specific flags...1385 const BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");1386 if (!TSF)1387 PrintFatalError(Inst.TheDef->getLoc(), "no TSFlags?");1388 std::optional<uint64_t> Value = TSF->convertInitializerToInt();1389 if (!Value)1390 PrintFatalError(Inst.TheDef, "Invalid TSFlags bit in " + Inst.getName());1391 1392 OS << ", 0x";1393 OS.write_hex(*Value);1394 OS << "ULL";1395 1396 OS << " }, // " << Inst.getName() << '\n';1397}1398 1399// emitEnums - Print out enum values for all of the instructions.1400void InstrInfoEmitter::emitEnums(1401 raw_ostream &OS,1402 ArrayRef<const CodeGenInstruction *> NumberedInstructions) {1403 1404 const CodeGenTarget &Target = CDP.getTargetInfo();1405 StringRef Namespace = Target.getInstNamespace();1406 1407 if (Namespace.empty())1408 PrintFatalError("No instructions defined!");1409 1410 {1411 IfDefEmitter IfDef(OS, "GET_INSTRINFO_ENUM");1412 NamespaceEmitter NS(OS, ("llvm::" + Namespace).str());1413 1414 auto II = llvm::max_element(1415 NumberedInstructions,1416 [](const CodeGenInstruction *InstA, const CodeGenInstruction *InstB) {1417 return InstA->getName().size() < InstB->getName().size();1418 });1419 size_t MaxNameSize = (*II)->getName().size();1420 1421 OS << " enum {\n";1422 for (const CodeGenInstruction *Inst : NumberedInstructions) {1423 OS << " " << left_justify(Inst->getName(), MaxNameSize) << " = "1424 << Target.getInstrIntValue(Inst->TheDef) << ", // "1425 << SrcMgr.getFormattedLocationNoOffset(Inst->TheDef->getLoc().front())1426 << '\n';1427 }1428 OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << '\n';1429 OS << " };\n";1430 1431 ArrayRef<const Record *> RegClassesByHwMode =1432 Target.getAllRegClassByHwMode();1433 if (!RegClassesByHwMode.empty()) {1434 OS << " enum RegClassByHwModeUses : uint16_t {\n";1435 for (const Record *ClassByHwMode : RegClassesByHwMode)1436 OS << indent(4) << ClassByHwMode->getName() << ",\n";1437 OS << " };\n";1438 }1439 }1440 1441 {1442 IfDefEmitter IfDef(OS, "GET_INSTRINFO_SCHED_ENUM");1443 NamespaceEmitter NS(OS, ("llvm::" + Namespace + "::Sched").str());1444 1445 OS << " enum {\n";1446 auto ExplictClasses = SchedModels.explicitSchedClasses();1447 for (const auto &[Idx, Class] : enumerate(ExplictClasses))1448 OS << " " << Class.Name << "\t= " << Idx << ",\n";1449 OS << " SCHED_LIST_END = " << ExplictClasses.size() << '\n';1450 OS << " };\n";1451 }1452}1453 1454static TableGen::Emitter::OptClass<InstrInfoEmitter>1455 X("gen-instr-info", "Generate instruction descriptions");1456