Index: include/llvm/MC/MCInstrDesc.h =================================================================== --- include/llvm/MC/MCInstrDesc.h +++ include/llvm/MC/MCInstrDesc.h @@ -20,9 +20,9 @@ #include namespace llvm { - class MCInst; - class MCSubtargetInfo; - class FeatureBitset; +class MCInst; +class MCSubtargetInfo; +class FeatureBitset; //===----------------------------------------------------------------------===// // Machine Operand Flags and Description @@ -60,7 +60,7 @@ OPERAND_FIRST_TARGET = 12, }; -} +} // namespace MCOI /// This holds information about one operand of a machine instruction, /// indicating the register class for register operands, etc. @@ -152,7 +152,21 @@ Add, Trap }; -} +} // namespace MCID + +/// \brief Defines an operand group. +/// +/// Many machine operands are aggregates of multiple target operands (e.g. +/// register, immediate) and during codegen it is not always clear how many +/// those operands to read. This type provides this information. +class MIOperandInfo { +public: + int16_t MINo; + int16_t Type; + int16_t OpsNum; + + bool isTargetType() { return Type >= MCOI::OPERAND_FIRST_TARGET; }; +}; /// Describe properties that are true of each instruction in the target /// description file. This captures information about side effects, register @@ -162,6 +176,7 @@ class MCInstrDesc { public: unsigned short Opcode; // The opcode number + unsigned short NumMIOperands; // Num of logical operands unsigned short NumOperands; // Num of args (may be more if variable_ops) unsigned char NumDefs; // Num of args that are definitions unsigned char Size; // Number of bytes in encoding. @@ -170,6 +185,7 @@ uint64_t TSFlags; // Target Specific Flag values const MCPhysReg *ImplicitUses; // Registers implicitly read by this instr const MCPhysReg *ImplicitDefs; // Registers implicitly defined by this instr + const MIOperandInfo *MIOpInfo; // 'NumMIOperands' entries about operands const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands // Subtarget feature that this is deprecated on, if any // -1 implies this is not deprecated by any single feature. It may still be @@ -375,7 +391,6 @@ /// override accordingly. bool isInsertSubregLike() const { return Flags & (1ULL << MCID::InsertSubreg); } - /// Return true if this instruction is convergent. /// /// Convergent instructions may not be made control-dependent on any Index: utils/TableGen/InstrInfoEmitter.cpp =================================================================== --- utils/TableGen/InstrInfoEmitter.cpp +++ utils/TableGen/InstrInfoEmitter.cpp @@ -74,7 +74,8 @@ void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map, unsigned> &EL, - const OperandInfoMapTy &OpInfo, + const OperandInfoMapTy &MIOpInfo, + const OperandInfoMapTy &MCOpInfo, raw_ostream &OS); void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target); void initOperandMapData( @@ -86,8 +87,12 @@ ArrayRef NumberedInstructions); // Operand information. - void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); - std::vector GetOperandInfo(const CodeGenInstruction &Inst); + void EmitMIOperandInfo(raw_ostream &OS, OperandInfoMapTy &MCOperandInfoIDs); + std::vector GetMIOperandInfo(const CodeGenTarget &Target, + const CodeGenInstruction &Inst); + + void EmitMCOperandInfo(raw_ostream &OS, OperandInfoMapTy &MCOperandInfoIDs); + std::vector GetMCOperandInfo(const CodeGenInstruction &Inst); }; } // end anonymous namespace @@ -105,7 +110,62 @@ //===----------------------------------------------------------------------===// std::vector -InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { +InstrInfoEmitter::GetMIOperandInfo(const CodeGenTarget &Target, + const CodeGenInstruction &Inst) { + + std::vector Result; + + const std::string &Namespace = Target.getInstNamespace(); + + for (auto &Op : Inst.Operands) { + + // One record + std::string Res; + + // 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) { + Res = std::to_string(Op.MIOperandNo) + ", " + Op.OperandType + ", 1"; + } else { + Res = std::to_string(Op.MIOperandNo) + ", " + Namespace + + "::MIOpTypes::" + Op.Rec->getName().str() + ", " + + std::to_string(Op.MINumOperands); + } + + Result.push_back(Res); + } + + return Result; +} + +void InstrInfoEmitter::EmitMIOperandInfo(raw_ostream &OS, + OperandInfoMapTy &MIOperandInfoIDs) { + // ID #0 is for no operand info. + unsigned OperandListNum = 0; + MIOperandInfoIDs[std::vector()] = ++OperandListNum; + + OS << "\n"; + const CodeGenTarget &Target = CDP.getTargetInfo(); + for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { + std::vector OperandInfo = GetMIOperandInfo(Target, *Inst); + unsigned &N = MIOperandInfoIDs[OperandInfo]; + if (N != 0) + continue; + + N = ++OperandListNum; + OS << "static const MIOperandInfo MIOperandInfo" << N << "[] = { "; + for (const std::string &Info : OperandInfo) + OS << "{ " << Info << " }, "; + OS << "};\n"; + } +} + +std::vector +InstrInfoEmitter::GetMCOperandInfo(const CodeGenInstruction &Inst) { std::vector Result; for (auto &Op : Inst.Operands) { @@ -189,21 +249,21 @@ return Result; } -void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, - OperandInfoMapTy &OperandInfoIDs) { +void InstrInfoEmitter::EmitMCOperandInfo(raw_ostream &OS, + OperandInfoMapTy &MCOperandInfoIDs) { // ID #0 is for no operand info. unsigned OperandListNum = 0; - OperandInfoIDs[std::vector()] = ++OperandListNum; + MCOperandInfoIDs[std::vector()] = ++OperandListNum; OS << "\n"; const CodeGenTarget &Target = CDP.getTargetInfo(); for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { - std::vector OperandInfo = GetOperandInfo(*Inst); - unsigned &N = OperandInfoIDs[OperandInfo]; + std::vector OperandInfo = GetMCOperandInfo(*Inst); + unsigned &N = MCOperandInfoIDs[OperandInfo]; if (N != 0) continue; N = ++OperandListNum; - OS << "static const MCOperandInfo OperandInfo" << N << "[] = { "; + OS << "static const MCOperandInfo MCOperandInfo" << N << "[] = { "; for (const std::string &Info : OperandInfo) OS << "{ " << Info << " }, "; OS << "};\n"; @@ -211,7 +271,7 @@ } /// 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 @@ -330,25 +390,23 @@ StringRef Namespace = Target.getInstNamespace(); std::vector 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"; + OS << "namespace MIOpTypes {\n"; + OS << "enum MIOperandType {\n"; - unsigned EnumVal = 0; + bool First = true; for (const Record *Op : Operands) { - if (!Op->isAnonymous()) - OS << " " << Op->getName() << " = " << EnumVal << ",\n"; - ++EnumVal; + OS << " " << Op->getName(); + if (First) { + OS << " = llvm::MCOI::OPERAND_FIRST_TARGET"; + First = false; + } + OS << ",\n"; } 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, @@ -428,11 +486,23 @@ emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS); emitEnums(OS); + // Get the MI types separately from data + OS << "#ifdef GET_INSTRINFO_MI_OPS_INFO\n"; + OS << "#undef GET_INSTRINFO_MI_OPS_INFO\n"; + OS << "namespace llvm {\n\n"; + + emitOperandTypesEnum(OS, CDP.getTargetInfo()); + + OS << "} // end llvm namespace\n"; + OS << "#endif // GET_INSTRINFO_MI_OPS_INFO\n\n"; + OS << "#ifdef GET_INSTRINFO_MC_DESC\n"; OS << "#undef GET_INSTRINFO_MC_DESC\n"; OS << "namespace llvm {\n\n"; + emitOperandTypesEnum(OS, CDP.getTargetInfo()); + CodeGenTarget &Target = CDP.getTargetInfo(); const std::string &TargetName = Target.getName(); Record *InstrInfo = Target.getInstructionSet(); @@ -456,10 +526,12 @@ } } - OperandInfoMapTy OperandInfoIDs; + OperandInfoMapTy MIOperandInfoIDs; + OperandInfoMapTy MCOperandInfoIDs; // Emit all of the operand info records. - EmitOperandInfo(OS, OperandInfoIDs); + EmitMIOperandInfo(OS, MIOperandInfoIDs); + EmitMCOperandInfo(OS, MCOperandInfoIDs); // Emit all of the MCInstrDesc records in their ENUM ordering. // @@ -473,7 +545,9 @@ // 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); + emitRecord( + *Inst, Num++, InstrInfo, EmittedLists, + MIOperandInfoIDs, MCOperandInfoIDs, OS); } OS << "};\n\n"; @@ -542,24 +616,27 @@ emitOperandNameMappings(OS, Target, NumberedInstructions); - emitOperandTypesEnum(OS, Target); - emitMCIIHelperMethods(OS, TargetName); } void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, - std::map, unsigned> &EmittedLists, - const OperandInfoMapTy &OpInfo, + std::map, unsigned> &EmittedLists, + const OperandInfoMapTy &MIOpInfo, + const OperandInfoMapTy &MCOpInfo, raw_ostream &OS) { int MinOperands = 0; - if (!Inst.Operands.empty()) + 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" + OS << Num << ",\t" + << Inst.Operands.size() << ",\t" + << MinOperands << ",\t" << Inst.Operands.NumDefs << ",\t" << Inst.TheDef->getValueAsInt("Size") << ",\t" << SchedModels.getSchedClassIdx(Inst) << ",\t0"; @@ -634,11 +711,19 @@ OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. - std::vector OperandInfo = GetOperandInfo(Inst); - if (OperandInfo.empty()) + std::vector MIOperandInfo = + GetMIOperandInfo(CDP.getTargetInfo(), Inst); + if (MIOperandInfo.empty()) + OS << "nullptr"; + else + OS << "MIOperandInfo" << MIOpInfo.find(MIOperandInfo)->second; + OS << ", "; + + std::vector MCOperandInfo = GetMCOperandInfo(Inst); + if (MCOperandInfo.empty()) OS << "nullptr"; else - OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; + OS << "MCOperandInfo" << MCOpInfo.find(MCOperandInfo)->second; if (Inst.HasComplexDeprecationPredicate) // Emit a function pointer to the complex predicate method.