summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp222
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp183
-rw-r--r--utils/TableGen/CodeGenInstruction.h14
3 files changed, 247 insertions, 172 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index a2c5de3e1e..aa8cc4e4c7 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -253,8 +253,11 @@ struct MatchableInfo {
/// The operand name this is, if anything.
StringRef SrcOpName;
+
+ /// The suboperand index within SrcOpName, or -1 for the entire operand.
+ int SubOpIdx;
- explicit AsmOperand(StringRef T) : Token(T), Class(0) {}
+ explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1) {}
};
/// ResOperand - This represents a single operand in the result instruction
@@ -296,46 +299,41 @@ struct MatchableInfo {
Record *Register;
};
- /// OpInfo - This is the information about the instruction operand that is
- /// being populated.
- const CGIOperandList::OperandInfo *OpInfo;
+ /// MINumOperands - The number of MCInst operands populated by this
+ /// operand.
+ unsigned MINumOperands;
- static ResOperand getRenderedOp(unsigned AsmOpNum,
- const CGIOperandList::OperandInfo *Op) {
+ static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) {
ResOperand X;
X.Kind = RenderAsmOperand;
X.AsmOperandNum = AsmOpNum;
- X.OpInfo = Op;
+ X.MINumOperands = NumOperands;
return X;
}
- static ResOperand getTiedOp(unsigned TiedOperandNum,
- const CGIOperandList::OperandInfo *Op) {
+ static ResOperand getTiedOp(unsigned TiedOperandNum) {
ResOperand X;
X.Kind = TiedOperand;
X.TiedOperandNum = TiedOperandNum;
- X.OpInfo = Op;
+ X.MINumOperands = 1;
return X;
}
- static ResOperand getImmOp(int64_t Val,
- const CGIOperandList::OperandInfo *Op) {
+ static ResOperand getImmOp(int64_t Val) {
ResOperand X;
X.Kind = ImmOperand;
X.ImmVal = Val;
- X.OpInfo = Op;
+ X.MINumOperands = 1;
return X;
}
- static ResOperand getRegOp(Record *Reg,
- const CGIOperandList::OperandInfo *Op) {
+ static ResOperand getRegOp(Record *Reg) {
ResOperand X;
X.Kind = RegOperand;
X.Register = Reg;
- X.OpInfo = Op;
+ X.MINumOperands = 1;
return X;
}
-
};
/// TheDef - This is the definition of the instruction or InstAlias that this
@@ -397,6 +395,18 @@ struct MatchableInfo {
Record *getSingletonRegisterForAsmOperand(unsigned i,
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 {
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
if (N == AsmOperands[i].SrcOpName)
@@ -531,7 +541,8 @@ private:
ClassInfo *getTokenClass(StringRef Token);
/// 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
/// classes.
@@ -541,11 +552,9 @@ private:
/// operand classes.
void BuildOperandClasses();
- void BuildInstructionOperandReference(MatchableInfo *II,
- StringRef OpName,
- MatchableInfo::AsmOperand &Op);
- void BuildAliasOperandReference(MatchableInfo *II,
- StringRef OpName,
+ void BuildInstructionOperandReference(MatchableInfo *II, StringRef OpName,
+ unsigned AsmOpIdx);
+ void BuildAliasOperandReference(MatchableInfo *II, StringRef OpName,
MatchableInfo::AsmOperand &Op);
public:
@@ -806,19 +815,24 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
}
ClassInfo *
-AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI) {
- if (OI.Rec->isSubClassOf("RegisterClass")) {
- if (ClassInfo *CI = RegisterClassClasses[OI.Rec])
+AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
+ int SubOpIdx) {
+ 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;
- 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!");
- Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
+ assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
if (ClassInfo *CI = AsmOperandClasses[MatchClass])
return CI;
- throw TGError(OI.Rec->getLoc(), "operand has no match class!");
+ throw TGError(Rec->getLoc(), "operand has no match class!");
}
void AsmMatcherInfo::
@@ -1120,7 +1134,9 @@ void AsmMatcherInfo::BuildInfo() {
MatchableInfo *II = *it;
// 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];
StringRef Token = Op.Token;
@@ -1151,7 +1167,7 @@ void AsmMatcherInfo::BuildInfo() {
OperandName = Token.substr(1);
if (II->DefRec.is<const CodeGenInstruction*>())
- BuildInstructionOperandReference(II, OperandName, Op);
+ BuildInstructionOperandReference(II, OperandName, i);
else
BuildAliasOperandReference(II, OperandName, Op);
}
@@ -1171,9 +1187,10 @@ void AsmMatcherInfo::BuildInfo() {
void AsmMatcherInfo::
BuildInstructionOperandReference(MatchableInfo *II,
StringRef OperandName,
- MatchableInfo::AsmOperand &Op) {
+ unsigned AsmOpIdx) {
const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>();
const CGIOperandList &Operands = CGI.Operands;
+ MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx];
// Map this token to an operand.
unsigned Idx;
@@ -1181,8 +1198,29 @@ BuildInstructionOperandReference(MatchableInfo *II,
throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
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.
- Op.Class = getOperandClass(Operands[Idx]);
+ Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx);
// If the named operand is tied, canonicalize it to the untied operand.
// For example, something like:
@@ -1196,15 +1234,12 @@ BuildInstructionOperandReference(MatchableInfo *II,
if (OITied != -1) {
// The tied operand index is an MIOperand index, find the operand that
// contains it.
- for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- if (Operands[i].MIOperandNo == unsigned(OITied)) {
- OperandName = Operands[i].Name;
- break;
- }
- }
+ std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied);
+ OperandName = Operands[Idx.first].Name;
+ Op->SubOpIdx = Idx.second;
}
- Op.SrcOpName = OperandName;
+ Op->SrcOpName = OperandName;
}
/// BuildAliasOperandReference - When parsing an operand reference out of the
@@ -1221,8 +1256,10 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
CGA.ResultOperands[i].getName() == OperandName) {
// 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.
- unsigned ResultIdx = CGA.ResultInstOperandIndex[i];
- Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx]);
+ unsigned ResultIdx = CGA.ResultInstOperandIndex[i].first;
+ Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
+ Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx],
+ Op.SubOpIdx);
Op.SrcOpName = OperandName;
return;
}
@@ -1242,22 +1279,31 @@ void MatchableInfo::BuildInstructionResultOperands() {
// If this is a tied operand, just copy from the previously handled operand.
int TiedOp = OpInfo.getTiedRegister();
if (TiedOp != -1) {
- ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo));
+ ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
continue;
}
- // Find out what operand from the asmparser that this MCInst operand comes
- // from.
+ // Find out what operand from the asmparser this MCInst operand comes from.
int SrcOperand = FindAsmOperandNamed(OpInfo.Name);
+ if (OpInfo.Name.empty() || SrcOperand == -1)
+ throw TGError(TheDef->getLoc(), "Instruction '" +
+ TheDef->getName() + "' has operand '" + OpInfo.Name +
+ "' that doesn't appear in asm string!");
- if (!OpInfo.Name.empty() && SrcOperand != -1) {
- ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
+ // 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;
}
-
- throw TGError(TheDef->getLoc(), "Instruction '" +
- TheDef->getName() + "' has operand '" + OpInfo.Name +
- "' that doesn't appear in asm string!");
+
+ // 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,42 +1314,50 @@ void MatchableInfo::BuildAliasResultOperands() {
// Loop over all operands of the result instruction, determining how to
// populate them.
unsigned AliasOpNo = 0;
+ unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
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.
- int TiedOp = OpInfo.getTiedRegister();
+ int TiedOp = OpInfo->getTiedRegister();
if (TiedOp != -1) {
- ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo));
- continue;
- }
-
- // Find out what operand from the asmparser that this MCInst operand comes
- // from.
- switch (CGA.ResultOperands[AliasOpNo].Kind) {
- case CodeGenInstAlias::ResultOperand::K_Record: {
- StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
- int SrcOperand = FindAsmOperandNamed(Name);
- if (SrcOperand != -1) {
- ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
- continue;
- }
-
- throw TGError(TheDef->getLoc(), "Instruction '" +
- TheDef->getName() + "' has operand '" + OpInfo.Name +
- "' that doesn't appear in asm string!");
- }
- case CodeGenInstAlias::ResultOperand::K_Imm: {
- int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
- ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
+ ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
continue;
}
- case CodeGenInstAlias::ResultOperand::K_Reg: {
- Record *Reg = CGA.ResultOperands[AliasOpNo++].getRegister();
- ResOperands.push_back(ResOperand::getRegOp(Reg, &OpInfo));
- continue;
- }
+ // Handle all the suboperands for this operand.
+ 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) {
+ default: assert(0 && "unexpected InstAlias operand kind");
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
+ int SrcOperand = FindAsmOperand(Name, SubIdx);
+ if (SrcOperand == -1)
+ throw TGError(TheDef->getLoc(), "Instruction '" +
+ TheDef->getName() + "' has operand '" + OpName +
+ "' 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: {
+ int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm();
+ ResOperands.push_back(ResOperand::getImmOp(ImmVal));
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Reg: {
+ Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister();
+ ResOperands.push_back(ResOperand::getRegOp(Reg));
+ break;
+ }
+ }
}
}
}
@@ -1362,19 +1416,19 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
Signature += "Reg";
else
Signature += Op.Class->ClassName;
- Signature += utostr(OpInfo.OpInfo->MINumOperands);
+ Signature += utostr(OpInfo.MINumOperands);
Signature += "_" + itostr(OpInfo.AsmOperandNum);
CaseOS << " ((" << TargetOperandClass << "*)Operands["
<< (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod
- << "(Inst, " << OpInfo.OpInfo->MINumOperands << ");\n";
+ << "(Inst, " << OpInfo.MINumOperands << ");\n";
break;
}
case MatchableInfo::ResOperand::TiedOperand: {
// 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.
- //assert(OpInfo.OpInfo->MINumOperands == 1 && "Not a singular MCOperand");
+ //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
unsigned TiedOp = OpInfo.TiedOperandNum;
assert(i > TiedOp && "Tied operand preceeds its target!");
CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n";
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index d69a44bc29..f37d3eabcd 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!");
}
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index fb0e50c08b..58913b9da2 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -16,6 +16,7 @@
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
#include <string>
#include <vector>
#include <utility>
@@ -297,11 +298,18 @@ namespace llvm {
/// ResultOperands - The decoded operands for the result instruction.
std::vector<ResultOperand> ResultOperands;
- /// ResultInstOperandIndex - For each operand, this vector holds the
- /// corresponding index of an operand in the result instruction.
- std::vector<unsigned> ResultInstOperandIndex;
+ /// ResultInstOperandIndex - For each operand, this vector holds a pair of
+ /// indices to identify the corresponding operand in the result
+ /// 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);
+
+ bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+ Record *InstOpRec, bool hasSubOps, SMLoc Loc,
+ CodeGenTarget &T, ResultOperand &ResOp);
};
}