diff options
author | Bob Wilson <bob.wilson@apple.com> | 2011-01-26 19:44:55 +0000 |
---|---|---|
committer | Bob Wilson <bob.wilson@apple.com> | 2011-01-26 19:44:55 +0000 |
commit | a49c7dfb360154070c08b8eb94ad31711d1babae (patch) | |
tree | a6d5a0f9b3ed95e98b7a809d93f766116e3aa51f /utils/TableGen/CodeGenInstruction.cpp | |
parent | eabde0cf0798e36934ffd03b071f2bd490ac1f11 (diff) | |
download | external_llvm-a49c7dfb360154070c08b8eb94ad31711d1babae.zip external_llvm-a49c7dfb360154070c08b8eb94ad31711d1babae.tar.gz external_llvm-a49c7dfb360154070c08b8eb94ad31711d1babae.tar.bz2 |
Improve the AsmMatcher's ability to handle suboperands.
When an operand class is defined with MIOperandInfo set to a list of
suboperands, the AsmMatcher has so far required that operand to also define
a custom ParserMatchClass, and InstAlias patterns have not been able to
set the individual suboperands separately. This patch removes both of those
restrictions. If a "compound" operand does not override the default
ParserMatchClass, then the AsmMatcher will now parse its suboperands
separately. If an InstAlias operand has the same class as the corresponding
compound operand, then it will be handled as before; but if that check fails,
TableGen will now try to match up a sequence of InstAlias operands with the
corresponding suboperands.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124314 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen/CodeGenInstruction.cpp')
-rw-r--r-- | utils/TableGen/CodeGenInstruction.cpp | 183 |
1 files changed, 98 insertions, 85 deletions
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index d69a44b..f37d3ea 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -390,6 +390,71 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) { /// CodeGenInstAlias Implementation //===----------------------------------------------------------------------===// +/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias +/// constructor. It checks if an argument in an InstAlias pattern matches +/// the corresponding operand of the instruction. It returns true on a +/// successful match, with ResOp set to the result operand to be used. +bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, + Record *InstOpRec, bool hasSubOps, + SMLoc Loc, CodeGenTarget &T, + ResultOperand &ResOp) { + Init *Arg = Result->getArg(AliasOpNo); + DefInit *ADI = dynamic_cast<DefInit*>(Arg); + + if (ADI && ADI->getDef() == InstOpRec) { + // If the operand is a record, it must have a name, and the record type + // must match up with the instruction's argument type. + if (Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + + " must have a name!"); + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + return true; + } + + // Handle explicit registers. + if (ADI && ADI->getDef()->isSubClassOf("Register")) { + if (!InstOpRec->isSubClassOf("RegisterClass")) + return false; + + if (!T.getRegisterClass(InstOpRec).containsRegister(ADI->getDef())) + throw TGError(Loc, "fixed register " +ADI->getDef()->getName() + + " is not a member of the " + InstOpRec->getName() + + " register class!"); + + if (!Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result fixed register argument must " + "not have a name!"); + + ResOp = ResultOperand(ADI->getDef()); + return true; + } + + // Handle "zero_reg" for optional def operands. + if (ADI && ADI->getDef()->getName() == "zero_reg") { + + // Check if this is an optional def. + if (!InstOpRec->isSubClassOf("OptionalDefOperand")) + throw TGError(Loc, "reg0 used for result that is not an " + "OptionalDefOperand!"); + + ResOp = ResultOperand(static_cast<Record*>(0)); + return true; + } + + if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + // Integer arguments can't have names. + if (!Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + + " must not have a name!"); + ResOp = ResultOperand(II->getValue()); + return true; + } + + return false; +} + CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { AsmString = R->getValueAsString("AsmString"); Result = R->getValueAsDag("ResultInst"); @@ -422,103 +487,51 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { // Decode and validate the arguments of the result. unsigned AliasOpNo = 0; for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + // Tied registers don't have an entry in the result dag. if (ResultInst->Operands[i].getTiedRegister() != -1) continue; if (AliasOpNo >= Result->getNumArgs()) - throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) + - " arguments, but " + ResultInst->TheDef->getName() + - " instruction expects " + - utostr(ResultInst->Operands.size()) + " operands!"); - - - Init *Arg = Result->getArg(AliasOpNo); - Record *ResultOpRec = ResultInst->Operands[i].Rec; - - // Handle explicit registers. - if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) { - if (ADI->getDef()->isSubClassOf("Register")) { - if (!Result->getArgName(AliasOpNo).empty()) - throw TGError(R->getLoc(), "result fixed register argument must " - "not have a name!"); - - if (!ResultOpRec->isSubClassOf("RegisterClass")) - throw TGError(R->getLoc(), "result fixed register argument is not " - "passed to a RegisterClass operand!"); - - if (!T.getRegisterClass(ResultOpRec).containsRegister(ADI->getDef())) - throw TGError(R->getLoc(), "fixed register " +ADI->getDef()->getName() - + " is not a member of the " + ResultOpRec->getName() + - " register class!"); - - // Now that it is validated, add it. - ResultOperands.push_back(ResultOperand(ADI->getDef())); - ResultInstOperandIndex.push_back(i); - ++AliasOpNo; - continue; - } - if (ADI->getDef()->getName() == "zero_reg") { - if (!Result->getArgName(AliasOpNo).empty()) - throw TGError(R->getLoc(), "result fixed register argument must " - "not have a name!"); - - // Check if this is an optional def. - if (!ResultOpRec->isSubClassOf("OptionalDefOperand")) - throw TGError(R->getLoc(), "reg0 used for result that is not an " - "OptionalDefOperand!"); - - // Now that it is validated, add it. - ResultOperands.push_back(ResultOperand(static_cast<Record*>(0))); - ResultInstOperandIndex.push_back(i); - ++AliasOpNo; - continue; - } - } - - // If the operand is a record, it must have a name, and the record type must - // match up with the instruction's argument type. - if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) { - if (Result->getArgName(AliasOpNo).empty()) - throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + - " must have a name!"); - - if (ADI->getDef() != ResultOpRec) - throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + - " declared with class " + ADI->getDef()->getName() + - ", instruction operand is class " + - ResultOpRec->getName()); - - // Now that it is validated, add it. - ResultOperands.push_back(ResultOperand(Result->getArgName(AliasOpNo), - ADI->getDef())); - ResultInstOperandIndex.push_back(i); + throw TGError(R->getLoc(), "not enough arguments for instruction!"); + + Record *InstOpRec = ResultInst->Operands[i].Rec; + unsigned NumSubOps = ResultInst->Operands[i].MINumOperands; + ResultOperand ResOp(static_cast<int64_t>(0)); + if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1), + R->getLoc(), T, ResOp)) { + ResultOperands.push_back(ResOp); + ResultInstOperandIndex.push_back(std::make_pair(i, -1)); ++AliasOpNo; continue; } - if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { - // Integer arguments can't have names. - if (!Result->getArgName(AliasOpNo).empty()) - throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + - " must not have a name!"); - if (ResultInst->Operands[i].MINumOperands != 1 || - !ResultOpRec->isSubClassOf("Operand")) - throw TGError(R->getLoc(), "invalid argument class " + - ResultOpRec->getName() + - " for integer result operand!"); - ResultOperands.push_back(ResultOperand(II->getValue())); - ResultInstOperandIndex.push_back(i); - ++AliasOpNo; + // If the argument did not match the instruction operand, and the operand + // is composed of multiple suboperands, try matching the suboperands. + if (NumSubOps > 1) { + DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; + for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { + if (AliasOpNo >= Result->getNumArgs()) + throw TGError(R->getLoc(), "not enough arguments for instruction!"); + Record *SubRec = dynamic_cast<DefInit*>(MIOI->getArg(SubOp))->getDef(); + if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, + R->getLoc(), T, ResOp)) { + ResultOperands.push_back(ResOp); + ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); + ++AliasOpNo; + } else { + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + " does not match instruction operand class " + + (SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); + } + } continue; } - - throw TGError(R->getLoc(), "result of inst alias has unknown operand type"); + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + " does not match instruction operand class " + + InstOpRec->getName()); } if (AliasOpNo != Result->getNumArgs()) - throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) + - " arguments, but " + ResultInst->TheDef->getName() + - " instruction expects " + utostr(ResultInst->Operands.size())+ - " operands!"); + throw TGError(R->getLoc(), "too many operands for instruction!"); } |