xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/InstrInfoEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This tablegen backend is responsible for emitting a description of the target
100b57cec5SDimitry Andric // instruction set for the code generator.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
14*0fca6ea1SDimitry Andric #include "Basic/SequenceToOffsetTable.h"
15*0fca6ea1SDimitry Andric #include "Common/CodeGenDAGPatterns.h"
16*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h"
17*0fca6ea1SDimitry Andric #include "Common/CodeGenSchedule.h"
18*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h"
19*0fca6ea1SDimitry Andric #include "Common/PredicateExpander.h"
20*0fca6ea1SDimitry Andric #include "Common/SubtargetFeatureInfo.h"
21*0fca6ea1SDimitry Andric #include "Common/Types.h"
220b57cec5SDimitry Andric #include "TableGenBackends.h"
230b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
24fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h"
255f757f3fSDimitry Andric #include "llvm/ADT/SmallVector.h"
260b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
270b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric #include "llvm/TableGen/Error.h"
300b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
310b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
320b57cec5SDimitry Andric #include <cassert>
330b57cec5SDimitry Andric #include <cstdint>
34fe6060f1SDimitry Andric #include <iterator>
350b57cec5SDimitry Andric #include <map>
360b57cec5SDimitry Andric #include <string>
370b57cec5SDimitry Andric #include <utility>
380b57cec5SDimitry Andric #include <vector>
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using namespace llvm;
410b57cec5SDimitry Andric 
4281ad6265SDimitry Andric cl::OptionCategory InstrInfoEmitterCat("Options for -gen-instr-info");
4381ad6265SDimitry Andric static cl::opt<bool> ExpandMIOperandInfo(
4481ad6265SDimitry Andric     "instr-info-expand-mi-operand-info",
4581ad6265SDimitry Andric     cl::desc("Expand operand's MIOperandInfo DAG into suboperands"),
4681ad6265SDimitry Andric     cl::cat(InstrInfoEmitterCat), cl::init(true));
4781ad6265SDimitry Andric 
480b57cec5SDimitry Andric namespace {
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric class InstrInfoEmitter {
510b57cec5SDimitry Andric   RecordKeeper &Records;
520b57cec5SDimitry Andric   CodeGenDAGPatterns CDP;
530b57cec5SDimitry Andric   const CodeGenSchedModels &SchedModels;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric public:
InstrInfoEmitter(RecordKeeper & R)56*0fca6ea1SDimitry Andric   InstrInfoEmitter(RecordKeeper &R)
57*0fca6ea1SDimitry Andric       : Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {}
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   // run - Output the instruction set description.
600b57cec5SDimitry Andric   void run(raw_ostream &OS);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric private:
630b57cec5SDimitry Andric   void emitEnums(raw_ostream &OS);
640b57cec5SDimitry Andric 
6506c3fb27SDimitry Andric   typedef std::vector<std::string> OperandInfoTy;
6606c3fb27SDimitry Andric   typedef std::vector<OperandInfoTy> OperandInfoListTy;
6706c3fb27SDimitry Andric   typedef std::map<OperandInfoTy, unsigned> OperandInfoMapTy;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   /// The keys of this map are maps which have OpName enum values as their keys
700b57cec5SDimitry Andric   /// and instruction operand indices as their values.  The values of this map
710b57cec5SDimitry Andric   /// are lists of instruction names.
72*0fca6ea1SDimitry Andric   typedef std::map<std::map<unsigned, unsigned>, std::vector<std::string>>
73*0fca6ea1SDimitry Andric       OpNameMapTy;
740b57cec5SDimitry Andric   typedef std::map<std::string, unsigned>::iterator StrUintMapIter;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   /// Generate member functions in the target-specific GenInstrInfo class.
770b57cec5SDimitry Andric   ///
780b57cec5SDimitry Andric   /// This method is used to custom expand TIIPredicate definitions.
790b57cec5SDimitry Andric   /// See file llvm/Target/TargetInstPredicates.td for a description of what is
800b57cec5SDimitry Andric   /// a TIIPredicate and how to use it.
810b57cec5SDimitry Andric   void emitTIIHelperMethods(raw_ostream &OS, StringRef TargetName,
820b57cec5SDimitry Andric                             bool ExpandDefinition = true);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   /// Expand TIIPredicate definitions to functions that accept a const MCInst
850b57cec5SDimitry Andric   /// reference.
860b57cec5SDimitry Andric   void emitMCIIHelperMethods(raw_ostream &OS, StringRef TargetName);
87753f127fSDimitry Andric 
88753f127fSDimitry Andric   /// Write verifyInstructionPredicates methods.
89753f127fSDimitry Andric   void emitFeatureVerifier(raw_ostream &OS, const CodeGenTarget &Target);
900b57cec5SDimitry Andric   void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
910b57cec5SDimitry Andric                   Record *InstrInfo,
920b57cec5SDimitry Andric                   std::map<std::vector<Record *>, unsigned> &EL,
9306c3fb27SDimitry Andric                   const OperandInfoMapTy &OperandInfo, raw_ostream &OS);
940b57cec5SDimitry Andric   void emitOperandTypeMappings(
950b57cec5SDimitry Andric       raw_ostream &OS, const CodeGenTarget &Target,
960b57cec5SDimitry Andric       ArrayRef<const CodeGenInstruction *> NumberedInstructions);
97*0fca6ea1SDimitry Andric   void
98*0fca6ea1SDimitry Andric   initOperandMapData(ArrayRef<const CodeGenInstruction *> NumberedInstructions,
990b57cec5SDimitry Andric                      StringRef Namespace,
1000b57cec5SDimitry Andric                      std::map<std::string, unsigned> &Operands,
1010b57cec5SDimitry Andric                      OpNameMapTy &OperandMap);
102*0fca6ea1SDimitry Andric   void emitOperandNameMappings(
103*0fca6ea1SDimitry Andric       raw_ostream &OS, const CodeGenTarget &Target,
1040b57cec5SDimitry Andric       ArrayRef<const CodeGenInstruction *> NumberedInstructions);
1050b57cec5SDimitry Andric 
106fe6060f1SDimitry Andric   void emitLogicalOperandSizeMappings(
107fe6060f1SDimitry Andric       raw_ostream &OS, StringRef Namespace,
108fe6060f1SDimitry Andric       ArrayRef<const CodeGenInstruction *> NumberedInstructions);
109fe6060f1SDimitry Andric   void emitLogicalOperandTypeMappings(
110fe6060f1SDimitry Andric       raw_ostream &OS, StringRef Namespace,
111fe6060f1SDimitry Andric       ArrayRef<const CodeGenInstruction *> NumberedInstructions);
112fe6060f1SDimitry Andric 
1130b57cec5SDimitry Andric   // Operand information.
11406c3fb27SDimitry Andric   unsigned CollectOperandInfo(OperandInfoListTy &OperandInfoList,
11506c3fb27SDimitry Andric                               OperandInfoMapTy &OperandInfoMap);
11606c3fb27SDimitry Andric   void EmitOperandInfo(raw_ostream &OS, OperandInfoListTy &OperandInfoList);
11706c3fb27SDimitry Andric   OperandInfoTy GetOperandInfo(const CodeGenInstruction &Inst);
1180b57cec5SDimitry Andric };
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric } // end anonymous namespace
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1230b57cec5SDimitry Andric // Operand Info Emission.
1240b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1250b57cec5SDimitry Andric 
12606c3fb27SDimitry Andric InstrInfoEmitter::OperandInfoTy
GetOperandInfo(const CodeGenInstruction & Inst)1270b57cec5SDimitry Andric InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
12806c3fb27SDimitry Andric   OperandInfoTy Result;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   for (auto &Op : Inst.Operands) {
1310b57cec5SDimitry Andric     // Handle aggregate operands and normal operands the same way by expanding
1320b57cec5SDimitry Andric     // either case into a list of operands for this op.
1330b57cec5SDimitry Andric     std::vector<CGIOperandList::OperandInfo> OperandList;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric     // This might be a multiple operand thing.  Targets like X86 have
1360b57cec5SDimitry Andric     // registers in their multi-operand operands.  It may also be an anonymous
1370b57cec5SDimitry Andric     // operand, which has a single operand, but no declared class for the
1380b57cec5SDimitry Andric     // operand.
1390b57cec5SDimitry Andric     DagInit *MIOI = Op.MIOperandInfo;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric     if (!MIOI || MIOI->getNumArgs() == 0) {
1420b57cec5SDimitry Andric       // Single, anonymous, operand.
1430b57cec5SDimitry Andric       OperandList.push_back(Op);
1440b57cec5SDimitry Andric     } else {
1450b57cec5SDimitry Andric       for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {
1460b57cec5SDimitry Andric         OperandList.push_back(Op);
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric         auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef();
1490b57cec5SDimitry Andric         OperandList.back().Rec = OpR;
1500b57cec5SDimitry Andric       }
1510b57cec5SDimitry Andric     }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric     for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
1540b57cec5SDimitry Andric       Record *OpR = OperandList[j].Rec;
1550b57cec5SDimitry Andric       std::string Res;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric       if (OpR->isSubClassOf("RegisterOperand"))
1580b57cec5SDimitry Andric         OpR = OpR->getValueAsDef("RegClass");
1590b57cec5SDimitry Andric       if (OpR->isSubClassOf("RegisterClass"))
1600b57cec5SDimitry Andric         Res += getQualifiedName(OpR) + "RegClassID, ";
1610b57cec5SDimitry Andric       else if (OpR->isSubClassOf("PointerLikeRegClass"))
1620b57cec5SDimitry Andric         Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";
1630b57cec5SDimitry Andric       else
1640b57cec5SDimitry Andric         // -1 means the operand does not have a fixed register class.
1650b57cec5SDimitry Andric         Res += "-1, ";
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric       // Fill in applicable flags.
1680b57cec5SDimitry Andric       Res += "0";
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric       // Ptr value whose register class is resolved via callback.
1710b57cec5SDimitry Andric       if (OpR->isSubClassOf("PointerLikeRegClass"))
1720b57cec5SDimitry Andric         Res += "|(1<<MCOI::LookupPtrRegClass)";
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric       // Predicate operands.  Check to see if the original unexpanded operand
1750b57cec5SDimitry Andric       // was of type PredicateOp.
1760b57cec5SDimitry Andric       if (Op.Rec->isSubClassOf("PredicateOp"))
1770b57cec5SDimitry Andric         Res += "|(1<<MCOI::Predicate)";
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric       // Optional def operands.  Check to see if the original unexpanded operand
1800b57cec5SDimitry Andric       // was of type OptionalDefOperand.
1810b57cec5SDimitry Andric       if (Op.Rec->isSubClassOf("OptionalDefOperand"))
1820b57cec5SDimitry Andric         Res += "|(1<<MCOI::OptionalDef)";
1830b57cec5SDimitry Andric 
184480093f4SDimitry Andric       // Branch target operands.  Check to see if the original unexpanded
185480093f4SDimitry Andric       // operand was of type BranchTargetOperand.
186480093f4SDimitry Andric       if (Op.Rec->isSubClassOf("BranchTargetOperand"))
187480093f4SDimitry Andric         Res += "|(1<<MCOI::BranchTarget)";
188480093f4SDimitry Andric 
1890b57cec5SDimitry Andric       // Fill in operand type.
1900b57cec5SDimitry Andric       Res += ", ";
1910b57cec5SDimitry Andric       assert(!Op.OperandType.empty() && "Invalid operand type.");
1920b57cec5SDimitry Andric       Res += Op.OperandType;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric       // Fill in constraint info.
1950b57cec5SDimitry Andric       Res += ", ";
1960b57cec5SDimitry Andric 
197*0fca6ea1SDimitry Andric       const CGIOperandList::ConstraintInfo &Constraint = Op.Constraints[j];
1980b57cec5SDimitry Andric       if (Constraint.isNone())
1990b57cec5SDimitry Andric         Res += "0";
2000b57cec5SDimitry Andric       else if (Constraint.isEarlyClobber())
201e8d8bef9SDimitry Andric         Res += "MCOI_EARLY_CLOBBER";
2020b57cec5SDimitry Andric       else {
2030b57cec5SDimitry Andric         assert(Constraint.isTied());
204e8d8bef9SDimitry Andric         Res += "MCOI_TIED_TO(" + utostr(Constraint.getTiedOperand()) + ")";
2050b57cec5SDimitry Andric       }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric       Result.push_back(Res);
2080b57cec5SDimitry Andric     }
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   return Result;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
21406c3fb27SDimitry Andric unsigned
CollectOperandInfo(OperandInfoListTy & OperandInfoList,OperandInfoMapTy & OperandInfoMap)21506c3fb27SDimitry Andric InstrInfoEmitter::CollectOperandInfo(OperandInfoListTy &OperandInfoList,
21606c3fb27SDimitry Andric                                      OperandInfoMapTy &OperandInfoMap) {
2170b57cec5SDimitry Andric   const CodeGenTarget &Target = CDP.getTargetInfo();
21806c3fb27SDimitry Andric   unsigned Offset = 0;
2190b57cec5SDimitry Andric   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
22006c3fb27SDimitry Andric     OperandInfoTy OperandInfo = GetOperandInfo(*Inst);
22106c3fb27SDimitry Andric     if (OperandInfoMap.insert({OperandInfo, Offset}).second) {
22206c3fb27SDimitry Andric       OperandInfoList.push_back(OperandInfo);
22306c3fb27SDimitry Andric       Offset += OperandInfo.size();
22406c3fb27SDimitry Andric     }
22506c3fb27SDimitry Andric   }
22606c3fb27SDimitry Andric   return Offset;
22706c3fb27SDimitry Andric }
2280b57cec5SDimitry Andric 
EmitOperandInfo(raw_ostream & OS,OperandInfoListTy & OperandInfoList)22906c3fb27SDimitry Andric void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
23006c3fb27SDimitry Andric                                        OperandInfoListTy &OperandInfoList) {
23106c3fb27SDimitry Andric   unsigned Offset = 0;
23206c3fb27SDimitry Andric   for (auto &OperandInfo : OperandInfoList) {
23306c3fb27SDimitry Andric     OS << "    /* " << Offset << " */";
23406c3fb27SDimitry Andric     for (auto &Info : OperandInfo)
2350b57cec5SDimitry Andric       OS << " { " << Info << " },";
23606c3fb27SDimitry Andric     OS << '\n';
23706c3fb27SDimitry Andric     Offset += OperandInfo.size();
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric /// Initialize data structures for generating operand name mappings.
2420b57cec5SDimitry Andric ///
2430b57cec5SDimitry Andric /// \param Operands [out] A map used to generate the OpName enum with operand
2440b57cec5SDimitry Andric ///        names as its keys and operand enum values as its values.
2450b57cec5SDimitry Andric /// \param OperandMap [out] A map for representing the operand name mappings for
2460b57cec5SDimitry Andric ///        each instructions.  This is used to generate the OperandMap table as
2470b57cec5SDimitry Andric ///        well as the getNamedOperandIdx() function.
initOperandMapData(ArrayRef<const CodeGenInstruction * > NumberedInstructions,StringRef Namespace,std::map<std::string,unsigned> & Operands,OpNameMapTy & OperandMap)2480b57cec5SDimitry Andric void InstrInfoEmitter::initOperandMapData(
2490b57cec5SDimitry Andric     ArrayRef<const CodeGenInstruction *> NumberedInstructions,
250*0fca6ea1SDimitry Andric     StringRef Namespace, std::map<std::string, unsigned> &Operands,
2510b57cec5SDimitry Andric     OpNameMapTy &OperandMap) {
2520b57cec5SDimitry Andric   unsigned NumOperands = 0;
2530b57cec5SDimitry Andric   for (const CodeGenInstruction *Inst : NumberedInstructions) {
2540b57cec5SDimitry Andric     if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
2550b57cec5SDimitry Andric       continue;
2560b57cec5SDimitry Andric     std::map<unsigned, unsigned> OpList;
2570b57cec5SDimitry Andric     for (const auto &Info : Inst->Operands) {
2580b57cec5SDimitry Andric       StrUintMapIter I = Operands.find(Info.Name);
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric       if (I == Operands.end()) {
261*0fca6ea1SDimitry Andric         I = Operands.insert(Operands.begin(), std::pair<std::string, unsigned>(
262*0fca6ea1SDimitry Andric                                                   Info.Name, NumOperands++));
2630b57cec5SDimitry Andric       }
2640b57cec5SDimitry Andric       OpList[I->second] = Info.MIOperandNo;
2650b57cec5SDimitry Andric     }
266*0fca6ea1SDimitry Andric     OperandMap[OpList].push_back(Namespace.str() +
267*0fca6ea1SDimitry Andric                                  "::" + Inst->TheDef->getName().str());
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric /// Generate a table and function for looking up the indices of operands by
2720b57cec5SDimitry Andric /// name.
2730b57cec5SDimitry Andric ///
2740b57cec5SDimitry Andric /// This code generates:
2750b57cec5SDimitry Andric /// - An enum in the llvm::TargetNamespace::OpName namespace, with one entry
2760b57cec5SDimitry Andric ///   for each operand name.
2770b57cec5SDimitry Andric /// - A 2-dimensional table called OperandMap for mapping OpName enum values to
2780b57cec5SDimitry Andric ///   operand indices.
2790b57cec5SDimitry Andric /// - A function called getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
2800b57cec5SDimitry Andric ///   for looking up the operand index for an instruction, given a value from
2810b57cec5SDimitry Andric ///   OpName enum
emitOperandNameMappings(raw_ostream & OS,const CodeGenTarget & Target,ArrayRef<const CodeGenInstruction * > NumberedInstructions)282*0fca6ea1SDimitry Andric void InstrInfoEmitter::emitOperandNameMappings(
283*0fca6ea1SDimitry Andric     raw_ostream &OS, const CodeGenTarget &Target,
2840b57cec5SDimitry Andric     ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
2850b57cec5SDimitry Andric   StringRef Namespace = Target.getInstNamespace();
2860b57cec5SDimitry Andric   std::string OpNameNS = "OpName";
2870b57cec5SDimitry Andric   // Map of operand names to their enumeration value.  This will be used to
2880b57cec5SDimitry Andric   // generate the OpName enum.
2890b57cec5SDimitry Andric   std::map<std::string, unsigned> Operands;
2900b57cec5SDimitry Andric   OpNameMapTy OperandMap;
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   initOperandMapData(NumberedInstructions, Namespace, Operands, OperandMap);
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n";
2950b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n";
2960b57cec5SDimitry Andric   OS << "namespace llvm {\n";
2970b57cec5SDimitry Andric   OS << "namespace " << Namespace << " {\n";
2980b57cec5SDimitry Andric   OS << "namespace " << OpNameNS << " {\n";
2990b57cec5SDimitry Andric   OS << "enum {\n";
3000b57cec5SDimitry Andric   for (const auto &Op : Operands)
3010b57cec5SDimitry Andric     OS << "  " << Op.first << " = " << Op.second << ",\n";
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   OS << "  OPERAND_LAST";
3040b57cec5SDimitry Andric   OS << "\n};\n";
3050b57cec5SDimitry Andric   OS << "} // end namespace OpName\n";
3060b57cec5SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
3070b57cec5SDimitry Andric   OS << "} // end namespace llvm\n";
3080b57cec5SDimitry Andric   OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n";
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n";
3110b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_NAMED_OPS\n";
3120b57cec5SDimitry Andric   OS << "namespace llvm {\n";
3130b57cec5SDimitry Andric   OS << "namespace " << Namespace << " {\n";
3140b57cec5SDimitry Andric   OS << "LLVM_READONLY\n";
3150b57cec5SDimitry Andric   OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n";
3160b57cec5SDimitry Andric   if (!Operands.empty()) {
3170b57cec5SDimitry Andric     OS << "  static const int16_t OperandMap [][" << Operands.size()
3180b57cec5SDimitry Andric        << "] = {\n";
3190b57cec5SDimitry Andric     for (const auto &Entry : OperandMap) {
3200b57cec5SDimitry Andric       const std::map<unsigned, unsigned> &OpList = Entry.first;
3210b57cec5SDimitry Andric       OS << "{";
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric       // Emit a row of the OperandMap table
3240b57cec5SDimitry Andric       for (unsigned i = 0, e = Operands.size(); i != e; ++i)
3250b57cec5SDimitry Andric         OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", ";
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric       OS << "},\n";
3280b57cec5SDimitry Andric     }
3290b57cec5SDimitry Andric     OS << "};\n";
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric     OS << "  switch(Opcode) {\n";
3320b57cec5SDimitry Andric     unsigned TableIndex = 0;
3330b57cec5SDimitry Andric     for (const auto &Entry : OperandMap) {
3340b57cec5SDimitry Andric       for (const std::string &Name : Entry.second)
3350b57cec5SDimitry Andric         OS << "  case " << Name << ":\n";
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric       OS << "    return OperandMap[" << TableIndex++ << "][NamedIdx];\n";
3380b57cec5SDimitry Andric     }
3390b57cec5SDimitry Andric     OS << "  default: return -1;\n";
3400b57cec5SDimitry Andric     OS << "  }\n";
3410b57cec5SDimitry Andric   } else {
3420b57cec5SDimitry Andric     // There are no operands, so no need to emit anything
3430b57cec5SDimitry Andric     OS << "  return -1;\n";
3440b57cec5SDimitry Andric   }
3450b57cec5SDimitry Andric   OS << "}\n";
3460b57cec5SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
3470b57cec5SDimitry Andric   OS << "} // end namespace llvm\n";
3480b57cec5SDimitry Andric   OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n";
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric /// Generate an enum for all the operand types for this target, under the
3520b57cec5SDimitry Andric /// llvm::TargetNamespace::OpTypes namespace.
3530b57cec5SDimitry Andric /// Operand types are all definitions derived of the Operand Target.td class.
emitOperandTypeMappings(raw_ostream & OS,const CodeGenTarget & Target,ArrayRef<const CodeGenInstruction * > NumberedInstructions)3540b57cec5SDimitry Andric void InstrInfoEmitter::emitOperandTypeMappings(
3550b57cec5SDimitry Andric     raw_ostream &OS, const CodeGenTarget &Target,
3560b57cec5SDimitry Andric     ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   StringRef Namespace = Target.getInstNamespace();
3590b57cec5SDimitry Andric   std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand");
3608bcb0991SDimitry Andric   std::vector<Record *> RegisterOperands =
3618bcb0991SDimitry Andric       Records.getAllDerivedDefinitions("RegisterOperand");
3628bcb0991SDimitry Andric   std::vector<Record *> RegisterClasses =
3638bcb0991SDimitry Andric       Records.getAllDerivedDefinitions("RegisterClass");
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
3660b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
3670b57cec5SDimitry Andric   OS << "namespace llvm {\n";
3680b57cec5SDimitry Andric   OS << "namespace " << Namespace << " {\n";
3690b57cec5SDimitry Andric   OS << "namespace OpTypes {\n";
3700b57cec5SDimitry Andric   OS << "enum OperandType {\n";
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   unsigned EnumVal = 0;
3738bcb0991SDimitry Andric   for (const std::vector<Record *> *RecordsToAdd :
3748bcb0991SDimitry Andric        {&Operands, &RegisterOperands, &RegisterClasses}) {
3758bcb0991SDimitry Andric     for (const Record *Op : *RecordsToAdd) {
3760b57cec5SDimitry Andric       if (!Op->isAnonymous())
3770b57cec5SDimitry Andric         OS << "  " << Op->getName() << " = " << EnumVal << ",\n";
3780b57cec5SDimitry Andric       ++EnumVal;
3790b57cec5SDimitry Andric     }
3808bcb0991SDimitry Andric   }
3810b57cec5SDimitry Andric 
382*0fca6ea1SDimitry Andric   OS << "  OPERAND_TYPE_LIST_END"
383*0fca6ea1SDimitry Andric      << "\n};\n";
3840b57cec5SDimitry Andric   OS << "} // end namespace OpTypes\n";
3850b57cec5SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
3860b57cec5SDimitry Andric   OS << "} // end namespace llvm\n";
3870b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n";
3900b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n";
3910b57cec5SDimitry Andric   OS << "namespace llvm {\n";
3920b57cec5SDimitry Andric   OS << "namespace " << Namespace << " {\n";
3930b57cec5SDimitry Andric   OS << "LLVM_READONLY\n";
3948bcb0991SDimitry Andric   OS << "static int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n";
39581ad6265SDimitry Andric   auto getInstrName = [&](int I) -> StringRef {
39681ad6265SDimitry Andric     return NumberedInstructions[I]->TheDef->getName();
39781ad6265SDimitry Andric   };
398e8d8bef9SDimitry Andric   // TODO: Factor out duplicate operand lists to compress the tables.
3990b57cec5SDimitry Andric   if (!NumberedInstructions.empty()) {
4000b57cec5SDimitry Andric     std::vector<int> OperandOffsets;
4010b57cec5SDimitry Andric     std::vector<Record *> OperandRecords;
4020b57cec5SDimitry Andric     int CurrentOffset = 0;
4030b57cec5SDimitry Andric     for (const CodeGenInstruction *Inst : NumberedInstructions) {
4040b57cec5SDimitry Andric       OperandOffsets.push_back(CurrentOffset);
4050b57cec5SDimitry Andric       for (const auto &Op : Inst->Operands) {
4060b57cec5SDimitry Andric         const DagInit *MIOI = Op.MIOperandInfo;
40781ad6265SDimitry Andric         if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) {
4080b57cec5SDimitry Andric           // Single, anonymous, operand.
4090b57cec5SDimitry Andric           OperandRecords.push_back(Op.Rec);
4100b57cec5SDimitry Andric           ++CurrentOffset;
4110b57cec5SDimitry Andric         } else {
412e8d8bef9SDimitry Andric           for (Init *Arg : MIOI->getArgs()) {
4130b57cec5SDimitry Andric             OperandRecords.push_back(cast<DefInit>(Arg)->getDef());
4140b57cec5SDimitry Andric             ++CurrentOffset;
4150b57cec5SDimitry Andric           }
4160b57cec5SDimitry Andric         }
4170b57cec5SDimitry Andric       }
4180b57cec5SDimitry Andric     }
4190b57cec5SDimitry Andric 
420e8d8bef9SDimitry Andric     // Emit the table of offsets (indexes) into the operand type table.
421e8d8bef9SDimitry Andric     // Size the unsigned integer offset to save space.
422e8d8bef9SDimitry Andric     assert(OperandRecords.size() <= UINT32_MAX &&
423e8d8bef9SDimitry Andric            "Too many operands for offset table");
42406c3fb27SDimitry Andric     OS << "  static const " << getMinimalTypeForRange(OperandRecords.size());
425e8d8bef9SDimitry Andric     OS << " Offsets[] = {\n";
42681ad6265SDimitry Andric     for (int I = 0, E = OperandOffsets.size(); I != E; ++I) {
42781ad6265SDimitry Andric       OS << "    /* " << getInstrName(I) << " */\n";
4280b57cec5SDimitry Andric       OS << "    " << OperandOffsets[I] << ",\n";
42981ad6265SDimitry Andric     }
4300b57cec5SDimitry Andric     OS << "  };\n";
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric     // Add an entry for the end so that we don't need to special case it below.
4330b57cec5SDimitry Andric     OperandOffsets.push_back(OperandRecords.size());
434e8d8bef9SDimitry Andric 
4350b57cec5SDimitry Andric     // Emit the actual operand types in a flat table.
436e8d8bef9SDimitry Andric     // Size the signed integer operand type to save space.
437e8d8bef9SDimitry Andric     assert(EnumVal <= INT16_MAX &&
438e8d8bef9SDimitry Andric            "Too many operand types for operand types table");
43981ad6265SDimitry Andric     OS << "\n  using namespace OpTypes;\n";
44006c3fb27SDimitry Andric     OS << "  static";
441e8d8bef9SDimitry Andric     OS << ((EnumVal <= INT8_MAX) ? " const int8_t" : " const int16_t");
442e8d8bef9SDimitry Andric     OS << " OpcodeOperandTypes[] = {\n    ";
44381ad6265SDimitry Andric     for (int I = 0, E = OperandRecords.size(), CurOffset = 0; I != E; ++I) {
4440b57cec5SDimitry Andric       // We print each Opcode's operands in its own row.
4450b57cec5SDimitry Andric       if (I == OperandOffsets[CurOffset]) {
44681ad6265SDimitry Andric         OS << "\n    /* " << getInstrName(CurOffset) << " */\n    ";
4470b57cec5SDimitry Andric         while (OperandOffsets[++CurOffset] == I)
44881ad6265SDimitry Andric           OS << "/* " << getInstrName(CurOffset) << " */\n    ";
4490b57cec5SDimitry Andric       }
4500b57cec5SDimitry Andric       Record *OpR = OperandRecords[I];
4518bcb0991SDimitry Andric       if ((OpR->isSubClassOf("Operand") ||
4528bcb0991SDimitry Andric            OpR->isSubClassOf("RegisterOperand") ||
4538bcb0991SDimitry Andric            OpR->isSubClassOf("RegisterClass")) &&
4548bcb0991SDimitry Andric           !OpR->isAnonymous())
45581ad6265SDimitry Andric         OS << OpR->getName();
4560b57cec5SDimitry Andric       else
4570b57cec5SDimitry Andric         OS << -1;
4580b57cec5SDimitry Andric       OS << ", ";
4590b57cec5SDimitry Andric     }
4600b57cec5SDimitry Andric     OS << "\n  };\n";
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     OS << "  return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n";
4630b57cec5SDimitry Andric   } else {
4640b57cec5SDimitry Andric     OS << "  llvm_unreachable(\"No instructions defined\");\n";
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric   OS << "}\n";
4670b57cec5SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
4680b57cec5SDimitry Andric   OS << "} // end namespace llvm\n";
4690b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_OPERAND_TYPE\n\n";
47081ad6265SDimitry Andric 
47181ad6265SDimitry Andric   OS << "#ifdef GET_INSTRINFO_MEM_OPERAND_SIZE\n";
47281ad6265SDimitry Andric   OS << "#undef GET_INSTRINFO_MEM_OPERAND_SIZE\n";
47381ad6265SDimitry Andric   OS << "namespace llvm {\n";
47481ad6265SDimitry Andric   OS << "namespace " << Namespace << " {\n";
47581ad6265SDimitry Andric   OS << "LLVM_READONLY\n";
47681ad6265SDimitry Andric   OS << "static int getMemOperandSize(int OpType) {\n";
47781ad6265SDimitry Andric   OS << "  switch (OpType) {\n";
4785f757f3fSDimitry Andric   std::map<int, SmallVector<StringRef, 0>> SizeToOperandName;
47981ad6265SDimitry Andric   for (const Record *Op : Operands) {
48081ad6265SDimitry Andric     if (!Op->isSubClassOf("X86MemOperand"))
48181ad6265SDimitry Andric       continue;
48281ad6265SDimitry Andric     if (int Size = Op->getValueAsInt("Size"))
48381ad6265SDimitry Andric       SizeToOperandName[Size].push_back(Op->getName());
48481ad6265SDimitry Andric   }
48581ad6265SDimitry Andric   OS << "  default: return 0;\n";
4865f757f3fSDimitry Andric   for (const auto &KV : SizeToOperandName) {
48781ad6265SDimitry Andric     for (const StringRef &OperandName : KV.second)
48881ad6265SDimitry Andric       OS << "  case OpTypes::" << OperandName << ":\n";
48981ad6265SDimitry Andric     OS << "    return " << KV.first << ";\n\n";
49081ad6265SDimitry Andric   }
49181ad6265SDimitry Andric   OS << "  }\n}\n";
49281ad6265SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
49381ad6265SDimitry Andric   OS << "} // end namespace llvm\n";
49481ad6265SDimitry Andric   OS << "#endif // GET_INSTRINFO_MEM_OPERAND_SIZE\n\n";
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric 
emitLogicalOperandSizeMappings(raw_ostream & OS,StringRef Namespace,ArrayRef<const CodeGenInstruction * > NumberedInstructions)497fe6060f1SDimitry Andric void InstrInfoEmitter::emitLogicalOperandSizeMappings(
498fe6060f1SDimitry Andric     raw_ostream &OS, StringRef Namespace,
499fe6060f1SDimitry Andric     ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
500fe6060f1SDimitry Andric   std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap;
501fe6060f1SDimitry Andric 
502fe6060f1SDimitry Andric   std::map<unsigned, std::vector<std::string>> InstMap;
503fe6060f1SDimitry Andric 
504fe6060f1SDimitry Andric   size_t LogicalOpListSize = 0U;
505fe6060f1SDimitry Andric   std::vector<unsigned> LogicalOpList;
506fe6060f1SDimitry Andric   for (const auto *Inst : NumberedInstructions) {
507fe6060f1SDimitry Andric     if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))
508fe6060f1SDimitry Andric       continue;
509fe6060f1SDimitry Andric 
510fe6060f1SDimitry Andric     LogicalOpList.clear();
511fe6060f1SDimitry Andric     llvm::transform(Inst->Operands, std::back_inserter(LogicalOpList),
512fe6060f1SDimitry Andric                     [](const CGIOperandList::OperandInfo &Op) -> unsigned {
513fe6060f1SDimitry Andric                       auto *MIOI = Op.MIOperandInfo;
514fe6060f1SDimitry Andric                       if (!MIOI || MIOI->getNumArgs() == 0)
515fe6060f1SDimitry Andric                         return 1;
516fe6060f1SDimitry Andric                       return MIOI->getNumArgs();
517fe6060f1SDimitry Andric                     });
518fe6060f1SDimitry Andric     LogicalOpListSize = std::max(LogicalOpList.size(), LogicalOpListSize);
519fe6060f1SDimitry Andric 
520fe6060f1SDimitry Andric     auto I =
521fe6060f1SDimitry Andric         LogicalOpSizeMap.insert({LogicalOpList, LogicalOpSizeMap.size()}).first;
522fe6060f1SDimitry Andric     InstMap[I->second].push_back(
523fe6060f1SDimitry Andric         (Namespace + "::" + Inst->TheDef->getName()).str());
524fe6060f1SDimitry Andric   }
525fe6060f1SDimitry Andric 
526fe6060f1SDimitry Andric   OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n";
527fe6060f1SDimitry Andric   OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n";
528fe6060f1SDimitry Andric   OS << "namespace llvm {\n";
529fe6060f1SDimitry Andric   OS << "namespace " << Namespace << " {\n";
530fe6060f1SDimitry Andric   OS << "LLVM_READONLY static unsigned\n";
531fe6060f1SDimitry Andric   OS << "getLogicalOperandSize(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";
532fe6060f1SDimitry Andric   if (!InstMap.empty()) {
533fe6060f1SDimitry Andric     std::vector<const std::vector<unsigned> *> LogicalOpSizeList(
534fe6060f1SDimitry Andric         LogicalOpSizeMap.size());
535fe6060f1SDimitry Andric     for (auto &P : LogicalOpSizeMap) {
536fe6060f1SDimitry Andric       LogicalOpSizeList[P.second] = &P.first;
537fe6060f1SDimitry Andric     }
538fe6060f1SDimitry Andric     OS << "  static const unsigned SizeMap[][" << LogicalOpListSize
539fe6060f1SDimitry Andric        << "] = {\n";
540fe6060f1SDimitry Andric     for (auto &R : LogicalOpSizeList) {
541fe6060f1SDimitry Andric       const auto &Row = *R;
542fe6060f1SDimitry Andric       OS << "   {";
543fe6060f1SDimitry Andric       int i;
544fe6060f1SDimitry Andric       for (i = 0; i < static_cast<int>(Row.size()); ++i) {
545fe6060f1SDimitry Andric         OS << Row[i] << ", ";
546fe6060f1SDimitry Andric       }
547fe6060f1SDimitry Andric       for (; i < static_cast<int>(LogicalOpListSize); ++i) {
548fe6060f1SDimitry Andric         OS << "0, ";
549fe6060f1SDimitry Andric       }
550fe6060f1SDimitry Andric       OS << "}, ";
551fe6060f1SDimitry Andric       OS << "\n";
552fe6060f1SDimitry Andric     }
553fe6060f1SDimitry Andric     OS << "  };\n";
554fe6060f1SDimitry Andric 
555fe6060f1SDimitry Andric     OS << "  switch (Opcode) {\n";
556fe6060f1SDimitry Andric     OS << "  default: return LogicalOpIdx;\n";
557fe6060f1SDimitry Andric     for (auto &P : InstMap) {
558fe6060f1SDimitry Andric       auto OpMapIdx = P.first;
559fe6060f1SDimitry Andric       const auto &Insts = P.second;
560fe6060f1SDimitry Andric       for (const auto &Inst : Insts) {
561fe6060f1SDimitry Andric         OS << "  case " << Inst << ":\n";
562fe6060f1SDimitry Andric       }
563fe6060f1SDimitry Andric       OS << "    return SizeMap[" << OpMapIdx << "][LogicalOpIdx];\n";
564fe6060f1SDimitry Andric     }
565fe6060f1SDimitry Andric     OS << "  }\n";
566fe6060f1SDimitry Andric   } else {
567fe6060f1SDimitry Andric     OS << "  return LogicalOpIdx;\n";
568fe6060f1SDimitry Andric   }
569fe6060f1SDimitry Andric   OS << "}\n";
570fe6060f1SDimitry Andric 
571fe6060f1SDimitry Andric   OS << "LLVM_READONLY static inline unsigned\n";
572fe6060f1SDimitry Andric   OS << "getLogicalOperandIdx(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";
573fe6060f1SDimitry Andric   OS << "  auto S = 0U;\n";
574fe6060f1SDimitry Andric   OS << "  for (auto i = 0U; i < LogicalOpIdx; ++i)\n";
575fe6060f1SDimitry Andric   OS << "    S += getLogicalOperandSize(Opcode, i);\n";
576fe6060f1SDimitry Andric   OS << "  return S;\n";
577fe6060f1SDimitry Andric   OS << "}\n";
578fe6060f1SDimitry Andric 
579fe6060f1SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
580fe6060f1SDimitry Andric   OS << "} // end namespace llvm\n";
581fe6060f1SDimitry Andric   OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n\n";
582fe6060f1SDimitry Andric }
583fe6060f1SDimitry Andric 
emitLogicalOperandTypeMappings(raw_ostream & OS,StringRef Namespace,ArrayRef<const CodeGenInstruction * > NumberedInstructions)584fe6060f1SDimitry Andric void InstrInfoEmitter::emitLogicalOperandTypeMappings(
585fe6060f1SDimitry Andric     raw_ostream &OS, StringRef Namespace,
586fe6060f1SDimitry Andric     ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
587fe6060f1SDimitry Andric   std::map<std::vector<std::string>, unsigned> LogicalOpTypeMap;
588fe6060f1SDimitry Andric 
589fe6060f1SDimitry Andric   std::map<unsigned, std::vector<std::string>> InstMap;
590fe6060f1SDimitry Andric 
591fe6060f1SDimitry Andric   size_t OpTypeListSize = 0U;
592fe6060f1SDimitry Andric   std::vector<std::string> LogicalOpTypeList;
593fe6060f1SDimitry Andric   for (const auto *Inst : NumberedInstructions) {
594fe6060f1SDimitry Andric     if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))
595fe6060f1SDimitry Andric       continue;
596fe6060f1SDimitry Andric 
597fe6060f1SDimitry Andric     LogicalOpTypeList.clear();
598fe6060f1SDimitry Andric     for (const auto &Op : Inst->Operands) {
599fe6060f1SDimitry Andric       auto *OpR = Op.Rec;
600fe6060f1SDimitry Andric       if ((OpR->isSubClassOf("Operand") ||
601fe6060f1SDimitry Andric            OpR->isSubClassOf("RegisterOperand") ||
602fe6060f1SDimitry Andric            OpR->isSubClassOf("RegisterClass")) &&
603fe6060f1SDimitry Andric           !OpR->isAnonymous()) {
604fe6060f1SDimitry Andric         LogicalOpTypeList.push_back(
605fe6060f1SDimitry Andric             (Namespace + "::OpTypes::" + Op.Rec->getName()).str());
606fe6060f1SDimitry Andric       } else {
607fe6060f1SDimitry Andric         LogicalOpTypeList.push_back("-1");
608fe6060f1SDimitry Andric       }
609fe6060f1SDimitry Andric     }
610fe6060f1SDimitry Andric     OpTypeListSize = std::max(LogicalOpTypeList.size(), OpTypeListSize);
611fe6060f1SDimitry Andric 
612fe6060f1SDimitry Andric     auto I =
613fe6060f1SDimitry Andric         LogicalOpTypeMap.insert({LogicalOpTypeList, LogicalOpTypeMap.size()})
614fe6060f1SDimitry Andric             .first;
615fe6060f1SDimitry Andric     InstMap[I->second].push_back(
616fe6060f1SDimitry Andric         (Namespace + "::" + Inst->TheDef->getName()).str());
617fe6060f1SDimitry Andric   }
618fe6060f1SDimitry Andric 
619fe6060f1SDimitry Andric   OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n";
620fe6060f1SDimitry Andric   OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n";
621fe6060f1SDimitry Andric   OS << "namespace llvm {\n";
622fe6060f1SDimitry Andric   OS << "namespace " << Namespace << " {\n";
623fe6060f1SDimitry Andric   OS << "LLVM_READONLY static int\n";
624fe6060f1SDimitry Andric   OS << "getLogicalOperandType(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";
625fe6060f1SDimitry Andric   if (!InstMap.empty()) {
626fe6060f1SDimitry Andric     std::vector<const std::vector<std::string> *> LogicalOpTypeList(
627fe6060f1SDimitry Andric         LogicalOpTypeMap.size());
628fe6060f1SDimitry Andric     for (auto &P : LogicalOpTypeMap) {
629fe6060f1SDimitry Andric       LogicalOpTypeList[P.second] = &P.first;
630fe6060f1SDimitry Andric     }
631fe6060f1SDimitry Andric     OS << "  static const int TypeMap[][" << OpTypeListSize << "] = {\n";
632fe6060f1SDimitry Andric     for (int r = 0, rs = LogicalOpTypeList.size(); r < rs; ++r) {
633fe6060f1SDimitry Andric       const auto &Row = *LogicalOpTypeList[r];
634fe6060f1SDimitry Andric       OS << "   {";
635fe6060f1SDimitry Andric       int i, s = Row.size();
636fe6060f1SDimitry Andric       for (i = 0; i < s; ++i) {
637fe6060f1SDimitry Andric         if (i > 0)
638fe6060f1SDimitry Andric           OS << ", ";
639fe6060f1SDimitry Andric         OS << Row[i];
640fe6060f1SDimitry Andric       }
641fe6060f1SDimitry Andric       for (; i < static_cast<int>(OpTypeListSize); ++i) {
642fe6060f1SDimitry Andric         if (i > 0)
643fe6060f1SDimitry Andric           OS << ", ";
644fe6060f1SDimitry Andric         OS << "-1";
645fe6060f1SDimitry Andric       }
646fe6060f1SDimitry Andric       OS << "}";
647fe6060f1SDimitry Andric       if (r != rs - 1)
648fe6060f1SDimitry Andric         OS << ",";
649fe6060f1SDimitry Andric       OS << "\n";
650fe6060f1SDimitry Andric     }
651fe6060f1SDimitry Andric     OS << "  };\n";
652fe6060f1SDimitry Andric 
653fe6060f1SDimitry Andric     OS << "  switch (Opcode) {\n";
654fe6060f1SDimitry Andric     OS << "  default: return -1;\n";
655fe6060f1SDimitry Andric     for (auto &P : InstMap) {
656fe6060f1SDimitry Andric       auto OpMapIdx = P.first;
657fe6060f1SDimitry Andric       const auto &Insts = P.second;
658fe6060f1SDimitry Andric       for (const auto &Inst : Insts) {
659fe6060f1SDimitry Andric         OS << "  case " << Inst << ":\n";
660fe6060f1SDimitry Andric       }
661fe6060f1SDimitry Andric       OS << "    return TypeMap[" << OpMapIdx << "][LogicalOpIdx];\n";
662fe6060f1SDimitry Andric     }
663fe6060f1SDimitry Andric     OS << "  }\n";
664fe6060f1SDimitry Andric   } else {
665fe6060f1SDimitry Andric     OS << "  return -1;\n";
666fe6060f1SDimitry Andric   }
667fe6060f1SDimitry Andric   OS << "}\n";
668fe6060f1SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
669fe6060f1SDimitry Andric   OS << "} // end namespace llvm\n";
670fe6060f1SDimitry Andric   OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n\n";
671fe6060f1SDimitry Andric }
672fe6060f1SDimitry Andric 
emitMCIIHelperMethods(raw_ostream & OS,StringRef TargetName)6730b57cec5SDimitry Andric void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,
6740b57cec5SDimitry Andric                                              StringRef TargetName) {
6750b57cec5SDimitry Andric   RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate");
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_MC_HELPER_DECLS\n";
6780b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_MC_HELPER_DECLS\n\n";
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric   OS << "namespace llvm {\n";
681753f127fSDimitry Andric   OS << "class MCInst;\n";
682753f127fSDimitry Andric   OS << "class FeatureBitset;\n\n";
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   OS << "namespace " << TargetName << "_MC {\n\n";
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric   for (const Record *Rec : TIIPredicates) {
6870b57cec5SDimitry Andric     OS << "bool " << Rec->getValueAsString("FunctionName")
6880b57cec5SDimitry Andric        << "(const MCInst &MI);\n";
6890b57cec5SDimitry Andric   }
6900b57cec5SDimitry Andric 
691753f127fSDimitry Andric   OS << "void verifyInstructionPredicates(unsigned Opcode, const FeatureBitset "
692753f127fSDimitry Andric         "&Features);\n";
693753f127fSDimitry Andric 
6948bcb0991SDimitry Andric   OS << "\n} // end namespace " << TargetName << "_MC\n";
6958bcb0991SDimitry Andric   OS << "} // end namespace llvm\n\n";
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_MC_HELPER_DECLS\n\n";
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_MC_HELPERS\n";
7000b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_MC_HELPERS\n\n";
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   OS << "namespace llvm {\n";
7030b57cec5SDimitry Andric   OS << "namespace " << TargetName << "_MC {\n\n";
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   PredicateExpander PE(TargetName);
7060b57cec5SDimitry Andric   PE.setExpandForMC(true);
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   for (const Record *Rec : TIIPredicates) {
7090b57cec5SDimitry Andric     OS << "bool " << Rec->getValueAsString("FunctionName");
7100b57cec5SDimitry Andric     OS << "(const MCInst &MI) {\n";
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric     OS.indent(PE.getIndentLevel() * 2);
7130b57cec5SDimitry Andric     PE.expandStatement(OS, Rec->getValueAsDef("Body"));
7140b57cec5SDimitry Andric     OS << "\n}\n\n";
7150b57cec5SDimitry Andric   }
7160b57cec5SDimitry Andric 
7178bcb0991SDimitry Andric   OS << "} // end namespace " << TargetName << "_MC\n";
7188bcb0991SDimitry Andric   OS << "} // end namespace llvm\n\n";
7190b57cec5SDimitry Andric 
720753f127fSDimitry Andric   OS << "#endif // GET_GENISTRINFO_MC_HELPERS\n\n";
721753f127fSDimitry Andric }
722753f127fSDimitry Andric 
723753f127fSDimitry Andric static std::string
getNameForFeatureBitset(const std::vector<Record * > & FeatureBitset)724753f127fSDimitry Andric getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {
725753f127fSDimitry Andric   std::string Name = "CEFBS";
726753f127fSDimitry Andric   for (const auto &Feature : FeatureBitset)
727753f127fSDimitry Andric     Name += ("_" + Feature->getName()).str();
728753f127fSDimitry Andric   return Name;
729753f127fSDimitry Andric }
730753f127fSDimitry Andric 
emitFeatureVerifier(raw_ostream & OS,const CodeGenTarget & Target)731753f127fSDimitry Andric void InstrInfoEmitter::emitFeatureVerifier(raw_ostream &OS,
732753f127fSDimitry Andric                                            const CodeGenTarget &Target) {
733753f127fSDimitry Andric   const auto &All = SubtargetFeatureInfo::getAll(Records);
734753f127fSDimitry Andric   std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
735753f127fSDimitry Andric   SubtargetFeatures.insert(All.begin(), All.end());
736753f127fSDimitry Andric 
7375f757f3fSDimitry Andric   OS << "#if (defined(ENABLE_INSTR_PREDICATE_VERIFIER) && !defined(NDEBUG)) "
7385f757f3fSDimitry Andric      << "||\\\n"
7395f757f3fSDimitry Andric      << "    defined(GET_AVAILABLE_OPCODE_CHECKER)\n"
74006c3fb27SDimitry Andric      << "#define GET_COMPUTE_FEATURES\n"
74106c3fb27SDimitry Andric      << "#endif\n";
74206c3fb27SDimitry Andric   OS << "#ifdef GET_COMPUTE_FEATURES\n"
74306c3fb27SDimitry Andric      << "#undef GET_COMPUTE_FEATURES\n"
74406c3fb27SDimitry Andric      << "namespace llvm {\n"
74506c3fb27SDimitry Andric      << "namespace " << Target.getName() << "_MC {\n\n";
746753f127fSDimitry Andric 
747753f127fSDimitry Andric   // Emit the subtarget feature enumeration.
748753f127fSDimitry Andric   SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
749753f127fSDimitry Andric                                                            OS);
750753f127fSDimitry Andric   // Emit the available features compute function.
75106c3fb27SDimitry Andric   OS << "inline ";
752753f127fSDimitry Andric   SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
753753f127fSDimitry Andric       Target.getName(), "", "computeAvailableFeatures", SubtargetFeatures, OS);
754753f127fSDimitry Andric 
755753f127fSDimitry Andric   std::vector<std::vector<Record *>> FeatureBitsets;
756753f127fSDimitry Andric   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
757753f127fSDimitry Andric     FeatureBitsets.emplace_back();
758753f127fSDimitry Andric     for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
759753f127fSDimitry Andric       const auto &I = SubtargetFeatures.find(Predicate);
760753f127fSDimitry Andric       if (I != SubtargetFeatures.end())
761753f127fSDimitry Andric         FeatureBitsets.back().push_back(I->second.TheDef);
762753f127fSDimitry Andric     }
763753f127fSDimitry Andric   }
764753f127fSDimitry Andric 
765753f127fSDimitry Andric   llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,
766753f127fSDimitry Andric                                  const std::vector<Record *> &B) {
767753f127fSDimitry Andric     if (A.size() < B.size())
768753f127fSDimitry Andric       return true;
769753f127fSDimitry Andric     if (A.size() > B.size())
770753f127fSDimitry Andric       return false;
771753f127fSDimitry Andric     for (auto Pair : zip(A, B)) {
772753f127fSDimitry Andric       if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())
773753f127fSDimitry Andric         return true;
774753f127fSDimitry Andric       if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())
775753f127fSDimitry Andric         return false;
776753f127fSDimitry Andric     }
777753f127fSDimitry Andric     return false;
778753f127fSDimitry Andric   });
779*0fca6ea1SDimitry Andric   FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end());
78006c3fb27SDimitry Andric   OS << "inline FeatureBitset computeRequiredFeatures(unsigned Opcode) {\n"
781753f127fSDimitry Andric      << "  enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"
782753f127fSDimitry Andric      << "    CEFBS_None,\n";
783753f127fSDimitry Andric   for (const auto &FeatureBitset : FeatureBitsets) {
784753f127fSDimitry Andric     if (FeatureBitset.empty())
785753f127fSDimitry Andric       continue;
786753f127fSDimitry Andric     OS << "    " << getNameForFeatureBitset(FeatureBitset) << ",\n";
787753f127fSDimitry Andric   }
788753f127fSDimitry Andric   OS << "  };\n\n"
789753f127fSDimitry Andric      << "  static constexpr FeatureBitset FeatureBitsets[] = {\n"
790753f127fSDimitry Andric      << "    {}, // CEFBS_None\n";
791753f127fSDimitry Andric   for (const auto &FeatureBitset : FeatureBitsets) {
792753f127fSDimitry Andric     if (FeatureBitset.empty())
793753f127fSDimitry Andric       continue;
794753f127fSDimitry Andric     OS << "    {";
795753f127fSDimitry Andric     for (const auto &Feature : FeatureBitset) {
796753f127fSDimitry Andric       const auto &I = SubtargetFeatures.find(Feature);
797753f127fSDimitry Andric       assert(I != SubtargetFeatures.end() && "Didn't import predicate?");
798753f127fSDimitry Andric       OS << I->second.getEnumBitName() << ", ";
799753f127fSDimitry Andric     }
800753f127fSDimitry Andric     OS << "},\n";
801753f127fSDimitry Andric   }
802753f127fSDimitry Andric   OS << "  };\n"
8035f757f3fSDimitry Andric      << "  static constexpr " << getMinimalTypeForRange(FeatureBitsets.size())
804753f127fSDimitry Andric      << " RequiredFeaturesRefs[] = {\n";
805753f127fSDimitry Andric   unsigned InstIdx = 0;
806753f127fSDimitry Andric   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
807753f127fSDimitry Andric     OS << "    CEFBS";
808753f127fSDimitry Andric     unsigned NumPredicates = 0;
809753f127fSDimitry Andric     for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
810753f127fSDimitry Andric       const auto &I = SubtargetFeatures.find(Predicate);
811753f127fSDimitry Andric       if (I != SubtargetFeatures.end()) {
812753f127fSDimitry Andric         OS << '_' << I->second.TheDef->getName();
813753f127fSDimitry Andric         NumPredicates++;
814753f127fSDimitry Andric       }
815753f127fSDimitry Andric     }
816753f127fSDimitry Andric     if (!NumPredicates)
817753f127fSDimitry Andric       OS << "_None";
818753f127fSDimitry Andric     OS << ", // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";
819753f127fSDimitry Andric     InstIdx++;
820753f127fSDimitry Andric   }
82106c3fb27SDimitry Andric   OS << "  };\n\n"
82206c3fb27SDimitry Andric      << "  assert(Opcode < " << InstIdx << ");\n"
82306c3fb27SDimitry Andric      << "  return FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n"
82406c3fb27SDimitry Andric      << "}\n\n";
82506c3fb27SDimitry Andric 
82606c3fb27SDimitry Andric   OS << "} // end namespace " << Target.getName() << "_MC\n"
82706c3fb27SDimitry Andric      << "} // end namespace llvm\n"
82806c3fb27SDimitry Andric      << "#endif // GET_COMPUTE_FEATURES\n\n";
82906c3fb27SDimitry Andric 
8305f757f3fSDimitry Andric   OS << "#ifdef GET_AVAILABLE_OPCODE_CHECKER\n"
8315f757f3fSDimitry Andric      << "#undef GET_AVAILABLE_OPCODE_CHECKER\n"
8325f757f3fSDimitry Andric      << "namespace llvm {\n"
8335f757f3fSDimitry Andric      << "namespace " << Target.getName() << "_MC {\n";
8345f757f3fSDimitry Andric   OS << "bool isOpcodeAvailable("
8355f757f3fSDimitry Andric      << "unsigned Opcode, const FeatureBitset &Features) {\n"
8365f757f3fSDimitry Andric      << "  FeatureBitset AvailableFeatures = "
8375f757f3fSDimitry Andric      << "computeAvailableFeatures(Features);\n"
8385f757f3fSDimitry Andric      << "  FeatureBitset RequiredFeatures = "
8395f757f3fSDimitry Andric      << "computeRequiredFeatures(Opcode);\n"
8405f757f3fSDimitry Andric      << "  FeatureBitset MissingFeatures =\n"
8415f757f3fSDimitry Andric      << "      (AvailableFeatures & RequiredFeatures) ^\n"
8425f757f3fSDimitry Andric      << "      RequiredFeatures;\n"
8435f757f3fSDimitry Andric      << "  return !MissingFeatures.any();\n"
8445f757f3fSDimitry Andric      << "}\n";
8455f757f3fSDimitry Andric   OS << "} // end namespace " << Target.getName() << "_MC\n"
8465f757f3fSDimitry Andric      << "} // end namespace llvm\n"
8475f757f3fSDimitry Andric      << "#endif // GET_AVAILABLE_OPCODE_CHECKER\n\n";
8485f757f3fSDimitry Andric 
84906c3fb27SDimitry Andric   OS << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n"
85006c3fb27SDimitry Andric      << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n"
85106c3fb27SDimitry Andric      << "#include <sstream>\n\n";
85206c3fb27SDimitry Andric 
85306c3fb27SDimitry Andric   OS << "namespace llvm {\n";
85406c3fb27SDimitry Andric   OS << "namespace " << Target.getName() << "_MC {\n\n";
85506c3fb27SDimitry Andric 
85606c3fb27SDimitry Andric   // Emit the name table for error messages.
85706c3fb27SDimitry Andric   OS << "#ifndef NDEBUG\n";
85806c3fb27SDimitry Andric   SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS);
85906c3fb27SDimitry Andric   OS << "#endif // NDEBUG\n\n";
86006c3fb27SDimitry Andric 
86106c3fb27SDimitry Andric   // Emit the predicate verifier.
86206c3fb27SDimitry Andric   OS << "void verifyInstructionPredicates(\n"
86306c3fb27SDimitry Andric      << "    unsigned Opcode, const FeatureBitset &Features) {\n"
86406c3fb27SDimitry Andric      << "#ifndef NDEBUG\n";
865753f127fSDimitry Andric   OS << "  FeatureBitset AvailableFeatures = "
866753f127fSDimitry Andric         "computeAvailableFeatures(Features);\n";
86706c3fb27SDimitry Andric   OS << "  FeatureBitset RequiredFeatures = "
86806c3fb27SDimitry Andric      << "computeRequiredFeatures(Opcode);\n";
869753f127fSDimitry Andric   OS << "  FeatureBitset MissingFeatures =\n"
870753f127fSDimitry Andric      << "      (AvailableFeatures & RequiredFeatures) ^\n"
871753f127fSDimitry Andric      << "      RequiredFeatures;\n"
872753f127fSDimitry Andric      << "  if (MissingFeatures.any()) {\n"
873753f127fSDimitry Andric      << "    std::ostringstream Msg;\n"
874753f127fSDimitry Andric      << "    Msg << \"Attempting to emit \" << &" << Target.getName()
875753f127fSDimitry Andric      << "InstrNameData[" << Target.getName() << "InstrNameIndices[Opcode]]\n"
876753f127fSDimitry Andric      << "        << \" instruction but the \";\n"
877753f127fSDimitry Andric      << "    for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n"
878753f127fSDimitry Andric      << "      if (MissingFeatures.test(i))\n"
879753f127fSDimitry Andric      << "        Msg << SubtargetFeatureNames[i] << \" \";\n"
880753f127fSDimitry Andric      << "    Msg << \"predicate(s) are not met\";\n"
881753f127fSDimitry Andric      << "    report_fatal_error(Msg.str().c_str());\n"
882753f127fSDimitry Andric      << "  }\n"
883753f127fSDimitry Andric      << "#endif // NDEBUG\n";
884753f127fSDimitry Andric   OS << "}\n";
885753f127fSDimitry Andric   OS << "} // end namespace " << Target.getName() << "_MC\n";
886753f127fSDimitry Andric   OS << "} // end namespace llvm\n";
887753f127fSDimitry Andric   OS << "#endif // ENABLE_INSTR_PREDICATE_VERIFIER\n\n";
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
emitTIIHelperMethods(raw_ostream & OS,StringRef TargetName,bool ExpandDefinition)8900b57cec5SDimitry Andric void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS,
8910b57cec5SDimitry Andric                                             StringRef TargetName,
8920b57cec5SDimitry Andric                                             bool ExpandDefinition) {
8930b57cec5SDimitry Andric   RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate");
8940b57cec5SDimitry Andric   if (TIIPredicates.empty())
8950b57cec5SDimitry Andric     return;
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   PredicateExpander PE(TargetName);
8980b57cec5SDimitry Andric   PE.setExpandForMC(false);
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   for (const Record *Rec : TIIPredicates) {
9010b57cec5SDimitry Andric     OS << (ExpandDefinition ? "" : "static ") << "bool ";
9020b57cec5SDimitry Andric     if (ExpandDefinition)
9030b57cec5SDimitry Andric       OS << TargetName << "InstrInfo::";
9040b57cec5SDimitry Andric     OS << Rec->getValueAsString("FunctionName");
9050b57cec5SDimitry Andric     OS << "(const MachineInstr &MI)";
9060b57cec5SDimitry Andric     if (!ExpandDefinition) {
9070b57cec5SDimitry Andric       OS << ";\n";
9080b57cec5SDimitry Andric       continue;
9090b57cec5SDimitry Andric     }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric     OS << " {\n";
9120b57cec5SDimitry Andric     OS.indent(PE.getIndentLevel() * 2);
9130b57cec5SDimitry Andric     PE.expandStatement(OS, Rec->getValueAsDef("Body"));
9140b57cec5SDimitry Andric     OS << "\n}\n\n";
9150b57cec5SDimitry Andric   }
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
9190b57cec5SDimitry Andric // Main Output.
9200b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
9210b57cec5SDimitry Andric 
9220b57cec5SDimitry Andric // run - Emit the main instruction description records for the target...
run(raw_ostream & OS)9230b57cec5SDimitry Andric void InstrInfoEmitter::run(raw_ostream &OS) {
9240b57cec5SDimitry Andric   emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);
9250b57cec5SDimitry Andric   emitEnums(OS);
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   CodeGenTarget &Target = CDP.getTargetInfo();
9285ffd83dbSDimitry Andric   const std::string &TargetName = std::string(Target.getName());
9290b57cec5SDimitry Andric   Record *InstrInfo = Target.getInstructionSet();
9300b57cec5SDimitry Andric 
93106c3fb27SDimitry Andric   // Collect all of the operand info records.
93206c3fb27SDimitry Andric   Records.startTimer("Collect operand info");
93306c3fb27SDimitry Andric   OperandInfoListTy OperandInfoList;
93406c3fb27SDimitry Andric   OperandInfoMapTy OperandInfoMap;
93506c3fb27SDimitry Andric   unsigned OperandInfoSize =
93606c3fb27SDimitry Andric       CollectOperandInfo(OperandInfoList, OperandInfoMap);
9370b57cec5SDimitry Andric 
93806c3fb27SDimitry Andric   // Collect all of the instruction's implicit uses and defs.
93906c3fb27SDimitry Andric   Records.startTimer("Collect uses/defs");
94006c3fb27SDimitry Andric   std::map<std::vector<Record *>, unsigned> EmittedLists;
94106c3fb27SDimitry Andric   std::vector<std::vector<Record *>> ImplicitLists;
94206c3fb27SDimitry Andric   unsigned ImplicitListSize = 0;
9430b57cec5SDimitry Andric   for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
944bdd1243dSDimitry Andric     std::vector<Record *> ImplicitOps = II->ImplicitUses;
945bdd1243dSDimitry Andric     llvm::append_range(ImplicitOps, II->ImplicitDefs);
94606c3fb27SDimitry Andric     if (EmittedLists.insert({ImplicitOps, ImplicitListSize}).second) {
94706c3fb27SDimitry Andric       ImplicitLists.push_back(ImplicitOps);
94806c3fb27SDimitry Andric       ImplicitListSize += ImplicitOps.size();
9490b57cec5SDimitry Andric     }
9500b57cec5SDimitry Andric   }
9510b57cec5SDimitry Andric 
95206c3fb27SDimitry Andric   ArrayRef<const CodeGenInstruction *> NumberedInstructions =
95306c3fb27SDimitry Andric       Target.getInstructionsByEnumValue();
95406c3fb27SDimitry Andric   OS << "#if defined(GET_INSTRINFO_MC_DESC) || "
95506c3fb27SDimitry Andric         "defined(GET_INSTRINFO_CTOR_DTOR)\n";
95606c3fb27SDimitry Andric   OS << "namespace llvm {\n\n";
9570b57cec5SDimitry Andric 
95806c3fb27SDimitry Andric   OS << "struct " << TargetName << "InstrTable {\n";
95906c3fb27SDimitry Andric   OS << "  MCInstrDesc Insts[" << NumberedInstructions.size() << "];\n";
96006c3fb27SDimitry Andric   OS << "  static_assert(alignof(MCInstrDesc) >= alignof(MCOperandInfo), "
96106c3fb27SDimitry Andric         "\"Unwanted padding between Insts and OperandInfo\");\n";
96206c3fb27SDimitry Andric   OS << "  MCOperandInfo OperandInfo[" << OperandInfoSize << "];\n";
96306c3fb27SDimitry Andric   OS << "  static_assert(alignof(MCOperandInfo) >= alignof(MCPhysReg), "
96406c3fb27SDimitry Andric         "\"Unwanted padding between OperandInfo and ImplicitOps\");\n";
96506c3fb27SDimitry Andric   OS << "  MCPhysReg ImplicitOps[" << std::max(ImplicitListSize, 1U) << "];\n";
96606c3fb27SDimitry Andric   OS << "};\n\n";
96706c3fb27SDimitry Andric 
96806c3fb27SDimitry Andric   OS << "} // end namespace llvm\n";
96906c3fb27SDimitry Andric   OS << "#endif // defined(GET_INSTRINFO_MC_DESC) || "
97006c3fb27SDimitry Andric         "defined(GET_INSTRINFO_CTOR_DTOR)\n\n";
97106c3fb27SDimitry Andric 
97206c3fb27SDimitry Andric   OS << "#ifdef GET_INSTRINFO_MC_DESC\n";
97306c3fb27SDimitry Andric   OS << "#undef GET_INSTRINFO_MC_DESC\n";
97406c3fb27SDimitry Andric   OS << "namespace llvm {\n\n";
9750b57cec5SDimitry Andric 
976bdd1243dSDimitry Andric   // Emit all of the MCInstrDesc records in reverse ENUM ordering.
977e8d8bef9SDimitry Andric   Records.startTimer("Emit InstrDesc records");
97806c3fb27SDimitry Andric   OS << "static_assert(sizeof(MCOperandInfo) % sizeof(MCPhysReg) == 0);\n";
97906c3fb27SDimitry Andric   OS << "static constexpr unsigned " << TargetName << "ImpOpBase = sizeof "
98006c3fb27SDimitry Andric      << TargetName << "InstrTable::OperandInfo / (sizeof(MCPhysReg));\n\n";
9810b57cec5SDimitry Andric 
98206c3fb27SDimitry Andric   OS << "extern const " << TargetName << "InstrTable " << TargetName
98306c3fb27SDimitry Andric      << "Descs = {\n  {\n";
9840b57cec5SDimitry Andric   SequenceToOffsetTable<std::string> InstrNames;
985bdd1243dSDimitry Andric   unsigned Num = NumberedInstructions.size();
986bdd1243dSDimitry Andric   for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) {
9870b57cec5SDimitry Andric     // Keep a list of the instruction names.
9885ffd83dbSDimitry Andric     InstrNames.add(std::string(Inst->TheDef->getName()));
9890b57cec5SDimitry Andric     // Emit the record into the table.
99006c3fb27SDimitry Andric     emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoMap, OS);
9910b57cec5SDimitry Andric   }
99206c3fb27SDimitry Andric 
99306c3fb27SDimitry Andric   OS << "  }, {\n";
99406c3fb27SDimitry Andric 
99506c3fb27SDimitry Andric   // Emit all of the operand info records.
99606c3fb27SDimitry Andric   Records.startTimer("Emit operand info");
99706c3fb27SDimitry Andric   EmitOperandInfo(OS, OperandInfoList);
99806c3fb27SDimitry Andric 
99906c3fb27SDimitry Andric   OS << "  }, {\n";
100006c3fb27SDimitry Andric 
100106c3fb27SDimitry Andric   // Emit all of the instruction's implicit uses and defs.
100206c3fb27SDimitry Andric   Records.startTimer("Emit uses/defs");
100306c3fb27SDimitry Andric   for (auto &List : ImplicitLists) {
100406c3fb27SDimitry Andric     OS << "    /* " << EmittedLists[List] << " */";
100506c3fb27SDimitry Andric     for (auto &Reg : List)
100606c3fb27SDimitry Andric       OS << ' ' << getQualifiedName(Reg) << ',';
100706c3fb27SDimitry Andric     OS << '\n';
100806c3fb27SDimitry Andric   }
100906c3fb27SDimitry Andric 
101006c3fb27SDimitry Andric   OS << "  }\n};\n\n";
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric   // Emit the array of instruction names.
1013e8d8bef9SDimitry Andric   Records.startTimer("Emit instruction names");
10140b57cec5SDimitry Andric   InstrNames.layout();
10155ffd83dbSDimitry Andric   InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName +
10165ffd83dbSDimitry Andric                                           "InstrNameData[]");
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   OS << "extern const unsigned " << TargetName << "InstrNameIndices[] = {";
10190b57cec5SDimitry Andric   Num = 0;
10200b57cec5SDimitry Andric   for (const CodeGenInstruction *Inst : NumberedInstructions) {
10210b57cec5SDimitry Andric     // Newline every eight entries.
10220b57cec5SDimitry Andric     if (Num % 8 == 0)
10230b57cec5SDimitry Andric       OS << "\n    ";
10245ffd83dbSDimitry Andric     OS << InstrNames.get(std::string(Inst->TheDef->getName())) << "U, ";
10250b57cec5SDimitry Andric     ++Num;
10260b57cec5SDimitry Andric   }
10270b57cec5SDimitry Andric   OS << "\n};\n\n";
10280b57cec5SDimitry Andric 
10295ffd83dbSDimitry Andric   bool HasDeprecationFeatures =
10305ffd83dbSDimitry Andric       llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {
10315ffd83dbSDimitry Andric         return !Inst->HasComplexDeprecationPredicate &&
10325ffd83dbSDimitry Andric                !Inst->DeprecatedReason.empty();
10335ffd83dbSDimitry Andric       });
10345ffd83dbSDimitry Andric   if (HasDeprecationFeatures) {
10355ffd83dbSDimitry Andric     OS << "extern const uint8_t " << TargetName
10365ffd83dbSDimitry Andric        << "InstrDeprecationFeatures[] = {";
10375ffd83dbSDimitry Andric     Num = 0;
10385ffd83dbSDimitry Andric     for (const CodeGenInstruction *Inst : NumberedInstructions) {
10395ffd83dbSDimitry Andric       if (Num % 8 == 0)
10405ffd83dbSDimitry Andric         OS << "\n    ";
10415ffd83dbSDimitry Andric       if (!Inst->HasComplexDeprecationPredicate &&
10425ffd83dbSDimitry Andric           !Inst->DeprecatedReason.empty())
10435ffd83dbSDimitry Andric         OS << Target.getInstNamespace() << "::" << Inst->DeprecatedReason
10445ffd83dbSDimitry Andric            << ", ";
10455ffd83dbSDimitry Andric       else
10465ffd83dbSDimitry Andric         OS << "uint8_t(-1), ";
10475ffd83dbSDimitry Andric       ++Num;
10485ffd83dbSDimitry Andric     }
10495ffd83dbSDimitry Andric     OS << "\n};\n\n";
10505ffd83dbSDimitry Andric   }
10515ffd83dbSDimitry Andric 
10525ffd83dbSDimitry Andric   bool HasComplexDeprecationInfos =
10535ffd83dbSDimitry Andric       llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {
10545ffd83dbSDimitry Andric         return Inst->HasComplexDeprecationPredicate;
10555ffd83dbSDimitry Andric       });
10565ffd83dbSDimitry Andric   if (HasComplexDeprecationInfos) {
10575ffd83dbSDimitry Andric     OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName
10585ffd83dbSDimitry Andric        << "InstrComplexDeprecationInfos[] = {";
10595ffd83dbSDimitry Andric     Num = 0;
10605ffd83dbSDimitry Andric     for (const CodeGenInstruction *Inst : NumberedInstructions) {
10615ffd83dbSDimitry Andric       if (Num % 8 == 0)
10625ffd83dbSDimitry Andric         OS << "\n    ";
10635ffd83dbSDimitry Andric       if (Inst->HasComplexDeprecationPredicate)
10645ffd83dbSDimitry Andric         // Emit a function pointer to the complex predicate method.
10655ffd83dbSDimitry Andric         OS << "&get" << Inst->DeprecatedReason << "DeprecationInfo, ";
10665ffd83dbSDimitry Andric       else
10675ffd83dbSDimitry Andric         OS << "nullptr, ";
10685ffd83dbSDimitry Andric       ++Num;
10695ffd83dbSDimitry Andric     }
10705ffd83dbSDimitry Andric     OS << "\n};\n\n";
10715ffd83dbSDimitry Andric   }
10725ffd83dbSDimitry Andric 
10730b57cec5SDimitry Andric   // MCInstrInfo initialization routine.
1074e8d8bef9SDimitry Andric   Records.startTimer("Emit initialization routine");
10750b57cec5SDimitry Andric   OS << "static inline void Init" << TargetName
10760b57cec5SDimitry Andric      << "MCInstrInfo(MCInstrInfo *II) {\n";
107706c3fb27SDimitry Andric   OS << "  II->InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName
10785ffd83dbSDimitry Andric      << "InstrNameIndices, " << TargetName << "InstrNameData, ";
10795ffd83dbSDimitry Andric   if (HasDeprecationFeatures)
10805ffd83dbSDimitry Andric     OS << TargetName << "InstrDeprecationFeatures, ";
10815ffd83dbSDimitry Andric   else
10825ffd83dbSDimitry Andric     OS << "nullptr, ";
10835ffd83dbSDimitry Andric   if (HasComplexDeprecationInfos)
10845ffd83dbSDimitry Andric     OS << TargetName << "InstrComplexDeprecationInfos, ";
10855ffd83dbSDimitry Andric   else
10865ffd83dbSDimitry Andric     OS << "nullptr, ";
10875ffd83dbSDimitry Andric   OS << NumberedInstructions.size() << ");\n}\n\n";
10880b57cec5SDimitry Andric 
10898bcb0991SDimitry Andric   OS << "} // end namespace llvm\n";
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_MC_DESC\n\n";
10920b57cec5SDimitry Andric 
10930b57cec5SDimitry Andric   // Create a TargetInstrInfo subclass to hide the MC layer initialization.
10940b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_HEADER\n";
10950b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_HEADER\n";
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric   std::string ClassName = TargetName + "GenInstrInfo";
10980b57cec5SDimitry Andric   OS << "namespace llvm {\n";
10990b57cec5SDimitry Andric   OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
11000b57cec5SDimitry Andric      << "  explicit " << ClassName
1101bdd1243dSDimitry Andric      << "(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u, "
1102bdd1243dSDimitry Andric         "unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u);\n"
11030b57cec5SDimitry Andric      << "  ~" << ClassName << "() override = default;\n";
11040b57cec5SDimitry Andric 
11058bcb0991SDimitry Andric   OS << "\n};\n} // end namespace llvm\n";
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_HEADER\n\n";
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_HELPER_DECLS\n";
11100b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_HELPER_DECLS\n\n";
111104eeddc0SDimitry Andric   emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ false);
11120b57cec5SDimitry Andric   OS << "\n";
11130b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_HELPER_DECLS\n\n";
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_HELPERS\n";
11160b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_HELPERS\n\n";
111704eeddc0SDimitry Andric   emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ true);
11180b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_HELPERS\n\n";
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n";
11210b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_CTOR_DTOR\n";
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric   OS << "namespace llvm {\n";
112406c3fb27SDimitry Andric   OS << "extern const " << TargetName << "InstrTable " << TargetName
112506c3fb27SDimitry Andric      << "Descs;\n";
11260b57cec5SDimitry Andric   OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";
11270b57cec5SDimitry Andric   OS << "extern const char " << TargetName << "InstrNameData[];\n";
11285ffd83dbSDimitry Andric   if (HasDeprecationFeatures)
11295ffd83dbSDimitry Andric     OS << "extern const uint8_t " << TargetName
11305ffd83dbSDimitry Andric        << "InstrDeprecationFeatures[];\n";
11315ffd83dbSDimitry Andric   if (HasComplexDeprecationInfos)
11325ffd83dbSDimitry Andric     OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName
11335ffd83dbSDimitry Andric        << "InstrComplexDeprecationInfos[];\n";
11340b57cec5SDimitry Andric   OS << ClassName << "::" << ClassName
1135bdd1243dSDimitry Andric      << "(unsigned CFSetupOpcode, unsigned CFDestroyOpcode, unsigned "
1136bdd1243dSDimitry Andric         "CatchRetOpcode, unsigned ReturnOpcode)\n"
11375ffd83dbSDimitry Andric      << "  : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, "
11385ffd83dbSDimitry Andric         "ReturnOpcode) {\n"
113906c3fb27SDimitry Andric      << "  InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName
11405ffd83dbSDimitry Andric      << "InstrNameIndices, " << TargetName << "InstrNameData, ";
11415ffd83dbSDimitry Andric   if (HasDeprecationFeatures)
11425ffd83dbSDimitry Andric     OS << TargetName << "InstrDeprecationFeatures, ";
11435ffd83dbSDimitry Andric   else
11445ffd83dbSDimitry Andric     OS << "nullptr, ";
11455ffd83dbSDimitry Andric   if (HasComplexDeprecationInfos)
11465ffd83dbSDimitry Andric     OS << TargetName << "InstrComplexDeprecationInfos, ";
11475ffd83dbSDimitry Andric   else
11485ffd83dbSDimitry Andric     OS << "nullptr, ";
11495ffd83dbSDimitry Andric   OS << NumberedInstructions.size() << ");\n}\n";
11508bcb0991SDimitry Andric   OS << "} // end namespace llvm\n";
11510b57cec5SDimitry Andric 
11520b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";
11530b57cec5SDimitry Andric 
1154e8d8bef9SDimitry Andric   Records.startTimer("Emit operand name mappings");
11550b57cec5SDimitry Andric   emitOperandNameMappings(OS, Target, NumberedInstructions);
11560b57cec5SDimitry Andric 
1157e8d8bef9SDimitry Andric   Records.startTimer("Emit operand type mappings");
11580b57cec5SDimitry Andric   emitOperandTypeMappings(OS, Target, NumberedInstructions);
11590b57cec5SDimitry Andric 
1160fe6060f1SDimitry Andric   Records.startTimer("Emit logical operand size mappings");
1161fe6060f1SDimitry Andric   emitLogicalOperandSizeMappings(OS, TargetName, NumberedInstructions);
1162fe6060f1SDimitry Andric 
1163fe6060f1SDimitry Andric   Records.startTimer("Emit logical operand type mappings");
1164fe6060f1SDimitry Andric   emitLogicalOperandTypeMappings(OS, TargetName, NumberedInstructions);
1165fe6060f1SDimitry Andric 
1166e8d8bef9SDimitry Andric   Records.startTimer("Emit helper methods");
11670b57cec5SDimitry Andric   emitMCIIHelperMethods(OS, TargetName);
1168753f127fSDimitry Andric 
1169753f127fSDimitry Andric   Records.startTimer("Emit verifier methods");
1170753f127fSDimitry Andric   emitFeatureVerifier(OS, Target);
11710b57cec5SDimitry Andric }
11720b57cec5SDimitry Andric 
emitRecord(const CodeGenInstruction & Inst,unsigned Num,Record * InstrInfo,std::map<std::vector<Record * >,unsigned> & EmittedLists,const OperandInfoMapTy & OperandInfoMap,raw_ostream & OS)117306c3fb27SDimitry Andric void InstrInfoEmitter::emitRecord(
117406c3fb27SDimitry Andric     const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo,
11750b57cec5SDimitry Andric     std::map<std::vector<Record *>, unsigned> &EmittedLists,
117606c3fb27SDimitry Andric     const OperandInfoMapTy &OperandInfoMap, raw_ostream &OS) {
11770b57cec5SDimitry Andric   int MinOperands = 0;
11780b57cec5SDimitry Andric   if (!Inst.Operands.empty())
11790b57cec5SDimitry Andric     // Each logical operand can be multiple MI operands.
1180*0fca6ea1SDimitry Andric     MinOperands =
1181*0fca6ea1SDimitry Andric         Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands;
1182*0fca6ea1SDimitry Andric   // Even the logical output operand may be multiple MI operands.
1183*0fca6ea1SDimitry Andric   int DefOperands = 0;
1184*0fca6ea1SDimitry Andric   if (Inst.Operands.NumDefs) {
1185*0fca6ea1SDimitry Andric     auto &Opnd = Inst.Operands[Inst.Operands.NumDefs - 1];
1186*0fca6ea1SDimitry Andric     DefOperands = Opnd.MIOperandNo + Opnd.MINumOperands;
1187*0fca6ea1SDimitry Andric   }
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric   OS << "    { ";
1190*0fca6ea1SDimitry Andric   OS << Num << ",\t" << MinOperands << ",\t" << DefOperands << ",\t"
11910b57cec5SDimitry Andric      << Inst.TheDef->getValueAsInt("Size") << ",\t"
119206c3fb27SDimitry Andric      << SchedModels.getSchedClassIdx(Inst) << ",\t";
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric   CodeGenTarget &Target = CDP.getTargetInfo();
11950b57cec5SDimitry Andric 
119606c3fb27SDimitry Andric   // Emit the implicit use/def list...
119706c3fb27SDimitry Andric   OS << Inst.ImplicitUses.size() << ",\t" << Inst.ImplicitDefs.size() << ",\t";
119806c3fb27SDimitry Andric   std::vector<Record *> ImplicitOps = Inst.ImplicitUses;
119906c3fb27SDimitry Andric   llvm::append_range(ImplicitOps, Inst.ImplicitDefs);
120006c3fb27SDimitry Andric   OS << Target.getName() << "ImpOpBase + " << EmittedLists[ImplicitOps]
120106c3fb27SDimitry Andric      << ",\t";
120206c3fb27SDimitry Andric 
120306c3fb27SDimitry Andric   // Emit the operand info offset.
120406c3fb27SDimitry Andric   OperandInfoTy OperandInfo = GetOperandInfo(Inst);
120506c3fb27SDimitry Andric   OS << OperandInfoMap.find(OperandInfo)->second << ",\t0";
120606c3fb27SDimitry Andric 
12070b57cec5SDimitry Andric   // Emit all of the target independent flags...
1208*0fca6ea1SDimitry Andric   if (Inst.isPreISelOpcode)
1209*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::PreISelOpcode)";
1210*0fca6ea1SDimitry Andric   if (Inst.isPseudo)
1211*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Pseudo)";
1212*0fca6ea1SDimitry Andric   if (Inst.isMeta)
1213*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Meta)";
1214*0fca6ea1SDimitry Andric   if (Inst.isReturn)
1215*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Return)";
1216*0fca6ea1SDimitry Andric   if (Inst.isEHScopeReturn)
1217*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::EHScopeReturn)";
1218*0fca6ea1SDimitry Andric   if (Inst.isBranch)
1219*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Branch)";
1220*0fca6ea1SDimitry Andric   if (Inst.isIndirectBranch)
1221*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::IndirectBranch)";
1222*0fca6ea1SDimitry Andric   if (Inst.isCompare)
1223*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Compare)";
1224*0fca6ea1SDimitry Andric   if (Inst.isMoveImm)
1225*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::MoveImm)";
1226*0fca6ea1SDimitry Andric   if (Inst.isMoveReg)
1227*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::MoveReg)";
1228*0fca6ea1SDimitry Andric   if (Inst.isBitcast)
1229*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Bitcast)";
1230*0fca6ea1SDimitry Andric   if (Inst.isAdd)
1231*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Add)";
1232*0fca6ea1SDimitry Andric   if (Inst.isTrap)
1233*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Trap)";
1234*0fca6ea1SDimitry Andric   if (Inst.isSelect)
1235*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Select)";
1236*0fca6ea1SDimitry Andric   if (Inst.isBarrier)
1237*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Barrier)";
1238*0fca6ea1SDimitry Andric   if (Inst.hasDelaySlot)
1239*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::DelaySlot)";
1240*0fca6ea1SDimitry Andric   if (Inst.isCall)
1241*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Call)";
1242*0fca6ea1SDimitry Andric   if (Inst.canFoldAsLoad)
1243*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::FoldableAsLoad)";
1244*0fca6ea1SDimitry Andric   if (Inst.mayLoad)
1245*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::MayLoad)";
1246*0fca6ea1SDimitry Andric   if (Inst.mayStore)
1247*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::MayStore)";
1248*0fca6ea1SDimitry Andric   if (Inst.mayRaiseFPException)
1249*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::MayRaiseFPException)";
1250*0fca6ea1SDimitry Andric   if (Inst.isPredicable)
1251*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Predicable)";
1252*0fca6ea1SDimitry Andric   if (Inst.isConvertibleToThreeAddress)
1253*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::ConvertibleTo3Addr)";
1254*0fca6ea1SDimitry Andric   if (Inst.isCommutable)
1255*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Commutable)";
1256*0fca6ea1SDimitry Andric   if (Inst.isTerminator)
1257*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Terminator)";
1258*0fca6ea1SDimitry Andric   if (Inst.isReMaterializable)
1259*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Rematerializable)";
1260*0fca6ea1SDimitry Andric   if (Inst.isNotDuplicable)
1261*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::NotDuplicable)";
1262*0fca6ea1SDimitry Andric   if (Inst.Operands.hasOptionalDef)
1263*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::HasOptionalDef)";
1264*0fca6ea1SDimitry Andric   if (Inst.usesCustomInserter)
1265*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::UsesCustomInserter)";
1266*0fca6ea1SDimitry Andric   if (Inst.hasPostISelHook)
1267*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::HasPostISelHook)";
1268*0fca6ea1SDimitry Andric   if (Inst.Operands.isVariadic)
1269*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Variadic)";
1270*0fca6ea1SDimitry Andric   if (Inst.hasSideEffects)
1271*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::UnmodeledSideEffects)";
1272*0fca6ea1SDimitry Andric   if (Inst.isAsCheapAsAMove)
1273*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::CheapAsAMove)";
12740b57cec5SDimitry Andric   if (!Target.getAllowRegisterRenaming() || Inst.hasExtraSrcRegAllocReq)
12750b57cec5SDimitry Andric     OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)";
12760b57cec5SDimitry Andric   if (!Target.getAllowRegisterRenaming() || Inst.hasExtraDefRegAllocReq)
12770b57cec5SDimitry Andric     OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)";
1278*0fca6ea1SDimitry Andric   if (Inst.isRegSequence)
1279*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::RegSequence)";
1280*0fca6ea1SDimitry Andric   if (Inst.isExtractSubreg)
1281*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::ExtractSubreg)";
1282*0fca6ea1SDimitry Andric   if (Inst.isInsertSubreg)
1283*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::InsertSubreg)";
1284*0fca6ea1SDimitry Andric   if (Inst.isConvergent)
1285*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Convergent)";
1286*0fca6ea1SDimitry Andric   if (Inst.variadicOpsAreDefs)
1287*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::VariadicOpsAreDefs)";
1288*0fca6ea1SDimitry Andric   if (Inst.isAuthenticated)
1289*0fca6ea1SDimitry Andric     OS << "|(1ULL<<MCID::Authenticated)";
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   // Emit all of the target-specific flags...
12920b57cec5SDimitry Andric   BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
12930b57cec5SDimitry Andric   if (!TSF)
12940b57cec5SDimitry Andric     PrintFatalError(Inst.TheDef->getLoc(), "no TSFlags?");
12950b57cec5SDimitry Andric   uint64_t Value = 0;
12960b57cec5SDimitry Andric   for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
12970b57cec5SDimitry Andric     if (const auto *Bit = dyn_cast<BitInit>(TSF->getBit(i)))
12980b57cec5SDimitry Andric       Value |= uint64_t(Bit->getValue()) << i;
12990b57cec5SDimitry Andric     else
13000b57cec5SDimitry Andric       PrintFatalError(Inst.TheDef->getLoc(),
13010b57cec5SDimitry Andric                       "Invalid TSFlags bit in " + Inst.TheDef->getName());
13020b57cec5SDimitry Andric   }
13030b57cec5SDimitry Andric   OS << ", 0x";
13040b57cec5SDimitry Andric   OS.write_hex(Value);
130506c3fb27SDimitry Andric   OS << "ULL";
13060b57cec5SDimitry Andric 
13070b57cec5SDimitry Andric   OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric // emitEnums - Print out enum values for all of the instructions.
emitEnums(raw_ostream & OS)13110b57cec5SDimitry Andric void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
13120b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_ENUM\n";
13130b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_ENUM\n";
13140b57cec5SDimitry Andric 
13150b57cec5SDimitry Andric   OS << "namespace llvm {\n\n";
13160b57cec5SDimitry Andric 
13175ffd83dbSDimitry Andric   const CodeGenTarget &Target = CDP.getTargetInfo();
13180b57cec5SDimitry Andric 
13190b57cec5SDimitry Andric   // We must emit the PHI opcode first...
13200b57cec5SDimitry Andric   StringRef Namespace = Target.getInstNamespace();
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric   if (Namespace.empty())
13230b57cec5SDimitry Andric     PrintFatalError("No instructions defined!");
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric   OS << "namespace " << Namespace << " {\n";
13260b57cec5SDimitry Andric   OS << "  enum {\n";
13270b57cec5SDimitry Andric   unsigned Num = 0;
13280b57cec5SDimitry Andric   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue())
1329*0fca6ea1SDimitry Andric     OS << "    " << Inst->TheDef->getName()
1330*0fca6ea1SDimitry Andric        << "\t= " << (Num = Target.getInstrIntValue(Inst->TheDef)) << ",\n";
1331*0fca6ea1SDimitry Andric   OS << "    INSTRUCTION_LIST_END = " << Num + 1 << "\n";
13320b57cec5SDimitry Andric   OS << "  };\n\n";
13338bcb0991SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
13348bcb0991SDimitry Andric   OS << "} // end namespace llvm\n";
13350b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_ENUM\n\n";
13360b57cec5SDimitry Andric 
13370b57cec5SDimitry Andric   OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n";
13380b57cec5SDimitry Andric   OS << "#undef GET_INSTRINFO_SCHED_ENUM\n";
13390b57cec5SDimitry Andric   OS << "namespace llvm {\n\n";
13400b57cec5SDimitry Andric   OS << "namespace " << Namespace << " {\n";
13410b57cec5SDimitry Andric   OS << "namespace Sched {\n";
13420b57cec5SDimitry Andric   OS << "  enum {\n";
13430b57cec5SDimitry Andric   Num = 0;
13440b57cec5SDimitry Andric   for (const auto &Class : SchedModels.explicit_classes())
13450b57cec5SDimitry Andric     OS << "    " << Class.Name << "\t= " << Num++ << ",\n";
13460b57cec5SDimitry Andric   OS << "    SCHED_LIST_END = " << Num << "\n";
13470b57cec5SDimitry Andric   OS << "  };\n";
13488bcb0991SDimitry Andric   OS << "} // end namespace Sched\n";
13498bcb0991SDimitry Andric   OS << "} // end namespace " << Namespace << "\n";
13508bcb0991SDimitry Andric   OS << "} // end namespace llvm\n";
13510b57cec5SDimitry Andric 
13520b57cec5SDimitry Andric   OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n";
13530b57cec5SDimitry Andric }
13540b57cec5SDimitry Andric 
EmitInstrInfo(RecordKeeper & RK,raw_ostream & OS)135506c3fb27SDimitry Andric static void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
1356e8d8bef9SDimitry Andric   RK.startTimer("Analyze DAG patterns");
13570b57cec5SDimitry Andric   InstrInfoEmitter(RK).run(OS);
1358e8d8bef9SDimitry Andric   RK.startTimer("Emit map table");
13590b57cec5SDimitry Andric   EmitMapTable(RK, OS);
13600b57cec5SDimitry Andric }
13610b57cec5SDimitry Andric 
136206c3fb27SDimitry Andric static TableGen::Emitter::Opt X("gen-instr-info", EmitInstrInfo,
136306c3fb27SDimitry Andric                                 "Generate instruction descriptions");
1364