X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FInstrInfoEmitter.cpp;h=3d4da0ee288d114cf9bcef878b4ff8190f0a29e3;hb=7aa8a459227ea02263d92e48ef109da3c0e0a5fb;hp=718491e2b5445d2ee507f1f4a03c10f4cebd4971;hpb=8b50f9b8dcd6da00ddc961ecda967719eb745dee;p=oota-llvm.git diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 718491e2b54..3d4da0ee288 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -14,7 +14,9 @@ #include "InstrInfoEmitter.h" #include "CodeGenTarget.h" +#include "llvm/Target/TargetInstrInfo.h" #include "Record.h" +#include using namespace llvm; // runEnums - Print out enum values for all of the instructions. @@ -25,38 +27,34 @@ void InstrInfoEmitter::runEnums(std::ostream &OS) { CodeGenTarget Target; // We must emit the PHI opcode first... - Record *InstrInfo = Target.getInstructionSet(); - - std::string Namespace = Target.inst_begin()->second.Namespace; - - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << " enum {\n"; + std::string Namespace; + for (CodeGenTarget::inst_iterator II = Target.inst_begin(), + E = Target.inst_end(); II != E; ++II) { + if (II->second.Namespace != "TargetInstrInfo") { + Namespace = II->second.Namespace; + break; + } + } + + if (Namespace.empty()) { + cerr << "No instructions defined!\n"; + exit(1); + } std::vector NumberedInstructions; Target.getInstructionsByEnumValue(NumberedInstructions); + OS << "namespace " << Namespace << " {\n"; + OS << " enum {\n"; for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { OS << " " << NumberedInstructions[i]->TheDef->getName() - << ", \t// " << i << "\n"; + << "\t= " << i << ",\n"; } - OS << " INSTRUCTION_LIST_END\n"; - OS << " };\n"; - if (!Namespace.empty()) - OS << "}\n"; + OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; + OS << " };\n}\n"; OS << "} // End llvm namespace \n"; } -static std::vector GetDefList(ListInit *LI, const std::string &Name) { - std::vector Result; - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - if (DefInit *DI = dynamic_cast(LI->getElement(i))) - Result.push_back(DI->getDef()); - else - throw "Illegal value in '" + Name + "' list!"; - return Result; -} - void InstrInfoEmitter::printDefList(const std::vector &Uses, unsigned Num, std::ostream &OS) const { OS << "static const unsigned ImplicitList" << Num << "[] = { "; @@ -65,125 +63,170 @@ void InstrInfoEmitter::printDefList(const std::vector &Uses, OS << "0 };\n"; } -static std::vector GetOperandInfo(const CodeGenInstruction &Inst) { - std::vector Result; - if (Inst.hasVariableNumberOfOperands) - return Result; // No info for variable operand instrs. - +std::vector +InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { + std::vector Result; + for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) { - if (Inst.OperandList[i].Rec->isSubClassOf("RegisterClass")) - Result.push_back(Inst.OperandList[i].Rec); - else { - // This might be a multiple operand thing. - // FIXME: Targets like X86 have registers in their multi-operand operands. - for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) - Result.push_back(0); + // Handle aggregate operands and normal operands the same way by expanding + // either case into a list of operands for this op. + std::vector 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 = Inst.OperandList[i].MIOperandInfo; + + if (!MIOI || MIOI->getNumArgs() == 0) { + // Single, anonymous, operand. + OperandList.push_back(Inst.OperandList[i]); + } else { + for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) { + OperandList.push_back(Inst.OperandList[i]); + + Record *OpR = dynamic_cast(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("RegisterClass")) + Res += getQualifiedName(OpR) + "RegClassID, "; + else + Res += "0, "; + // Fill in applicable flags. + Res += "0"; + + // Ptr value whose register class is resolved via callback. + if (OpR->getName() == "ptr_rc") + Res += "|M_LOOK_UP_PTR_REG_CLASS"; + + // Predicate operands. Check to see if the original unexpanded operand + // was of type PredicateOperand. + if (j == 0 && Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand")) + Res += "|M_PREDICATE_OPERAND"; + + // Fill in constraint info. + Res += ", " + Inst.OperandList[i].Constraints[j]; + Result.push_back(Res); } } + return Result; } // run - Emit the main instruction description records for the target... void InstrInfoEmitter::run(std::ostream &OS) { + GatherItinClasses(); + EmitSourceFileHeader("Target Instruction Descriptors", OS); OS << "namespace llvm {\n\n"; CodeGenTarget Target; const std::string &TargetName = Target.getName(); Record *InstrInfo = Target.getInstructionSet(); - Record *PHI = InstrInfo->getValueAsDef("PHIInst"); - - // Emit empty implicit uses and defs lists - OS << "static const unsigned EmptyImpList[] = { 0 };\n"; // Keep track of all of the def lists we have emitted already. std::map, unsigned> EmittedLists; - std::map ListNumbers; unsigned ListNumber = 0; // Emit all of the instruction's implicit uses and defs. for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) { Record *Inst = II->second.TheDef; - ListInit *LI = Inst->getValueAsListInit("Uses"); - if (LI->getSize()) { - std::vector Uses = GetDefList(LI, Inst->getName()); + std::vector Uses = Inst->getValueAsListOfDefs("Uses"); + if (!Uses.empty()) { unsigned &IL = EmittedLists[Uses]; if (!IL) printDefList(Uses, IL = ++ListNumber, OS); - ListNumbers[LI] = IL; } - LI = Inst->getValueAsListInit("Defs"); - if (LI->getSize()) { - std::vector Uses = GetDefList(LI, Inst->getName()); - unsigned &IL = EmittedLists[Uses]; - if (!IL) printDefList(Uses, IL = ++ListNumber, OS); - ListNumbers[LI] = IL; + std::vector Defs = Inst->getValueAsListOfDefs("Defs"); + if (!Defs.empty()) { + unsigned &IL = EmittedLists[Defs]; + if (!IL) printDefList(Defs, IL = ++ListNumber, OS); } } - std::map, unsigned> OperandInfosEmitted; + std::map, unsigned> OperandInfosEmitted; unsigned OperandListNum = 0; - OperandInfosEmitted[std::vector()] = ++OperandListNum; + OperandInfosEmitted[std::vector()] = ++OperandListNum; // Emit all of the operand info records. OS << "\n"; for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) { - std::vector OperandInfo = GetOperandInfo(II->second); + std::vector OperandInfo = GetOperandInfo(II->second); unsigned &N = OperandInfosEmitted[OperandInfo]; if (N == 0) { N = ++OperandListNum; OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { "; - for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) { - if (Record *RC = OperandInfo[i]) { - OS << "{ &" << getQualifiedName(RC) << "RegClass }, "; - } else { - OS << "{ 0 }, "; - } - } + for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) + OS << "{ " << OperandInfo[i] << " }, "; OS << "};\n"; } } - // Emit all of the TargetInstrDescriptor records. + // Emit all of the TargetInstrDescriptor records in their ENUM ordering. // OS << "\nstatic const TargetInstrDescriptor " << TargetName << "Insts[] = {\n"; - emitRecord(Target.getPHIInstruction(), 0, InstrInfo, ListNumbers, - OperandInfosEmitted, OS); + std::vector NumberedInstructions; + Target.getInstructionsByEnumValue(NumberedInstructions); - unsigned i = 0; - for (CodeGenTarget::inst_iterator II = Target.inst_begin(), - E = Target.inst_end(); II != E; ++II) - if (II->second.TheDef != PHI) - emitRecord(II->second, ++i, InstrInfo, ListNumbers, - OperandInfosEmitted, OS); + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) + emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, + OperandInfosEmitted, OS); OS << "};\n"; OS << "} // End llvm namespace \n"; } void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, - std::map &ListNumbers, - std::map, unsigned> &OpInfo, + std::map, unsigned> &EmittedLists, + std::map, unsigned> &OpInfo, std::ostream &OS) { - int NumOperands; - if (Inst.hasVariableNumberOfOperands) - NumOperands = -1; - else if (!Inst.OperandList.empty()) + int MinOperands; + if (!Inst.OperandList.empty()) // Each logical operand can be multiple MI operands. - NumOperands = Inst.OperandList.back().MIOperandNo + + MinOperands = Inst.OperandList.back().MIOperandNo + Inst.OperandList.back().MINumOperands; else - NumOperands = 0; + MinOperands = 0; - OS << " { \""; + OS << " { "; + OS << Num << ",\t" << MinOperands << ",\t\""; + if (Inst.Name.empty()) OS << Inst.TheDef->getName(); else OS << Inst.Name; - OS << "\",\t" << NumOperands << ", -1, 0, false, 0, 0, 0, 0"; + + unsigned ItinClass = !IsItineraries ? 0 : + ItinClassNumber(Inst.TheDef->getValueAsDef("Itinerary")->getName()); + + OS << "\",\t" << ItinClass << ", 0"; + + // Try to determine (from the pattern), if the instruction is a store. + bool isStore = false; + if (dynamic_cast(Inst.TheDef->getValueInit("Pattern"))) { + ListInit *LI = Inst.TheDef->getValueAsListInit("Pattern"); + if (LI && LI->getSize() > 0) { + DagInit *Dag = (DagInit *)LI->getElement(0); + DefInit *OpDef = dynamic_cast(Dag->getOperator()); + if (OpDef) { + Record *Operator = OpDef->getDef(); + if (Operator->isSubClassOf("SDNode")) { + const std::string Opcode = Operator->getValueAsString("Opcode"); + if (Opcode == "ISD::STORE" || Opcode == "ISD::TRUNCSTORE") + isStore = true; + } + } + } + } // Emit all of the target indepedent flags... if (Inst.isReturn) OS << "|M_RET_FLAG"; @@ -192,13 +235,15 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.hasDelaySlot) OS << "|M_DELAY_SLOT_FLAG"; if (Inst.isCall) OS << "|M_CALL_FLAG"; if (Inst.isLoad) OS << "|M_LOAD_FLAG"; - if (Inst.isStore) OS << "|M_STORE_FLAG"; - if (Inst.isTwoAddress) OS << "|M_2_ADDR_FLAG"; + if (Inst.isStore || isStore) OS << "|M_STORE_FLAG"; + if (Inst.isPredicated) OS << "|M_PREDICATED"; if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR"; if (Inst.isCommutable) OS << "|M_COMMUTABLE"; if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG"; - if (Inst.usesCustomDAGSChedInserter) + if (Inst.usesCustomDAGSchedInserter) OS << "|M_USES_CUSTOM_DAG_SCHED_INSERTION"; + if (Inst.hasVariableNumberOfOperands) + OS << "|M_VARIABLE_OPS"; OS << ", 0"; // Emit all of the target-specific flags... @@ -215,20 +260,20 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << ", "; // Emit the implicit uses and defs lists... - LI = Inst.TheDef->getValueAsListInit("Uses"); - if (!LI->getSize()) - OS << "EmptyImpList, "; + std::vector UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); + if (UseList.empty()) + OS << "NULL, "; else - OS << "ImplicitList" << ListNumbers[LI] << ", "; + OS << "ImplicitList" << EmittedLists[UseList] << ", "; - LI = Inst.TheDef->getValueAsListInit("Defs"); - if (!LI->getSize()) - OS << "EmptyImpList, "; + std::vector DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); + if (DefList.empty()) + OS << "NULL, "; else - OS << "ImplicitList" << ListNumbers[LI] << ", "; + OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. - std::vector OperandInfo = GetOperandInfo(Inst); + std::vector OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) OS << "0"; else @@ -237,6 +282,30 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } +struct LessRecord { + bool operator()(const Record *Rec1, const Record *Rec2) const { + return Rec1->getName() < Rec2->getName(); + } +}; +void InstrInfoEmitter::GatherItinClasses() { + std::vector DefList = + Records.getAllDerivedDefinitions("InstrItinClass"); + IsItineraries = !DefList.empty(); + + if (!IsItineraries) return; + + std::sort(DefList.begin(), DefList.end(), LessRecord()); + + for (unsigned i = 0, N = DefList.size(); i < N; i++) { + Record *Def = DefList[i]; + ItinClassMap[Def->getName()] = i; + } +} + +unsigned InstrInfoEmitter::ItinClassNumber(std::string ItinName) { + return ItinClassMap[ItinName]; +} + void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, IntInit *ShiftInt, std::ostream &OS) { if (Val == 0 || ShiftInt == 0) @@ -244,8 +313,13 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, RecordVal *RV = R->getValue(Val->getValue()); int Shift = ShiftInt->getValue(); - if (RV == 0 || RV->getValue() == 0) - throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!"; + if (RV == 0 || RV->getValue() == 0) { + // This isn't an error if this is a builtin instruction. + if (R->getName() != "PHI" && R->getName() != "INLINEASM") + throw R->getName() + " doesn't have a field named '" + + Val->getValue() + "'!"; + return; + } Init *Value = RV->getValue(); if (BitInit *BI = dynamic_cast(Value)) { @@ -256,17 +330,26 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, Init *I = BI->convertInitializerTo(new IntRecTy()); if (I) if (IntInit *II = dynamic_cast(I)) { - if (II->getValue()) - OS << "|(" << II->getValue() << "<<" << Shift << ")"; + if (II->getValue()) { + if (Shift) + OS << "|(" << II->getValue() << "<<" << Shift << ")"; + else + OS << "|" << II->getValue(); + } return; } } else if (IntInit *II = dynamic_cast(Value)) { - if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")"; + if (II->getValue()) { + if (Shift) + OS << "|(" << II->getValue() << "<<" << Shift << ")"; + else + OS << II->getValue(); + } return; } - std::cerr << "Unhandled initializer: " << *Val << "\n"; + cerr << "Unhandled initializer: " << *Val << "\n"; throw "In record '" + R->getName() + "' for TSFlag emission."; }