mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 13:10:34 +00:00
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:
parent
eabde0cf07
commit
a49c7dfb36
@ -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";
|
||||
|
@ -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!");
|
||||
throw TGError(R->getLoc(), "not enough arguments for instruction!");
|
||||
|
||||
|
||||
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);
|
||||
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!");
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user