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: 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 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 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 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. 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 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. 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 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 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 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 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 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 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... 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 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. 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 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