diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 26423d02ffc..aaef0417b5a 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -60,6 +60,9 @@ namespace llvm { /// MIOperandInfo - Default MI operand type. Note an operand may be made /// up of multiple MI operands. DagInit *MIOperandInfo; + + /// Constraint info for this operand. + std::string Constraint; OperandInfo(Record *R, const std::string &N, const std::string &PMN, unsigned MION, unsigned MINO, DagInit *MIOI) @@ -71,14 +74,6 @@ namespace llvm { /// type (which is a record). std::vector OperandList; - /// ConstraintStr - The operand constraints string. - /// - std::string ConstraintStr; - - /// ConstraintsList - List of constraints, encoded into one unsigned int per - /// operand. - std::vector ConstraintsList; - // Various boolean values we track for the instruction. bool isReturn; bool isBranch; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 5893a58623a..aaf21b5d6c0 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -19,7 +19,6 @@ #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Target/TargetInstrInfo.h" #include #include using namespace llvm; @@ -274,8 +273,8 @@ bool CodeGenTarget::isLittleEndianEncoding() const { return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); } -static std::pair parseConstraint(const std::string &CStr, - CodeGenInstruction *I) { +static std::string ParseConstraint(const std::string &CStr, + CodeGenInstruction *I, unsigned &DestOp) { const std::string ops("="); // FIXME: Only supports TIED_TO for now. std::string::size_type pos = CStr.find_first_of(ops); assert(pos != std::string::npos && "Unrecognized constraint"); @@ -286,26 +285,24 @@ static std::pair parseConstraint(const std::string &CStr, std::string::size_type wpos = Name.find_first_of(delims); if (wpos != std::string::npos) Name = Name.substr(0, wpos); - unsigned FIdx = I->getOperandNamed(Name); + DestOp = I->getOperandNamed(Name); Name = CStr.substr(pos+1); wpos = Name.find_first_not_of(delims); if (wpos != std::string::npos) Name = Name.substr(wpos+1); + unsigned TIdx = I->getOperandNamed(Name); - if (TIdx >= FIdx) + if (TIdx >= DestOp) throw "Illegal tied-to operand constraint '" + CStr + "'"; - return std::make_pair(FIdx, (TIdx << 16) | - (1 << (unsigned)TargetInstrInfo::TIED_TO)); + + // Build the string. + return "((" + utostr(TIdx) + " << 16) | TargetInstrInfo::TIED_TO)"; } -static std::vector parseConstraints(const std::string &CStr, - CodeGenInstruction *I) { - unsigned NumOps = I->OperandList.size(); - std::vector Res(NumOps, 0); - if (CStr == "") - return Res; - +static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) { + if (CStr.empty()) return; + const std::string delims(","); std::string::size_type bidx, eidx; @@ -314,13 +311,16 @@ static std::vector parseConstraints(const std::string &CStr, eidx = CStr.find_first_of(delims, bidx); if (eidx == std::string::npos) eidx = CStr.length(); - std::pair C = - parseConstraint(CStr.substr(bidx, eidx), I); - Res[C.first] = C.second; + + unsigned OpNo; + std::string Constr = ParseConstraint(CStr.substr(bidx, eidx), I, OpNo); + assert(OpNo < I->OperandList.size() && "Invalid operand no?"); + + if (!I->OperandList[OpNo].Constraint.empty()) + throw "Operand #" + utostr(OpNo) + " cannot have multiple constraints!"; + I->OperandList[OpNo].Constraint = Constr; bidx = CStr.find_first_not_of(delims, eidx); } - - return Res; } CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) @@ -403,8 +403,17 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) MIOperandNo += NumOps; } - ConstraintStr = R->getValueAsString("Constraints"); - ConstraintsList = parseConstraints(ConstraintStr, this); + ParseConstraints(R->getValueAsString("Constraints"), this); + + // For backward compatibility: isTwoAddress means operand 1 is tied to + // operand 0. + if (isTwoAddress && OperandList[1].Constraint.empty()) + OperandList[1].Constraint = "((0 << 16) | TargetInstrInfo::TIED_TO)"; + + // Any operands with unset constraints get 0 as their constraint. + for (unsigned op = 0, e = OperandList.size(); op != e; ++op) + if (OperandList[op].Constraint.empty()) + OperandList[op].Constraint = "0"; } diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 41fb6969944..9202308ffdb 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -63,35 +63,52 @@ void InstrInfoEmitter::printDefList(const std::vector &Uses, OS << "0 };\n"; } -static std::vector > -GetOperandInfo(const CodeGenInstruction &Inst) { - std::vector > Result; +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(std::make_pair(Inst.OperandList[i].Rec, - Inst.ConstraintsList[i])); + std::string OpStr = getQualifiedName(Inst.OperandList[i].Rec); + OpStr += "RegClassID, 0, "; + OpStr += Inst.OperandList[i].Constraint; + + Result.push_back(OpStr); } else { - // This might be a multiple operand thing. - // Targets like X86 have registers in their multi-operand operands. + // 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; - unsigned NumDefs = MIOI->getNumArgs(); + for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) { - if (NumDefs <= j) { - Result.push_back(std::make_pair((Record*)0, Inst.ConstraintsList[i])); - } else { - DefInit *Def = dynamic_cast(MIOI->getArg(j)); - Result.push_back(std::make_pair(Def ? Def->getDef() : 0, - Inst.ConstraintsList[i])); - } + Record *OpR = 0; + if (MIOI && j < MIOI->getNumArgs()) + if (DefInit *Def = dynamic_cast(MIOI->getArg(j))) + OpR = Def->getDef(); + + + std::string Res; + + if (OpR && 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 && OpR->getName() == "ptr_rc") + Res += "|M_LOOK_UP_PTR_REG_CLASS"; + + // fill in constraint info. + Res += ", " + Inst.OperandList[i].Constraint; + + Result.push_back(Res); } } } - // For backward compatibility: isTwoAddress means operand 1 is tied to - // operand 0. - if (Inst.isTwoAddress) - Result[1].second |= (0 << 16) | (1 << (unsigned)TargetInstrInfo::TIED_TO); - return Result; } @@ -127,34 +144,21 @@ void InstrInfoEmitter::run(std::ostream &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) { - Record *RC = OperandInfo[i].first; - // FIXME: We only care about register operands for now. - if (RC && RC->isSubClassOf("RegisterClass")) - OS << "{ " << getQualifiedName(RC) << "RegClassID, 0, "; - else if (RC && RC->getName() == "ptr_rc") - // Ptr value whose register class is resolved via callback. - OS << "{ 0, 1, "; - else - OS << "{ 0, 0, "; - OS << OperandInfo[i].second << " }, "; - } + for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) + OS << "{ " << OperandInfo[i] << " }, "; OS << "};\n"; } } @@ -176,7 +180,7 @@ void InstrInfoEmitter::run(std::ostream &OS) { void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map, unsigned> &EmittedLists, - std::map >, unsigned> &OpInfo, + std::map, unsigned> &OpInfo, std::ostream &OS) { int MinOperands; if (!Inst.OperandList.empty()) @@ -262,7 +266,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. - std::vector > OperandInfo = GetOperandInfo(Inst); + std::vector OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) OS << "0"; else diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index 8d27305c0f5..adc871129e1 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -45,12 +45,13 @@ private: void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map, unsigned> &EL, - std::map >, unsigned> &OpInfo, + std::map, unsigned> &OpInfo, std::ostream &OS); void GatherItinClasses(); unsigned ItinClassNumber(std::string ItinName); void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift, std::ostream &OS); + std::vector GetOperandInfo(const CodeGenInstruction &Inst); }; } // End llvm namespace