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
This commit is contained in:
Bob Wilson 2011-01-26 19:44:55 +00:00
parent eabde0cf07
commit a49c7dfb36
3 changed files with 246 additions and 171 deletions

View File

@ -254,7 +254,10 @@ struct MatchableInfo {
/// The operand name this is, if anything. /// The operand name this is, if anything.
StringRef SrcOpName; StringRef SrcOpName;
explicit AsmOperand(StringRef T) : Token(T), Class(0) {} /// The suboperand index within SrcOpName, or -1 for the entire operand.
int SubOpIdx;
explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1) {}
}; };
/// ResOperand - This represents a single operand in the result instruction /// ResOperand - This represents a single operand in the result instruction
@ -296,46 +299,41 @@ struct MatchableInfo {
Record *Register; Record *Register;
}; };
/// OpInfo - This is the information about the instruction operand that is /// MINumOperands - The number of MCInst operands populated by this
/// being populated. /// operand.
const CGIOperandList::OperandInfo *OpInfo; unsigned MINumOperands;
static ResOperand getRenderedOp(unsigned AsmOpNum, static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) {
const CGIOperandList::OperandInfo *Op) {
ResOperand X; ResOperand X;
X.Kind = RenderAsmOperand; X.Kind = RenderAsmOperand;
X.AsmOperandNum = AsmOpNum; X.AsmOperandNum = AsmOpNum;
X.OpInfo = Op; X.MINumOperands = NumOperands;
return X; return X;
} }
static ResOperand getTiedOp(unsigned TiedOperandNum, static ResOperand getTiedOp(unsigned TiedOperandNum) {
const CGIOperandList::OperandInfo *Op) {
ResOperand X; ResOperand X;
X.Kind = TiedOperand; X.Kind = TiedOperand;
X.TiedOperandNum = TiedOperandNum; X.TiedOperandNum = TiedOperandNum;
X.OpInfo = Op; X.MINumOperands = 1;
return X; return X;
} }
static ResOperand getImmOp(int64_t Val, static ResOperand getImmOp(int64_t Val) {
const CGIOperandList::OperandInfo *Op) {
ResOperand X; ResOperand X;
X.Kind = ImmOperand; X.Kind = ImmOperand;
X.ImmVal = Val; X.ImmVal = Val;
X.OpInfo = Op; X.MINumOperands = 1;
return X; return X;
} }
static ResOperand getRegOp(Record *Reg, static ResOperand getRegOp(Record *Reg) {
const CGIOperandList::OperandInfo *Op) {
ResOperand X; ResOperand X;
X.Kind = RegOperand; X.Kind = RegOperand;
X.Register = Reg; X.Register = Reg;
X.OpInfo = Op; X.MINumOperands = 1;
return X; return X;
} }
}; };
/// TheDef - This is the definition of the instruction or InstAlias that this /// TheDef - This is the definition of the instruction or InstAlias that this
@ -397,6 +395,18 @@ struct MatchableInfo {
Record *getSingletonRegisterForAsmOperand(unsigned i, Record *getSingletonRegisterForAsmOperand(unsigned i,
const AsmMatcherInfo &Info) const; const AsmMatcherInfo &Info) const;
/// FindAsmOperand - Find the AsmOperand with the specified name and
/// suboperand index.
int FindAsmOperand(StringRef N, int SubOpIdx) const {
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
if (N == AsmOperands[i].SrcOpName &&
SubOpIdx == AsmOperands[i].SubOpIdx)
return i;
return -1;
}
/// FindAsmOperandNamed - Find the first AsmOperand with the specified name.
/// This does not check the suboperand index.
int FindAsmOperandNamed(StringRef N) const { int FindAsmOperandNamed(StringRef N) const {
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
if (N == AsmOperands[i].SrcOpName) if (N == AsmOperands[i].SrcOpName)
@ -531,7 +541,8 @@ private:
ClassInfo *getTokenClass(StringRef Token); ClassInfo *getTokenClass(StringRef Token);
/// getOperandClass - Lookup or create the class for the given operand. /// getOperandClass - Lookup or create the class for the given operand.
ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI); ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI,
int SubOpIdx = -1);
/// BuildRegisterClasses - Build the ClassInfo* instances for register /// BuildRegisterClasses - Build the ClassInfo* instances for register
/// classes. /// classes.
@ -541,11 +552,9 @@ private:
/// operand classes. /// operand classes.
void BuildOperandClasses(); void BuildOperandClasses();
void BuildInstructionOperandReference(MatchableInfo *II, void BuildInstructionOperandReference(MatchableInfo *II, StringRef OpName,
StringRef OpName, unsigned AsmOpIdx);
MatchableInfo::AsmOperand &Op); void BuildAliasOperandReference(MatchableInfo *II, StringRef OpName,
void BuildAliasOperandReference(MatchableInfo *II,
StringRef OpName,
MatchableInfo::AsmOperand &Op); MatchableInfo::AsmOperand &Op);
public: public:
@ -806,19 +815,24 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
} }
ClassInfo * ClassInfo *
AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI) { AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
if (OI.Rec->isSubClassOf("RegisterClass")) { int SubOpIdx) {
if (ClassInfo *CI = RegisterClassClasses[OI.Rec]) Record *Rec = OI.Rec;
if (SubOpIdx != -1)
Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
if (Rec->isSubClassOf("RegisterClass")) {
if (ClassInfo *CI = RegisterClassClasses[Rec])
return CI; return CI;
throw TGError(OI.Rec->getLoc(), "register class has no class info!"); throw TGError(Rec->getLoc(), "register class has no class info!");
} }
assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!"); assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass"); Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
if (ClassInfo *CI = AsmOperandClasses[MatchClass]) if (ClassInfo *CI = AsmOperandClasses[MatchClass])
return CI; return CI;
throw TGError(OI.Rec->getLoc(), "operand has no match class!"); throw TGError(Rec->getLoc(), "operand has no match class!");
} }
void AsmMatcherInfo:: void AsmMatcherInfo::
@ -1120,7 +1134,9 @@ void AsmMatcherInfo::BuildInfo() {
MatchableInfo *II = *it; MatchableInfo *II = *it;
// Parse the tokens after the mnemonic. // Parse the tokens after the mnemonic.
for (unsigned i = 0, e = II->AsmOperands.size(); i != e; ++i) { // Note: BuildInstructionOperandReference may insert new AsmOperands, so
// don't precompute the loop bound.
for (unsigned i = 0; i != II->AsmOperands.size(); ++i) {
MatchableInfo::AsmOperand &Op = II->AsmOperands[i]; MatchableInfo::AsmOperand &Op = II->AsmOperands[i];
StringRef Token = Op.Token; StringRef Token = Op.Token;
@ -1151,7 +1167,7 @@ void AsmMatcherInfo::BuildInfo() {
OperandName = Token.substr(1); OperandName = Token.substr(1);
if (II->DefRec.is<const CodeGenInstruction*>()) if (II->DefRec.is<const CodeGenInstruction*>())
BuildInstructionOperandReference(II, OperandName, Op); BuildInstructionOperandReference(II, OperandName, i);
else else
BuildAliasOperandReference(II, OperandName, Op); BuildAliasOperandReference(II, OperandName, Op);
} }
@ -1171,9 +1187,10 @@ void AsmMatcherInfo::BuildInfo() {
void AsmMatcherInfo:: void AsmMatcherInfo::
BuildInstructionOperandReference(MatchableInfo *II, BuildInstructionOperandReference(MatchableInfo *II,
StringRef OperandName, StringRef OperandName,
MatchableInfo::AsmOperand &Op) { unsigned AsmOpIdx) {
const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>(); const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>();
const CGIOperandList &Operands = CGI.Operands; const CGIOperandList &Operands = CGI.Operands;
MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx];
// Map this token to an operand. // Map this token to an operand.
unsigned Idx; unsigned Idx;
@ -1181,8 +1198,29 @@ BuildInstructionOperandReference(MatchableInfo *II,
throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
OperandName.str() + "'"); OperandName.str() + "'");
// If the instruction operand has multiple suboperands, but the parser
// match class for the asm operand is still the default "ImmAsmOperand",
// then handle each suboperand separately.
if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) {
Record *Rec = Operands[Idx].Rec;
assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") {
// Insert remaining suboperands after AsmOpIdx in II->AsmOperands.
StringRef Token = Op->Token; // save this in case Op gets moved
for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) {
MatchableInfo::AsmOperand NewAsmOp(Token);
NewAsmOp.SubOpIdx = SI;
II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp);
}
// Replace Op with first suboperand.
Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved
Op->SubOpIdx = 0;
}
}
// Set up the operand class. // Set up the operand class.
Op.Class = getOperandClass(Operands[Idx]); Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx);
// If the named operand is tied, canonicalize it to the untied operand. // If the named operand is tied, canonicalize it to the untied operand.
// For example, something like: // For example, something like:
@ -1196,15 +1234,12 @@ BuildInstructionOperandReference(MatchableInfo *II,
if (OITied != -1) { if (OITied != -1) {
// The tied operand index is an MIOperand index, find the operand that // The tied operand index is an MIOperand index, find the operand that
// contains it. // contains it.
for (unsigned i = 0, e = Operands.size(); i != e; ++i) { std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied);
if (Operands[i].MIOperandNo == unsigned(OITied)) { OperandName = Operands[Idx.first].Name;
OperandName = Operands[i].Name; Op->SubOpIdx = Idx.second;
break;
}
}
} }
Op.SrcOpName = OperandName; Op->SrcOpName = OperandName;
} }
/// BuildAliasOperandReference - When parsing an operand reference out of the /// BuildAliasOperandReference - When parsing an operand reference out of the
@ -1221,8 +1256,10 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
CGA.ResultOperands[i].getName() == OperandName) { CGA.ResultOperands[i].getName() == OperandName) {
// It's safe to go with the first one we find, because CodeGenInstAlias // It's safe to go with the first one we find, because CodeGenInstAlias
// validates that all operands with the same name have the same record. // validates that all operands with the same name have the same record.
unsigned ResultIdx = CGA.ResultInstOperandIndex[i]; unsigned ResultIdx = CGA.ResultInstOperandIndex[i].first;
Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx]); Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx],
Op.SubOpIdx);
Op.SrcOpName = OperandName; Op.SrcOpName = OperandName;
return; return;
} }
@ -1242,22 +1279,31 @@ void MatchableInfo::BuildInstructionResultOperands() {
// If this is a tied operand, just copy from the previously handled operand. // If this is a tied operand, just copy from the previously handled operand.
int TiedOp = OpInfo.getTiedRegister(); int TiedOp = OpInfo.getTiedRegister();
if (TiedOp != -1) { if (TiedOp != -1) {
ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo)); ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
continue; continue;
} }
// Find out what operand from the asmparser that this MCInst operand comes // Find out what operand from the asmparser this MCInst operand comes from.
// from.
int SrcOperand = FindAsmOperandNamed(OpInfo.Name); int SrcOperand = FindAsmOperandNamed(OpInfo.Name);
if (OpInfo.Name.empty() || SrcOperand == -1)
if (!OpInfo.Name.empty() && SrcOperand != -1) {
ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
continue;
}
throw TGError(TheDef->getLoc(), "Instruction '" + throw TGError(TheDef->getLoc(), "Instruction '" +
TheDef->getName() + "' has operand '" + OpInfo.Name + TheDef->getName() + "' has operand '" + OpInfo.Name +
"' that doesn't appear in asm string!"); "' that doesn't appear in asm string!");
// Check if the one AsmOperand populates the entire operand.
unsigned NumOperands = OpInfo.MINumOperands;
if (AsmOperands[SrcOperand].SubOpIdx == -1) {
ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands));
continue;
}
// Add a separate ResOperand for each suboperand.
for (unsigned AI = 0; AI < NumOperands; ++AI) {
assert(AsmOperands[SrcOperand+AI].SubOpIdx == (int)AI &&
AsmOperands[SrcOperand+AI].SrcOpName == OpInfo.Name &&
"unexpected AsmOperands for suboperands");
ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1));
}
} }
} }
@ -1268,41 +1314,49 @@ void MatchableInfo::BuildAliasResultOperands() {
// Loop over all operands of the result instruction, determining how to // Loop over all operands of the result instruction, determining how to
// populate them. // populate them.
unsigned AliasOpNo = 0; unsigned AliasOpNo = 0;
unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i]; const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];
// If this is a tied operand, just copy from the previously handled operand. // If this is a tied operand, just copy from the previously handled operand.
int TiedOp = OpInfo.getTiedRegister(); int TiedOp = OpInfo->getTiedRegister();
if (TiedOp != -1) { if (TiedOp != -1) {
ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo)); ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
continue; continue;
} }
// Find out what operand from the asmparser that this MCInst operand comes // Handle all the suboperands for this operand.
// from. const std::string &OpName = OpInfo->Name;
for ( ; AliasOpNo < LastOpNo &&
CGA.ResultInstOperandIndex[AliasOpNo].first == i; ++AliasOpNo) {
int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
// Find out what operand from the asmparser that this MCInst operand
// comes from.
switch (CGA.ResultOperands[AliasOpNo].Kind) { switch (CGA.ResultOperands[AliasOpNo].Kind) {
default: assert(0 && "unexpected InstAlias operand kind");
case CodeGenInstAlias::ResultOperand::K_Record: { case CodeGenInstAlias::ResultOperand::K_Record: {
StringRef Name = CGA.ResultOperands[AliasOpNo++].getName(); StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
int SrcOperand = FindAsmOperandNamed(Name); int SrcOperand = FindAsmOperand(Name, SubIdx);
if (SrcOperand != -1) { if (SrcOperand == -1)
ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
continue;
}
throw TGError(TheDef->getLoc(), "Instruction '" + throw TGError(TheDef->getLoc(), "Instruction '" +
TheDef->getName() + "' has operand '" + OpInfo.Name + TheDef->getName() + "' has operand '" + OpName +
"' that doesn't appear in asm string!"); "' that doesn't appear in asm string!");
unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);
ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand,
NumOperands));
break;
} }
case CodeGenInstAlias::ResultOperand::K_Imm: { case CodeGenInstAlias::ResultOperand::K_Imm: {
int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm(); int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm();
ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo)); ResOperands.push_back(ResOperand::getImmOp(ImmVal));
continue; break;
} }
case CodeGenInstAlias::ResultOperand::K_Reg: { case CodeGenInstAlias::ResultOperand::K_Reg: {
Record *Reg = CGA.ResultOperands[AliasOpNo++].getRegister(); Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister();
ResOperands.push_back(ResOperand::getRegOp(Reg, &OpInfo)); ResOperands.push_back(ResOperand::getRegOp(Reg));
continue; break;
}
} }
} }
} }
@ -1362,19 +1416,19 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
Signature += "Reg"; Signature += "Reg";
else else
Signature += Op.Class->ClassName; Signature += Op.Class->ClassName;
Signature += utostr(OpInfo.OpInfo->MINumOperands); Signature += utostr(OpInfo.MINumOperands);
Signature += "_" + itostr(OpInfo.AsmOperandNum); Signature += "_" + itostr(OpInfo.AsmOperandNum);
CaseOS << " ((" << TargetOperandClass << "*)Operands[" CaseOS << " ((" << TargetOperandClass << "*)Operands["
<< (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod
<< "(Inst, " << OpInfo.OpInfo->MINumOperands << ");\n"; << "(Inst, " << OpInfo.MINumOperands << ");\n";
break; break;
} }
case MatchableInfo::ResOperand::TiedOperand: { case MatchableInfo::ResOperand::TiedOperand: {
// If this operand is tied to a previous one, just copy the MCInst // If this operand is tied to a previous one, just copy the MCInst
// operand from the earlier one.We can only tie single MCOperand values. // operand from the earlier one.We can only tie single MCOperand values.
//assert(OpInfo.OpInfo->MINumOperands == 1 && "Not a singular MCOperand"); //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
unsigned TiedOp = OpInfo.TiedOperandNum; unsigned TiedOp = OpInfo.TiedOperandNum;
assert(i > TiedOp && "Tied operand preceeds its target!"); assert(i > TiedOp && "Tied operand preceeds its target!");
CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n"; CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n";

View File

@ -390,6 +390,71 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
/// CodeGenInstAlias Implementation /// 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) { CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
AsmString = R->getValueAsString("AsmString"); AsmString = R->getValueAsString("AsmString");
Result = R->getValueAsDag("ResultInst"); Result = R->getValueAsDag("ResultInst");
@ -422,103 +487,51 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
// Decode and validate the arguments of the result. // Decode and validate the arguments of the result.
unsigned AliasOpNo = 0; unsigned AliasOpNo = 0;
for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
// Tied registers don't have an entry in the result dag. // Tied registers don't have an entry in the result dag.
if (ResultInst->Operands[i].getTiedRegister() != -1) if (ResultInst->Operands[i].getTiedRegister() != -1)
continue; continue;
if (AliasOpNo >= Result->getNumArgs()) if (AliasOpNo >= Result->getNumArgs())
throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) + throw TGError(R->getLoc(), "not enough arguments for instruction!");
" arguments, but " + ResultInst->TheDef->getName() +
" instruction expects " +
utostr(ResultInst->Operands.size()) + " operands!");
Record *InstOpRec = ResultInst->Operands[i].Rec;
Init *Arg = Result->getArg(AliasOpNo); unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
Record *ResultOpRec = ResultInst->Operands[i].Rec; ResultOperand ResOp(static_cast<int64_t>(0));
if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
// Handle explicit registers. R->getLoc(), T, ResOp)) {
if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) { ResultOperands.push_back(ResOp);
if (ADI->getDef()->isSubClassOf("Register")) { ResultInstOperandIndex.push_back(std::make_pair(i, -1));
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; ++AliasOpNo;
continue; 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 the argument did not match the instruction operand, and the operand
if (!ResultOpRec->isSubClassOf("OptionalDefOperand")) // is composed of multiple suboperands, try matching the suboperands.
throw TGError(R->getLoc(), "reg0 used for result that is not an " if (NumSubOps > 1) {
"OptionalDefOperand!"); DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
// Now that it is validated, add it. if (AliasOpNo >= Result->getNumArgs())
ResultOperands.push_back(ResultOperand(static_cast<Record*>(0))); throw TGError(R->getLoc(), "not enough arguments for instruction!");
ResultInstOperandIndex.push_back(i); 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; ++AliasOpNo;
continue; } else {
}
}
// 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) + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" must have a name!"); " does not match instruction operand class " +
(SubOp == 0 ? InstOpRec->getName() :SubRec->getName()));
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);
++AliasOpNo;
continue; 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) + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" must not have a name!"); " does not match instruction operand class " +
if (ResultInst->Operands[i].MINumOperands != 1 || InstOpRec->getName());
!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;
continue;
}
throw TGError(R->getLoc(), "result of inst alias has unknown operand type");
} }
if (AliasOpNo != Result->getNumArgs()) if (AliasOpNo != Result->getNumArgs())
throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) + throw TGError(R->getLoc(), "too many operands for instruction!");
" arguments, but " + ResultInst->TheDef->getName() +
" instruction expects " + utostr(ResultInst->Operands.size())+
" operands!");
} }

View File

@ -16,6 +16,7 @@
#include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/ValueTypes.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/SourceMgr.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <utility> #include <utility>
@ -297,11 +298,18 @@ namespace llvm {
/// ResultOperands - The decoded operands for the result instruction. /// ResultOperands - The decoded operands for the result instruction.
std::vector<ResultOperand> ResultOperands; std::vector<ResultOperand> ResultOperands;
/// ResultInstOperandIndex - For each operand, this vector holds the /// ResultInstOperandIndex - For each operand, this vector holds a pair of
/// corresponding index of an operand in the result instruction. /// indices to identify the corresponding operand in the result
std::vector<unsigned> ResultInstOperandIndex; /// instruction. The first index specifies the operand and the second
/// index specifies the suboperand. If there are no suboperands or if all
/// of them are matched by the operand, the second value should be -1.
std::vector<std::pair<unsigned, int> > ResultInstOperandIndex;
CodeGenInstAlias(Record *R, CodeGenTarget &T); CodeGenInstAlias(Record *R, CodeGenTarget &T);
bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
Record *InstOpRec, bool hasSubOps, SMLoc Loc,
CodeGenTarget &T, ResultOperand &ResOp);
}; };
} }