X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FInstrInfoEmitter.cpp;h=1df8ae54c7167bef2c968a62a1f6b0d94ed9dcf1;hb=7a88b655ccad0f128ea1a5e8ca433a8827a24ff3;hp=8b3efd33f4dcfaac2ae640d2f7c04cb2a33c3def;hpb=bf1aab15075884933e94a3aa950d88a7f16b5989;p=oota-llvm.git diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 8b3efd33f4d..1df8ae54c71 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -12,15 +12,65 @@ // //===----------------------------------------------------------------------===// -#include "InstrInfoEmitter.h" + +#include "CodeGenDAGPatterns.h" +#include "CodeGenSchedule.h" #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" -#include "llvm/TableGen/Record.h" +#include "TableGenBackends.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include #include +#include +#include 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, 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::vector > OpNameMapTy; + typedef std::map::iterator StrUintMapIter; + void emitRecord(const CodeGenInstruction &Inst, unsigned Num, + Record *InstrInfo, + std::map, unsigned> &EL, + const OperandInfoMapTy &OpInfo, + raw_ostream &OS); + void initOperandMapData( + const std::vector NumberedInstructions, + const std::string &Namespace, + std::map &Operands, + OpNameMapTy &OperandMap); + void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target, + const std::vector &NumberedInstructions); + + // Operand information. + void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); + std::vector GetOperandInfo(const CodeGenInstruction &Inst); +}; +} // End anonymous namespace + static void PrintDefList(const std::vector &Uses, unsigned Num, raw_ostream &OS) { OS << "static const uint16_t ImplicitList" << Num << "[] = { "; @@ -29,23 +79,6 @@ static void PrintDefList(const std::vector &Uses, OS << "0 };\n"; } -//===----------------------------------------------------------------------===// -// Instruction Itinerary Information. -//===----------------------------------------------------------------------===// - -void InstrInfoEmitter::GatherItinClasses() { - std::vector DefList = - Records.getAllDerivedDefinitions("InstrItinClass"); - std::sort(DefList.begin(), DefList.end(), LessRecord()); - - for (unsigned i = 0, N = DefList.size(); i < N; i++) - ItinClassMap[DefList[i]->getName()] = i; -} - -unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) { - return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()]; -} - //===----------------------------------------------------------------------===// // Operand Info Emission. //===----------------------------------------------------------------------===// @@ -72,7 +105,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) { OperandList.push_back(Inst.Operands[i]); - Record *OpR = dynamic_cast(MIOI->getArg(j))->getDef(); + Record *OpR = cast(MIOI->getArg(j))->getDef(); OperandList.back().Rec = OpR; } } @@ -157,17 +190,130 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, } } + +/// 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( + const std::vector NumberedInstructions, + const std::string &Namespace, + std::map &Operands, + OpNameMapTy &OperandMap) { + + unsigned NumOperands = 0; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + const CodeGenInstruction *Inst = NumberedInstructions[i]; + if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) { + continue; + } + std::map OpList; + for (unsigned j = 0, je = Inst->Operands.size(); j != je; ++j) { + const CGIOperandList::OperandInfo &Info = Inst->Operands[j]; + StrUintMapIter I = Operands.find(Info.Name); + + if (I == Operands.end()) { + I = Operands.insert(Operands.begin(), + std::pair(Info.Name, NumOperands++)); + } + OpList[I->second] = Info.MIOperandNo; + } + OperandMap[OpList].push_back(Namespace + "::" + Inst->TheDef->getName()); + } +} + +/// 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, + const std::vector &NumberedInstructions) { + + const std::string &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 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 {"; + OS << "namespace " << Namespace << " {\n"; + OS << "namespace " << OpNameNS << " { \n"; + OS << "enum {\n"; + for (StrUintMapIter i = Operands.begin(), e = Operands.end(); i != e; ++i) + OS << " " << i->first << " = " << i->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"; + + OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n"; + OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; + OS << "namespace llvm {"; + OS << "namespace " << Namespace << " {\n"; + OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n"; + OS << " static const int16_t OperandMap []["<< Operands.size() << "] = {\n"; + for (OpNameMapTy::iterator i = OperandMap.begin(), e = OperandMap.end(); + i != e; ++i) { + const std::map &OpList = i->first; + OS << "{"; + + // Emit a row of the OperandMap table + for (unsigned ii = 0, ie = Operands.size(); ii != ie; ++ii) + OS << (OpList.count(ii) == 0 ? -1 : (int)OpList.find(ii)->second) << ", "; + + OS << "},\n"; + } + OS << "};\n"; + + OS << " switch(Opcode) {\n"; + unsigned TableIndex = 0; + for (OpNameMapTy::iterator i = OperandMap.begin(), e = OperandMap.end(); + i != e; ++i) { + std::vector &OpcodeList = i->second; + + for (unsigned ii = 0, ie = OpcodeList.size(); ii != ie; ++ii) + OS << " case " << OpcodeList[ii] << ":\n"; + + OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n"; + } + OS << " default: return -1;\n"; + OS << " }\n"; + OS << "}\n"; + OS << "} // End namespace " << Namespace << "\n"; + OS << "} // End namespace llvm\n"; + OS << "#endif //GET_INSTRINFO_NAMED_OPS\n"; + +} + //===----------------------------------------------------------------------===// // Main Output. //===----------------------------------------------------------------------===// // run - Emit the main instruction description records for the target... void InstrInfoEmitter::run(raw_ostream &OS) { + emitSourceFileHeader("Target Instruction Enum Values", OS); emitEnums(OS); - GatherItinClasses(); - - EmitSourceFileHeader("Target Instruction Descriptors", OS); + emitSourceFileHeader("Target Instruction Descriptors", OS); OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n"; OS << "#undef GET_INSTRINFO_MC_DESC\n"; @@ -253,7 +399,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { std::string ClassName = TargetName + "GenInstrInfo"; OS << "namespace llvm {\n"; - OS << "struct " << ClassName << " : public TargetInstrInfoImpl {\n" + OS << "struct " << ClassName << " : public TargetInstrInfo {\n" << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n" << "};\n"; OS << "} // End llvm namespace \n"; @@ -268,13 +414,15 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; OS << "extern const char " << TargetName << "InstrNameData[];\n"; OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" - << " : TargetInstrInfoImpl(SO, DO) {\n" + << " : TargetInstrInfo(SO, DO) {\n" << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " << NumberedInstructions.size() << ");\n}\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_INSTRINFO_CTOR\n\n"; + + emitOperandNameMappings(OS, Target, NumberedInstructions); } void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, @@ -283,7 +431,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, const OperandInfoMapTy &OpInfo, raw_ostream &OS) { int MinOperands = 0; - if (!Inst.Operands.size() == 0) + if (!Inst.Operands.empty()) // Each logical operand can be multiple MI operands. MinOperands = Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands; @@ -291,7 +439,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << " { "; OS << Num << ",\t" << MinOperands << ",\t" << Inst.Operands.NumDefs << ",\t" - << getItinClassNumber(Inst.TheDef) << ",\t" + << SchedModels.getSchedClassIdx(Inst) << ",\t" << Inst.TheDef->getValueAsInt("Size") << ",\t0"; // Emit all of the target indepedent flags... @@ -302,6 +450,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isCompare) OS << "|(1<getValueAsBitsInit("TSFlags"); - if (!TSF) throw "no TSFlags?"; + if (!TSF) + PrintFatalError("no TSFlags?"); uint64_t Value = 0; for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { - if (BitInit *Bit = dynamic_cast(TSF->getBit(i))) + if (BitInit *Bit = dyn_cast(TSF->getBit(i))) Value |= uint64_t(Bit->getValue()) << i; else - throw "Invalid TSFlags bit in " + Inst.TheDef->getName(); + PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName()); } OS << ", 0x"; OS.write_hex(Value); @@ -362,7 +512,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, // emitEnums - Print out enum values for all of the instructions. void InstrInfoEmitter::emitEnums(raw_ostream &OS) { - EmitSourceFileHeader("Target Instruction Enum Values", OS); OS << "\n#ifdef GET_INSTRINFO_ENUM\n"; OS << "#undef GET_INSTRINFO_ENUM\n"; @@ -394,3 +543,12 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { OS << "#endif // GET_INSTRINFO_ENUM\n\n"; } + +namespace llvm { + +void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) { + InstrInfoEmitter(RK).run(OS); + EmitMapTable(RK, OS); +} + +} // End llvm namespace