rewrite EmitConvertToMCInst to iterate over the MCInst operands,

filling them in one at a time.  Previously this iterated over the
asmoperands, which left the problem of "holes".  The new approach
simplifies things.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118104 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner
2010-11-02 22:55:03 +00:00
parent 0800ce7189
commit 9b0d4bfca0
2 changed files with 76 additions and 99 deletions

View File

@@ -1040,13 +1040,12 @@ void AsmMatcherInfo::BuildInfo() {
// grovel for. Only worry about this for single entry operands, we have to // grovel for. Only worry about this for single entry operands, we have to
// clean this up anyway. // clean this up anyway.
const CGIOperandList::OperandInfo *OI = &II->OperandList[Idx]; const CGIOperandList::OperandInfo *OI = &II->OperandList[Idx];
if (OI->Constraints[0].isTied()) { int OITied = OI->getTiedRegister();
unsigned TiedOp = OI->Constraints[0].getTiedOperand(); 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 = II->OperandList.size(); i != e; ++i) { for (unsigned i = 0, e = II->OperandList.size(); i != e; ++i) {
if (II->OperandList[i].MIOperandNo == TiedOp) { if (II->OperandList[i].MIOperandNo == unsigned(OITied)) {
OI = &II->OperandList[i]; OI = &II->OperandList[i];
break; break;
} }
@@ -1064,16 +1063,6 @@ void AsmMatcherInfo::BuildInfo() {
std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
} }
static std::pair<unsigned, unsigned> *
GetTiedOperandAtIndex(SmallVectorImpl<std::pair<unsigned, unsigned> > &List,
unsigned Index) {
for (unsigned i = 0, e = List.size(); i != e; ++i)
if (Index == List[i].first)
return &List[i];
return 0;
}
static void EmitConvertToMCInst(CodeGenTarget &Target, static void EmitConvertToMCInst(CodeGenTarget &Target,
std::vector<MatchableInfo*> &Infos, std::vector<MatchableInfo*> &Infos,
raw_ostream &OS) { raw_ostream &OS) {
@@ -1103,74 +1092,45 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
// TargetOperandClass - This is the target's operand class, like X86Operand. // TargetOperandClass - This is the target's operand class, like X86Operand.
std::string TargetOperandClass = Target.getName() + "Operand"; std::string TargetOperandClass = Target.getName() + "Operand";
/// OperandMap - This is a mapping from the MCInst operands (specified by the
/// II.OperandList operands) to the AsmOperands that they filled in from.
SmallVector<int, 16> OperandMap;
for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(), for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) { ie = Infos.end(); it != ie; ++it) {
MatchableInfo &II = **it; MatchableInfo &II = **it;
OperandMap.clear();
OperandMap.resize(II.OperandList.size(), -1);
// Order the (class) operands by the order to convert them into an MCInst. // Order the (class) operands by the order to convert them into an MCInst.
SmallVector<std::pair<unsigned, unsigned>, 4> MIOperandList;
for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
MatchableInfo::Operand &Op = II.AsmOperands[i]; MatchableInfo::Operand &Op = II.AsmOperands[i];
if (Op.OperandInfo) if (!Op.OperandInfo) continue;
MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i));
}
// Find any tied operands. unsigned LogicalOpNum = Op.OperandInfo - &II.OperandList[0];
SmallVector<std::pair<unsigned, unsigned>, 4> TiedOperands; assert(LogicalOpNum < OperandMap.size() && "Invalid operand number");
for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) { OperandMap[LogicalOpNum] = i;
const CGIOperandList::OperandInfo &OpInfo = II.OperandList[i];
for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) {
const CGIOperandList::ConstraintInfo &CI = OpInfo.Constraints[j];
if (!CI.isTied()) continue;
TiedOperands.push_back(std::make_pair(OpInfo.MIOperandNo,
CI.getTiedOperand()));
}
}
array_pod_sort(MIOperandList.begin(), MIOperandList.end());
// Compute the total number of operands.
unsigned NumMIOperands = 0;
for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
const CGIOperandList::OperandInfo &OI = II.OperandList[i];
NumMIOperands = std::max(NumMIOperands, OI.MIOperandNo+OI.MINumOperands);
} }
// Build the conversion function signature. // Build the conversion function signature.
std::string Signature = "Convert"; std::string Signature = "Convert";
unsigned CurIndex = 0;
std::string CaseBody; std::string CaseBody;
raw_string_ostream CaseOS(CaseBody); raw_string_ostream CaseOS(CaseBody);
// Compute the convert enum and the case body. // Compute the convert enum and the case body.
for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) { for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
MatchableInfo::Operand &Op = II.AsmOperands[MIOperandList[i].second]; const CGIOperandList::OperandInfo &OpInfo = II.OperandList[i];
assert(CurIndex <= Op.OperandInfo->MIOperandNo &&
"Duplicate match for instruction operand!");
// Add the implicit operands. // Find out what operand from the asmparser that this MCInst operand comes
for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) { // from.
// See if this is a tied operand. int SrcOperand = OperandMap[i];
std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands, if (SrcOperand != -1) {
CurIndex); // Otherwise, this comes from something we parsed.
MatchableInfo::Operand &Op = II.AsmOperands[SrcOperand];
if (!Tie) { // Registers are always converted the same, don't duplicate the
// If not, this is some implicit operand. Just assume it is a register // conversion function based on them.
// for now.
CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
Signature += "__Imp";
} else {
// Copy the tied operand.
assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
CaseOS << " Inst.addOperand(Inst.getOperand("
<< Tie->second << "));\n";
Signature += "__Tie" + utostr(Tie->second);
}
}
// Registers are always converted the same, don't duplicate the conversion
// function based on them.
// //
// FIXME: We could generalize this based on the render method, if it // FIXME: We could generalize this based on the render method, if it
// mattered. // mattered.
@@ -1180,32 +1140,38 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
else else
Signature += Op.Class->ClassName; Signature += Op.Class->ClassName;
Signature += utostr(Op.OperandInfo->MINumOperands); Signature += utostr(Op.OperandInfo->MINumOperands);
Signature += "_" + utostr(MIOperandList[i].second); Signature += "_" + itostr(SrcOperand);
CaseOS << " ((" << TargetOperandClass << "*)Operands[" CaseOS << " ((" << TargetOperandClass << "*)Operands["
<< MIOperandList[i].second << "+1])->" << Op.Class->RenderMethod << SrcOperand << "+1])->" << Op.Class->RenderMethod
<< "(Inst, " << Op.OperandInfo->MINumOperands << ");\n"; << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n";
CurIndex += Op.OperandInfo->MINumOperands; continue;
} }
// And add trailing implicit operands.
for (; CurIndex != NumMIOperands; ++CurIndex) {
std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
CurIndex);
if (!Tie) { // If this operand is tied to a previous one, just copy the MCInst operand
// If not, this is some implicit operand. Just assume it is a register // from the earlier one.
// for now. int TiedOp = OpInfo.getTiedRegister();
if (TiedOp != -1) {
// Copy the tied operand.
// FIXME: What if the operand has multiple MINumOperands? This happens
// in ARM.
//assert(OpInfo.MINumOperands == 1);
assert(i > unsigned(TiedOp) && "Tied operand preceeds its target!");
CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n";
Signature += "__Tie" + itostr(TiedOp);
continue;
}
// Otherwise this is some sort of dummy operand that is mentioned in the
// ins/outs list but not mentioned in the asmstring, brutalize a dummy
// value into the operand.
// FIXME: This is a terrible hack: If an MCInst operand doesn't occur in
// the asmstring, there is no way to parse something meaningful.
// Just assume it is a zero register for now.
CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
Signature += "__Imp"; Signature += "__Imp";
} else {
// Copy the tied operand.
assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
CaseOS << " Inst.addOperand(Inst.getOperand("
<< Tie->second << "));\n";
Signature += "__Tie" + utostr(Tie->second);
}
} }
II.ConversionFnKind = Signature; II.ConversionFnKind = Signature;

View File

@@ -103,6 +103,17 @@ namespace llvm {
DagInit *MIOI) DagInit *MIOI)
: Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN),
MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {}
/// getTiedOperand - If this operand is tied to another one, return the
/// other operand number. Otherwise, return -1.
int getTiedRegister() const {
for (unsigned j = 0, e = Constraints.size(); j != e; ++j) {
const CGIOperandList::ConstraintInfo &CI = Constraints[j];
if (CI.isTied()) return CI.getTiedOperand();
}
return -1;
}
}; };
CGIOperandList(Record *D); CGIOperandList(Record *D);