mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-26 20:26:07 +00:00
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:
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user