brintos

brintos / llvm-project-archived public Read only

0
0
Text · 52.6 KiB · 9cd6ad2 Raw
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