llvm.org GIT mirror llvm / 0bb7500
ADd support for adding constraints to suboperands git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31748 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 14 years ago
3 changed file(s) with 111 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
6060 /// up of multiple MI operands.
6161 DagInit *MIOperandInfo;
6262
63 /// Constraint info for this operand.
64 std::string Constraint;
63 /// Constraint info for this operand. This operand can have pieces, so we
64 /// track constraint info for each.
65 std::vector Constraints;
6566
6667 OperandInfo(Record *R, const std::string &N, const std::string &PMN,
6768 unsigned MION, unsigned MINO, DagInit *MIOI)
9091 bool hasVariableNumberOfOperands;
9192 bool hasCtrlDep;
9293 bool noResults;
94
95 /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
96 /// where $foo is a whole operand and $foo.bar refers to a suboperand.
97 /// This throws an exception if the name is invalid. If AllowWholeOp is
98 /// true, references to operands with suboperands are allowed, otherwise
99 /// not.
100 std::pair ParseOperandName(const std::string &Op,
101 bool AllowWholeOp = true);
102
103 /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
104 /// flat machineinstr operand #.
105 unsigned getFlattenedOperandNumber(std::pair Op) const {
106 return OperandList[Op.first].MIOperandNo + Op.second;
107 }
108
93109
94110 CodeGenInstruction(Record *R, const std::string &AsmStr);
95111
272272 return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
273273 }
274274
275 static std::string ParseConstraint(const std::string &CStr,
276 CodeGenInstruction *I, unsigned &DestOp) {
277 const std::string ops("="); // FIXME: Only supports TIED_TO for now.
278 std::string::size_type pos = CStr.find_first_of(ops);
275
276
277 static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
278 // FIXME: Only supports TIED_TO for now.
279 std::string::size_type pos = CStr.find_first_of('=');
279280 assert(pos != std::string::npos && "Unrecognized constraint");
280 std::string Name = CStr.substr(1, pos); // Skip '$'
281 std::string Name = CStr.substr(0, pos);
281282
282283 // TIED_TO: $src1 = $dst
283 const std::string delims(" \t");
284 std::string::size_type wpos = Name.find_first_of(delims);
285 if (wpos != std::string::npos)
286 Name = Name.substr(0, wpos);
287 DestOp = I->getOperandNamed(Name);
284 std::string::size_type wpos = Name.find_first_of(" \t");
285 if (wpos == std::string::npos)
286 throw "Illegal format for tied-to constraint: '" + CStr + "'";
287 std::string DestOpName = Name.substr(0, wpos);
288 std::pair DestOp = I->ParseOperandName(DestOpName, false);
288289
289290 Name = CStr.substr(pos+1);
290 wpos = Name.find_first_not_of(delims);
291 if (wpos != std::string::npos)
292 Name = Name.substr(wpos+1);
293
294 unsigned TIdx = I->getOperandNamed(Name);
295 if (TIdx >= DestOp)
291 wpos = Name.find_first_not_of(" \t");
292 if (wpos == std::string::npos)
293 throw "Illegal format for tied-to constraint: '" + CStr + "'";
294
295 std::pair SrcOp =
296 I->ParseOperandName(Name.substr(wpos), false);
297 if (SrcOp > DestOp)
296298 throw "Illegal tied-to operand constraint '" + CStr + "'";
297299
298 // Build the string.
299 return "((" + utostr(TIdx) + " << 16) | (1 << TargetInstrInfo::TIED_TO))";
300
301 unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
302 // Build the string for the operand.
303 std::string OpConstraint =
304 "((" + utostr(FlatOpNo) + " << 16) | (1 << TargetInstrInfo::TIED_TO))";
305
306
307 if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
308 throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
309 I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint;
300310 }
301311
302312 static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
313 // Make sure the constraints list for each operand is large enough to hold
314 // constraint info, even if none is present.
315 for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i)
316 I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands);
317
303318 if (CStr.empty()) return;
304319
305320 const std::string delims(",");
311326 if (eidx == std::string::npos)
312327 eidx = CStr.length();
313328
314 unsigned OpNo;
315 std::string Constr = ParseConstraint(CStr.substr(bidx, eidx), I, OpNo);
316 assert(OpNo < I->OperandList.size() && "Invalid operand no?");
317
318 if (!I->OperandList[OpNo].Constraint.empty())
319 throw "Operand #" + utostr(OpNo) + " cannot have multiple constraints!";
320 I->OperandList[OpNo].Constraint = Constr;
329 ParseConstraint(CStr.substr(bidx, eidx), I);
321330 bidx = CStr.find_first_not_of(delims, eidx);
322331 }
323332 }
407416
408417 // For backward compatibility: isTwoAddress means operand 1 is tied to
409418 // operand 0.
410 if (isTwoAddress && OperandList[1].Constraint.empty())
411 OperandList[1].Constraint = "((0 << 16) | (1 << TargetInstrInfo::TIED_TO))";
419 if (isTwoAddress) {
420 if (!OperandList[1].Constraints[0].empty())
421 throw R->getName() + ": cannot use isTwoAddress property: instruction "
422 "already has constraint set!";
423 OperandList[1].Constraints[0] =
424 "((0 << 16) | (1 << TargetInstrInfo::TIED_TO))";
425 }
412426
413427 // Any operands with unset constraints get 0 as their constraint.
414428 for (unsigned op = 0, e = OperandList.size(); op != e; ++op)
415 if (OperandList[op].Constraint.empty())
416 OperandList[op].Constraint = "0";
429 for (unsigned j = 0, e = OperandList[op].MINumOperands; j != e; ++j)
430 if (OperandList[op].Constraints[j].empty())
431 OperandList[op].Constraints[j] = "0";
417432 }
418433
419434
429444 throw "Instruction '" + TheDef->getName() +
430445 "' does not have an operand named '$" + Name + "'!";
431446 }
447
448 std::pair
449 CodeGenInstruction::ParseOperandName(const std::string &Op,
450 bool AllowWholeOp) {
451 if (Op.empty() || Op[0] != '$')
452 throw TheDef->getName() + ": Illegal operand name: '" + Op + "'";
453
454 std::string OpName = Op.substr(1);
455 std::string SubOpName;
456
457 // Check to see if this is $foo.bar.
458 std::string::size_type DotIdx = OpName.find_first_of(".");
459 if (DotIdx != std::string::npos) {
460 SubOpName = OpName.substr(DotIdx+1);
461 if (SubOpName.empty())
462 throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'";
463 OpName = OpName.substr(0, DotIdx);
464 }
465
466 unsigned OpIdx = getOperandNamed(OpName);
467
468 if (SubOpName.empty()) { // If no suboperand name was specified:
469 // If one was needed, throw.
470 if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
471 SubOpName.empty())
472 throw TheDef->getName() + ": Illegal to refer to"
473 " whole operand part of complex operand '" + Op + "'";
474
475 // Otherwise, return the operand.
476 return std::make_pair(OpIdx, 0U);
477 }
478
479 // Find the suboperand number involved.
480 DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
481 if (MIOpInfo == 0)
482 throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
483
484 // Find the operand with the right name.
485 for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
486 if (MIOpInfo->getArgName(i) == SubOpName)
487 return std::make_pair(OpIdx, i);
488
489 // Otherwise, didn't find it!
490 throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
491 }
492
493
494
432495
433496 //===----------------------------------------------------------------------===//
434497 // ComplexPattern implementation
110110 Res += "|M_PREDICATE_OPERAND";
111111
112112 // Fill in constraint info.
113 Res += ", " + Inst.OperandList[i].Constraint;
113 Res += ", " + Inst.OperandList[i].Constraints[j];
114114 Result.push_back(Res);
115115 }
116116 }