| //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This tablegen backend is responsible for emitting a description of the target |
| // instruction set for the code generator. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "CodeGenDAGPatterns.h" |
| #include "CodeGenInstruction.h" |
| #include "CodeGenSchedule.h" |
| #include "CodeGenTarget.h" |
| #include "PredicateExpander.h" |
| #include "SequenceToOffsetTable.h" |
| #include "TableGenBackends.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "llvm/TableGen/Error.h" |
| #include "llvm/TableGen/Record.h" |
| #include "llvm/TableGen/TableGenBackend.h" |
| #include <cassert> |
| #include <cstdint> |
| #include <map> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| using namespace llvm; |
| |
| namespace { |
| |
| class InstrInfoEmitter { |
| RecordKeeper &Records; |
| CodeGenDAGPatterns CDP; |
| const CodeGenSchedModels &SchedModels; |
| |
| public: |
| InstrInfoEmitter(RecordKeeper &R): |
| Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {} |
| |
| // run - Output the instruction set description. |
| void run(raw_ostream &OS); |
| |
| private: |
| void emitEnums(raw_ostream &OS); |
| |
| typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; |
| |
| /// The keys of this map are maps which have OpName enum values as their keys |
| /// and instruction operand indices as their values. The values of this map |
| /// are lists of instruction names. |
| typedef std::map<std::map<unsigned, unsigned>, |
| std::vector<std::string>> OpNameMapTy; |
| typedef std::map<std::string, unsigned>::iterator StrUintMapIter; |
| |
| /// Generate member functions in the target-specific GenInstrInfo class. |
| /// |
| /// This method is used to custom expand TIIPredicate definitions. |
| /// See file llvm/Target/TargetInstPredicates.td for a description of what is |
| /// a TIIPredicate and how to use it. |
| void emitTIIHelperMethods(raw_ostream &OS); |
| |
| /// Expand TIIPredicate definitions to functions that accept a const MCInst |
| /// reference. |
| void emitMCIIHelperMethods(raw_ostream &OS); |
| void emitRecord(const CodeGenInstruction &Inst, unsigned Num, |
| Record *InstrInfo, |
| std::map<std::vector<Record*>, unsigned> &EL, |
| const OperandInfoMapTy &OpInfo, |
| raw_ostream &OS); |
| void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target); |
| void initOperandMapData( |
| ArrayRef<const CodeGenInstruction *> NumberedInstructions, |
| StringRef Namespace, |
| std::map<std::string, unsigned> &Operands, |
| OpNameMapTy &OperandMap); |
| void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target, |
| ArrayRef<const CodeGenInstruction*> NumberedInstructions); |
| |
| // Operand information. |
| void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); |
| std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); |
| }; |
| |
| } // end anonymous namespace |
| |
| static void PrintDefList(const std::vector<Record*> &Uses, |
| unsigned Num, raw_ostream &OS) { |
| OS << "static const MCPhysReg ImplicitList" << Num << "[] = { "; |
| for (Record *U : Uses) |
| OS << getQualifiedName(U) << ", "; |
| OS << "0 };\n"; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Operand Info Emission. |
| //===----------------------------------------------------------------------===// |
| |
| std::vector<std::string> |
| InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { |
| std::vector<std::string> Result; |
| |
| for (auto &Op : Inst.Operands) { |
| // Handle aggregate operands and normal operands the same way by expanding |
| // either case into a list of operands for this op. |
| std::vector<CGIOperandList::OperandInfo> OperandList; |
| |
| // This might be a multiple operand thing. Targets like X86 have |
| // registers in their multi-operand operands. It may also be an anonymous |
| // operand, which has a single operand, but no declared class for the |
| // operand. |
| DagInit *MIOI = Op.MIOperandInfo; |
| |
| if (!MIOI || MIOI->getNumArgs() == 0) { |
| // Single, anonymous, operand. |
| OperandList.push_back(Op); |
| } else { |
| for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) { |
| OperandList.push_back(Op); |
| |
| auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef(); |
| OperandList.back().Rec = OpR; |
| } |
| } |
| |
| for (unsigned j = 0, e = OperandList.size(); j != e; ++j) { |
| Record *OpR = OperandList[j].Rec; |
| std::string Res; |
| |
| if (OpR->isSubClassOf("RegisterOperand")) |
| OpR = OpR->getValueAsDef("RegClass"); |
| if (OpR->isSubClassOf("RegisterClass")) |
| Res += getQualifiedName(OpR) + "RegClassID, "; |
| else if (OpR->isSubClassOf("PointerLikeRegClass")) |
| Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", "; |
| else |
| // -1 means the operand does not have a fixed register class. |
| Res += "-1, "; |
| |
| // Fill in applicable flags. |
| Res += "0"; |
| |
| // Ptr value whose register class is resolved via callback. |
| if (OpR->isSubClassOf("PointerLikeRegClass")) |
| Res += "|(1<<MCOI::LookupPtrRegClass)"; |
| |
| // Predicate operands. Check to see if the original unexpanded operand |
| // was of type PredicateOp. |
| if (Op.Rec->isSubClassOf("PredicateOp")) |
| Res += "|(1<<MCOI::Predicate)"; |
| |
| // Optional def operands. Check to see if the original unexpanded operand |
| // was of type OptionalDefOperand. |
| if (Op.Rec->isSubClassOf("OptionalDefOperand")) |
| Res += "|(1<<MCOI::OptionalDef)"; |
| |
| // Fill in operand type. |
| Res += ", "; |
| assert(!Op.OperandType.empty() && "Invalid operand type."); |
| Res += Op.OperandType; |
| |
| // Fill in constraint info. |
| Res += ", "; |
| |
| const CGIOperandList::ConstraintInfo &Constraint = |
| Op.Constraints[j]; |
| if (Constraint.isNone()) |
| Res += "0"; |
| else if (Constraint.isEarlyClobber()) |
| Res += "(1 << MCOI::EARLY_CLOBBER)"; |
| else { |
| assert(Constraint.isTied()); |
| Res += "((" + utostr(Constraint.getTiedOperand()) + |
| " << 16) | (1 << MCOI::TIED_TO))"; |
| } |
| |
| Result.push_back(Res); |
| } |
| } |
| |
| return Result; |
| } |
| |
| void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, |
| OperandInfoMapTy &OperandInfoIDs) { |
| // ID #0 is for no operand info. |
| unsigned OperandListNum = 0; |
| OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum; |
| |
| OS << "\n"; |
| const CodeGenTarget &Target = CDP.getTargetInfo(); |
| for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { |
| std::vector<std::string> OperandInfo = GetOperandInfo(*Inst); |
| unsigned &N = OperandInfoIDs[OperandInfo]; |
| if (N != 0) continue; |
| |
| N = ++OperandListNum; |
| OS << "static const MCOperandInfo OperandInfo" << N << "[] = { "; |
| for (const std::string &Info : OperandInfo) |
| OS << "{ " << Info << " }, "; |
| OS << "};\n"; |
| } |
| } |
| |
| /// Initialize data structures for generating operand name mappings. |
| /// |
| /// \param Operands [out] A map used to generate the OpName enum with operand |
| /// names as its keys and operand enum values as its values. |
| /// \param OperandMap [out] A map for representing the operand name mappings for |
| /// each instructions. This is used to generate the OperandMap table as |
| /// well as the getNamedOperandIdx() function. |
| void InstrInfoEmitter::initOperandMapData( |
| ArrayRef<const CodeGenInstruction *> NumberedInstructions, |
| StringRef Namespace, |
| std::map<std::string, unsigned> &Operands, |
| OpNameMapTy &OperandMap) { |
| unsigned NumOperands = 0; |
| for (const CodeGenInstruction *Inst : NumberedInstructions) { |
| if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) |
| continue; |
| std::map<unsigned, unsigned> OpList; |
| for (const auto &Info : Inst->Operands) { |
| StrUintMapIter I = Operands.find(Info.Name); |
| |
| if (I == Operands.end()) { |
| I = Operands.insert(Operands.begin(), |
| std::pair<std::string, unsigned>(Info.Name, NumOperands++)); |
| } |
| OpList[I->second] = Info.MIOperandNo; |
| } |
| OperandMap[OpList].push_back(Namespace.str() + "::" + |
| Inst->TheDef->getName().str()); |
| } |
| } |
| |
| /// Generate a table and function for looking up the indices of operands by |
| /// name. |
| /// |
| /// This code generates: |
| /// - An enum in the llvm::TargetNamespace::OpName namespace, with one entry |
| /// for each operand name. |
| /// - A 2-dimensional table called OperandMap for mapping OpName enum values to |
| /// operand indices. |
| /// - A function called getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) |
| /// for looking up the operand index for an instruction, given a value from |
| /// OpName enum |
| void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, |
| const CodeGenTarget &Target, |
| ArrayRef<const CodeGenInstruction*> NumberedInstructions) { |
| StringRef Namespace = Target.getInstNamespace(); |
| std::string OpNameNS = "OpName"; |
| // Map of operand names to their enumeration value. This will be used to |
| // generate the OpName enum. |
| std::map<std::string, unsigned> Operands; |
| OpNameMapTy OperandMap; |
| |
| initOperandMapData(NumberedInstructions, Namespace, Operands, OperandMap); |
| |
| OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n"; |
| OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n"; |
| OS << "namespace llvm {\n"; |
| OS << "namespace " << Namespace << " {\n"; |
| OS << "namespace " << OpNameNS << " {\n"; |
| OS << "enum {\n"; |
| for (const auto &Op : Operands) |
| OS << " " << Op.first << " = " << Op.second << ",\n"; |
| |
| OS << "OPERAND_LAST"; |
| OS << "\n};\n"; |
| OS << "} // end namespace OpName\n"; |
| OS << "} // end namespace " << Namespace << "\n"; |
| OS << "} // end namespace llvm\n"; |
| OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n"; |
| |
| OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n"; |
| OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; |
| OS << "namespace llvm {\n"; |
| OS << "namespace " << Namespace << " {\n"; |
| OS << "LLVM_READONLY\n"; |
| OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n"; |
| if (!Operands.empty()) { |
| OS << " static const int16_t OperandMap [][" << Operands.size() |
| << "] = {\n"; |
| for (const auto &Entry : OperandMap) { |
| const std::map<unsigned, unsigned> &OpList = Entry.first; |
| OS << "{"; |
| |
| // Emit a row of the OperandMap table |
| for (unsigned i = 0, e = Operands.size(); i != e; ++i) |
| OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", "; |
| |
| OS << "},\n"; |
| } |
| OS << "};\n"; |
| |
| OS << " switch(Opcode) {\n"; |
| unsigned TableIndex = 0; |
| for (const auto &Entry : OperandMap) { |
| for (const std::string &Name : Entry.second) |
| OS << " case " << Name << ":\n"; |
| |
| OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n"; |
| } |
| OS << " default: return -1;\n"; |
| OS << " }\n"; |
| } else { |
| // There are no operands, so no need to emit anything |
| OS << " return -1;\n"; |
| } |
| OS << "}\n"; |
| OS << "} // end namespace " << Namespace << "\n"; |
| OS << "} // end namespace llvm\n"; |
| OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n"; |
| } |
| |
| /// Generate an enum for all the operand types for this target, under the |
| /// llvm::TargetNamespace::OpTypes namespace. |
| /// Operand types are all definitions derived of the Operand Target.td class. |
| void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, |
| const CodeGenTarget &Target) { |
| |
| StringRef Namespace = Target.getInstNamespace(); |
| std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand"); |
| |
| OS << "#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; |
| OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; |
| OS << "namespace llvm {\n"; |
| OS << "namespace " << Namespace << " {\n"; |
| OS << "namespace OpTypes {\n"; |
| OS << "enum OperandType {\n"; |
| |
| unsigned EnumVal = 0; |
| for (const Record *Op : Operands) { |
| if (!Op->isAnonymous()) |
| OS << " " << Op->getName() << " = " << EnumVal << ",\n"; |
| ++EnumVal; |
| } |
| |
| OS << " OPERAND_TYPE_LIST_END" << "\n};\n"; |
| OS << "} // end namespace OpTypes\n"; |
| OS << "} // end namespace " << Namespace << "\n"; |
| OS << "} // end namespace llvm\n"; |
| OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n"; |
| } |
| |
| void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS) { |
| RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate"); |
| if (TIIPredicates.empty()) |
| return; |
| |
| CodeGenTarget &Target = CDP.getTargetInfo(); |
| const StringRef TargetName = Target.getName(); |
| formatted_raw_ostream FOS(OS); |
| |
| FOS << "#ifdef GET_GENINSTRINFO_MC_DECL\n"; |
| FOS << "#undef GET_GENINSTRINFO_MC_DECL\n\n"; |
| |
| FOS << "namespace llvm {\n"; |
| FOS << "class MCInst;\n\n"; |
| |
| FOS << "namespace " << TargetName << "_MC {\n\n"; |
| |
| for (const Record *Rec : TIIPredicates) { |
| FOS << "bool " << Rec->getValueAsString("FunctionName") |
| << "(const MCInst &MI);\n"; |
| } |
| |
| FOS << "\n} // end " << TargetName << "_MC namespace\n"; |
| FOS << "} // end llvm namespace\n\n"; |
| |
| FOS << "#endif // GET_GENINSTRINFO_MC_DECL\n\n"; |
| |
| FOS << "#ifdef GET_GENINSTRINFO_MC_HELPERS\n"; |
| FOS << "#undef GET_GENINSTRINFO_MC_HELPERS\n\n"; |
| |
| FOS << "namespace llvm {\n"; |
| FOS << "namespace " << TargetName << "_MC {\n\n"; |
| |
| PredicateExpander PE; |
| PE.setExpandForMC(true); |
| for (const Record *Rec : TIIPredicates) { |
| FOS << "bool " << Rec->getValueAsString("FunctionName"); |
| FOS << "(const MCInst &MI) {\n"; |
| FOS << " return "; |
| PE.expandPredicate(FOS, Rec->getValueAsDef("Pred")); |
| FOS << ";\n}\n"; |
| } |
| |
| FOS << "\n} // end " << TargetName << "_MC namespace\n"; |
| FOS << "} // end llvm namespace\n\n"; |
| |
| FOS << "#endif // GET_GENISTRINFO_MC_HELPERS\n"; |
| } |
| |
| void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS) { |
| RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate"); |
| if (TIIPredicates.empty()) |
| return; |
| |
| formatted_raw_ostream FOS(OS); |
| PredicateExpander PE; |
| PE.setExpandForMC(false); |
| PE.setIndentLevel(2); |
| |
| for (const Record *Rec : TIIPredicates) { |
| FOS << "\n static bool " << Rec->getValueAsString("FunctionName"); |
| FOS << "(const MachineInstr &MI) {\n"; |
| FOS << " return "; |
| PE.expandPredicate(FOS, Rec->getValueAsDef("Pred")); |
| FOS << ";\n }\n"; |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Main Output. |
| //===----------------------------------------------------------------------===// |
| |
| // run - Emit the main instruction description records for the target... |
| void InstrInfoEmitter::run(raw_ostream &OS) { |
| emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS); |
| emitEnums(OS); |
| |
| OS << "#ifdef GET_INSTRINFO_MC_DESC\n"; |
| OS << "#undef GET_INSTRINFO_MC_DESC\n"; |
| |
| OS << "namespace llvm {\n\n"; |
| |
| CodeGenTarget &Target = CDP.getTargetInfo(); |
| const std::string &TargetName = Target.getName(); |
| Record *InstrInfo = Target.getInstructionSet(); |
| |
| // Keep track of all of the def lists we have emitted already. |
| std::map<std::vector<Record*>, unsigned> EmittedLists; |
| unsigned ListNumber = 0; |
| |
| // Emit all of the instruction's implicit uses and defs. |
| for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) { |
| Record *Inst = II->TheDef; |
| std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); |
| if (!Uses.empty()) { |
| unsigned &IL = EmittedLists[Uses]; |
| if (!IL) PrintDefList(Uses, IL = ++ListNumber, OS); |
| } |
| std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs"); |
| if (!Defs.empty()) { |
| unsigned &IL = EmittedLists[Defs]; |
| if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS); |
| } |
| } |
| |
| OperandInfoMapTy OperandInfoIDs; |
| |
| // Emit all of the operand info records. |
| EmitOperandInfo(OS, OperandInfoIDs); |
| |
| // Emit all of the MCInstrDesc records in their ENUM ordering. |
| // |
| OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n"; |
| ArrayRef<const CodeGenInstruction*> NumberedInstructions = |
| Target.getInstructionsByEnumValue(); |
| |
| SequenceToOffsetTable<std::string> InstrNames; |
| unsigned Num = 0; |
| for (const CodeGenInstruction *Inst : NumberedInstructions) { |
| // Keep a list of the instruction names. |
| InstrNames.add(Inst->TheDef->getName()); |
| // Emit the record into the table. |
| emitRecord(*Inst, Num++, InstrInfo, EmittedLists, OperandInfoIDs, OS); |
| } |
| OS << "};\n\n"; |
| |
| // Emit the array of instruction names. |
| InstrNames.layout(); |
| OS << "extern const char " << TargetName << "InstrNameData[] = {\n"; |
| InstrNames.emit(OS, printChar); |
| OS << "};\n\n"; |
| |
| OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {"; |
| Num = 0; |
| for (const CodeGenInstruction *Inst : NumberedInstructions) { |
| // Newline every eight entries. |
| if (Num % 8 == 0) |
| OS << "\n "; |
| OS << InstrNames.get(Inst->TheDef->getName()) << "U, "; |
| ++Num; |
| } |
| |
| OS << "\n};\n\n"; |
| |
| // MCInstrInfo initialization routine. |
| OS << "static inline void Init" << TargetName |
| << "MCInstrInfo(MCInstrInfo *II) {\n"; |
| OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " |
| << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " |
| << NumberedInstructions.size() << ");\n}\n\n"; |
| |
| OS << "} // end llvm namespace\n"; |
| |
| OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; |
| |
| // Create a TargetInstrInfo subclass to hide the MC layer initialization. |
| OS << "#ifdef GET_INSTRINFO_HEADER\n"; |
| OS << "#undef GET_INSTRINFO_HEADER\n"; |
| |
| std::string ClassName = TargetName + "GenInstrInfo"; |
| OS << "namespace llvm {\n"; |
| OS << "struct " << ClassName << " : public TargetInstrInfo {\n" |
| << " explicit " << ClassName |
| << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n" |
| << " ~" << ClassName << "() override = default;\n"; |
| |
| emitTIIHelperMethods(OS); |
| |
| OS << "\n};\n} // end llvm namespace\n"; |
| |
| OS << "#endif // GET_INSTRINFO_HEADER\n\n"; |
| |
| OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n"; |
| OS << "#undef GET_INSTRINFO_CTOR_DTOR\n"; |
| |
| OS << "namespace llvm {\n"; |
| OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n"; |
| OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; |
| OS << "extern const char " << TargetName << "InstrNameData[];\n"; |
| OS << ClassName << "::" << ClassName |
| << "(int CFSetupOpcode, int CFDestroyOpcode, int CatchRetOpcode, int ReturnOpcode)\n" |
| << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, ReturnOpcode) {\n" |
| << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName |
| << "InstrNameIndices, " << TargetName << "InstrNameData, " |
| << NumberedInstructions.size() << ");\n}\n"; |
| OS << "} // end llvm namespace\n"; |
| |
| OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n"; |
| |
| emitOperandNameMappings(OS, Target, NumberedInstructions); |
| |
| emitOperandTypesEnum(OS, Target); |
| |
| emitMCIIHelperMethods(OS); |
| } |
| |
| void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, |
| Record *InstrInfo, |
| std::map<std::vector<Record*>, unsigned> &EmittedLists, |
| const OperandInfoMapTy &OpInfo, |
| raw_ostream &OS) { |
| int MinOperands = 0; |
| if (!Inst.Operands.empty()) |
| // Each logical operand can be multiple MI operands. |
| MinOperands = Inst.Operands.back().MIOperandNo + |
| Inst.Operands.back().MINumOperands; |
| |
| OS << " { "; |
| OS << Num << ",\t" << MinOperands << ",\t" |
| << Inst.Operands.NumDefs << ",\t" |
| << Inst.TheDef->getValueAsInt("Size") << ",\t" |
| << SchedModels.getSchedClassIdx(Inst) << ",\t0"; |
| |
| CodeGenTarget &Target = CDP.getTargetInfo(); |
| |
| // Emit all of the target independent flags... |
| if (Inst.isPseudo) OS << "|(1ULL<<MCID::Pseudo)"; |
| if (Inst.isReturn) OS << "|(1ULL<<MCID::Return)"; |
| if (Inst.isBranch) OS << "|(1ULL<<MCID::Branch)"; |
| if (Inst.isIndirectBranch) OS << "|(1ULL<<MCID::IndirectBranch)"; |
| if (Inst.isCompare) OS << "|(1ULL<<MCID::Compare)"; |
| if (Inst.isMoveImm) OS << "|(1ULL<<MCID::MoveImm)"; |
| if (Inst.isMoveReg) OS << "|(1ULL<<MCID::MoveReg)"; |
| if (Inst.isBitcast) OS << "|(1ULL<<MCID::Bitcast)"; |
| if (Inst.isAdd) OS << "|(1ULL<<MCID::Add)"; |
| if (Inst.isTrap) OS << "|(1ULL<<MCID::Trap)"; |
| if (Inst.isSelect) OS << "|(1ULL<<MCID::Select)"; |
| if (Inst.isBarrier) OS << "|(1ULL<<MCID::Barrier)"; |
| if (Inst.hasDelaySlot) OS << "|(1ULL<<MCID::DelaySlot)"; |
| if (Inst.isCall) OS << "|(1ULL<<MCID::Call)"; |
| if (Inst.canFoldAsLoad) OS << "|(1ULL<<MCID::FoldableAsLoad)"; |
| if (Inst.mayLoad) OS << "|(1ULL<<MCID::MayLoad)"; |
| if (Inst.mayStore) OS << "|(1ULL<<MCID::MayStore)"; |
| if (Inst.isPredicable) OS << "|(1ULL<<MCID::Predicable)"; |
| if (Inst.isConvertibleToThreeAddress) OS << "|(1ULL<<MCID::ConvertibleTo3Addr)"; |
| if (Inst.isCommutable) OS << "|(1ULL<<MCID::Commutable)"; |
| if (Inst.isTerminator) OS << "|(1ULL<<MCID::Terminator)"; |
| if (Inst.isReMaterializable) OS << "|(1ULL<<MCID::Rematerializable)"; |
| if (Inst.isNotDuplicable) OS << "|(1ULL<<MCID::NotDuplicable)"; |
| if (Inst.Operands.hasOptionalDef) OS << "|(1ULL<<MCID::HasOptionalDef)"; |
| if (Inst.usesCustomInserter) OS << "|(1ULL<<MCID::UsesCustomInserter)"; |
| if (Inst.hasPostISelHook) OS << "|(1ULL<<MCID::HasPostISelHook)"; |
| if (Inst.Operands.isVariadic)OS << "|(1ULL<<MCID::Variadic)"; |
| if (Inst.hasSideEffects) OS << "|(1ULL<<MCID::UnmodeledSideEffects)"; |
| if (Inst.isAsCheapAsAMove) OS << "|(1ULL<<MCID::CheapAsAMove)"; |
| if (!Target.getAllowRegisterRenaming() || Inst.hasExtraSrcRegAllocReq) |
| OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)"; |
| if (!Target.getAllowRegisterRenaming() || Inst.hasExtraDefRegAllocReq) |
| OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)"; |
| if (Inst.isRegSequence) OS << "|(1ULL<<MCID::RegSequence)"; |
| if (Inst.isExtractSubreg) OS << "|(1ULL<<MCID::ExtractSubreg)"; |
| if (Inst.isInsertSubreg) OS << "|(1ULL<<MCID::InsertSubreg)"; |
| if (Inst.isConvergent) OS << "|(1ULL<<MCID::Convergent)"; |
| |
| // Emit all of the target-specific flags... |
| BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); |
| if (!TSF) |
| PrintFatalError("no TSFlags?"); |
| uint64_t Value = 0; |
| for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { |
| if (const auto *Bit = dyn_cast<BitInit>(TSF->getBit(i))) |
| Value |= uint64_t(Bit->getValue()) << i; |
| else |
| PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName()); |
| } |
| OS << ", 0x"; |
| OS.write_hex(Value); |
| OS << "ULL, "; |
| |
| // Emit the implicit uses and defs lists... |
| std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); |
| if (UseList.empty()) |
| OS << "nullptr, "; |
| else |
| OS << "ImplicitList" << EmittedLists[UseList] << ", "; |
| |
| std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); |
| if (DefList.empty()) |
| OS << "nullptr, "; |
| else |
| OS << "ImplicitList" << EmittedLists[DefList] << ", "; |
| |
| // Emit the operand info. |
| std::vector<std::string> OperandInfo = GetOperandInfo(Inst); |
| if (OperandInfo.empty()) |
| OS << "nullptr"; |
| else |
| OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; |
| |
| if (Inst.HasComplexDeprecationPredicate) |
| // Emit a function pointer to the complex predicate method. |
| OS << ", -1 " |
| << ",&get" << Inst.DeprecatedReason << "DeprecationInfo"; |
| else if (!Inst.DeprecatedReason.empty()) |
| // Emit the Subtarget feature. |
| OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason |
| << " ,nullptr"; |
| else |
| // Instruction isn't deprecated. |
| OS << ", -1 ,nullptr"; |
| |
| OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; |
| } |
| |
| // emitEnums - Print out enum values for all of the instructions. |
| void InstrInfoEmitter::emitEnums(raw_ostream &OS) { |
| OS << "#ifdef GET_INSTRINFO_ENUM\n"; |
| OS << "#undef GET_INSTRINFO_ENUM\n"; |
| |
| OS << "namespace llvm {\n\n"; |
| |
| CodeGenTarget Target(Records); |
| |
| // We must emit the PHI opcode first... |
| StringRef Namespace = Target.getInstNamespace(); |
| |
| if (Namespace.empty()) |
| PrintFatalError("No instructions defined!"); |
| |
| OS << "namespace " << Namespace << " {\n"; |
| OS << " enum {\n"; |
| unsigned Num = 0; |
| for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) |
| OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n"; |
| OS << " INSTRUCTION_LIST_END = " << Num << "\n"; |
| OS << " };\n\n"; |
| OS << "} // end " << Namespace << " namespace\n"; |
| OS << "} // end llvm namespace\n"; |
| OS << "#endif // GET_INSTRINFO_ENUM\n\n"; |
| |
| OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n"; |
| OS << "#undef GET_INSTRINFO_SCHED_ENUM\n"; |
| OS << "namespace llvm {\n\n"; |
| OS << "namespace " << Namespace << " {\n"; |
| OS << "namespace Sched {\n"; |
| OS << " enum {\n"; |
| Num = 0; |
| for (const auto &Class : SchedModels.explicit_classes()) |
| OS << " " << Class.Name << "\t= " << Num++ << ",\n"; |
| OS << " SCHED_LIST_END = " << Num << "\n"; |
| OS << " };\n"; |
| OS << "} // end Sched namespace\n"; |
| OS << "} // end " << Namespace << " namespace\n"; |
| OS << "} // end llvm namespace\n"; |
| |
| OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n"; |
| } |
| |
| namespace llvm { |
| |
| void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) { |
| InstrInfoEmitter(RK).run(OS); |
| EmitMapTable(RK, OS); |
| } |
| |
| } // end llvm namespace |