-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");
- std::string Name = CStr.substr(1, pos); // Skip '$'
-
- // TIED_TO: $src1 = $dst
- const std::string delims(" \t");
- std::string::size_type wpos = Name.find_first_of(delims);
- if (wpos != std::string::npos)
- Name = Name.substr(0, wpos);
- 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 >= DestOp)
- throw "Illegal tied-to operand constraint '" + CStr + "'";
-
- // Build the string.
- return "((" + utostr(TIdx) + " << 16) | (1 << TargetInstrInfo::TIED_TO))";
-}
-
-static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
- if (CStr.empty()) return;
-
- const std::string delims(",");
- std::string::size_type bidx, eidx;
-
- bidx = CStr.find_first_not_of(delims);
- while (bidx != std::string::npos) {
- eidx = CStr.find_first_of(delims, bidx);
- if (eidx == std::string::npos)
- eidx = CStr.length();
-
- 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);
- }
-}
-
-CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
- : TheDef(R), AsmString(AsmStr) {
- Name = R->getValueAsString("Name");
- Namespace = R->getValueAsString("Namespace");
-
- isReturn = R->getValueAsBit("isReturn");
- isBranch = R->getValueAsBit("isBranch");
- isBarrier = R->getValueAsBit("isBarrier");
- isCall = R->getValueAsBit("isCall");
- isLoad = R->getValueAsBit("isLoad");
- isStore = R->getValueAsBit("isStore");
- isTwoAddress = R->getValueAsBit("isTwoAddress");
- isPredicated = false; // set below.
- isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
- isCommutable = R->getValueAsBit("isCommutable");
- isTerminator = R->getValueAsBit("isTerminator");
- hasDelaySlot = R->getValueAsBit("hasDelaySlot");
- usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter");
- hasCtrlDep = R->getValueAsBit("hasCtrlDep");
- noResults = R->getValueAsBit("noResults");
- hasVariableNumberOfOperands = false;
-
- DagInit *DI;
- try {
- DI = R->getValueAsDag("OperandList");
- } catch (...) {
- // Error getting operand list, just ignore it (sparcv9).
- AsmString.clear();
- OperandList.clear();
- return;
- }
-
- unsigned MIOperandNo = 0;
- std::set<std::string> OperandNames;
- for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
- DefInit *Arg = dynamic_cast<DefInit*>(DI->getArg(i));
- if (!Arg)
- throw "Illegal operand for the '" + R->getName() + "' instruction!";
-
- Record *Rec = Arg->getDef();
- std::string PrintMethod = "printOperand";
- unsigned NumOps = 1;
- DagInit *MIOpInfo = 0;
- if (Rec->isSubClassOf("Operand")) {
- PrintMethod = Rec->getValueAsString("PrintMethod");
- MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
-
- // Verify that MIOpInfo has an 'ops' root value.
- if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) ||
- dynamic_cast<DefInit*>(MIOpInfo->getOperator())
- ->getDef()->getName() != "ops")
- throw "Bad value for MIOperandInfo in operand '" + Rec->getName() +
- "'\n";
-
- // If we have MIOpInfo, then we have #operands equal to number of entries
- // in MIOperandInfo.
- if (unsigned NumArgs = MIOpInfo->getNumArgs())
- NumOps = NumArgs;
-
- isPredicated |= Rec->isSubClassOf("PredicateOperand");
- } else if (Rec->getName() == "variable_ops") {
- hasVariableNumberOfOperands = true;
- continue;
- } else if (!Rec->isSubClassOf("RegisterClass") &&
- Rec->getName() != "ptr_rc")
- throw "Unknown operand class '" + Rec->getName() +
- "' in instruction '" + R->getName() + "' instruction!";
-
- // Check that the operand has a name and that it's unique.
- if (DI->getArgName(i).empty())
- throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
- " has no name!";
- if (!OperandNames.insert(DI->getArgName(i)).second)
- throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
- " has the same name as a previous operand!";
-
- OperandList.push_back(OperandInfo(Rec, DI->getArgName(i), PrintMethod,
- MIOperandNo, NumOps, MIOpInfo));
- MIOperandNo += NumOps;
- }
-
- 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) | (1 << 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";
-}
-
-
-
-/// getOperandNamed - Return the index of the operand with the specified
-/// non-empty name. If the instruction does not have an operand with the
-/// specified name, throw an exception.
-///
-unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
- assert(!Name.empty() && "Cannot search for operand with no name!");
- for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
- if (OperandList[i].Name == Name) return i;
- throw "Instruction '" + TheDef->getName() +
- "' does not have an operand named '$" + Name + "'!";
-}
-