mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-05 13:26:55 +00:00
Fix a tblgen problem handling variable_ops in tblgen instruction
definitions. This adds a new construct, "discard", for indicating that a named node in the input matching pattern is to be discarded, instead of corresponding to a node in the output pattern. This allows tblgen to know where the arguments for the varaible_ops are supposed to begin. This fixes "rdar://5791600", whatever that is ;-). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51699 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -916,6 +916,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
||||
MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP);
|
||||
} else if (OperandNode->getName() == "unknown") {
|
||||
MadeChange |= Child->UpdateNodeType(MVT::isUnknown, TP);
|
||||
} else if (OperandNode->getName() == "discard") {
|
||||
MadeChange |= Child->UpdateNodeType(MVT::isUnknown, TP);
|
||||
} else {
|
||||
assert(0 && "Unknown operand type!");
|
||||
abort();
|
||||
|
@@ -163,7 +163,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
|
||||
isVariadic = true;
|
||||
continue;
|
||||
} else if (!Rec->isSubClassOf("RegisterClass") &&
|
||||
Rec->getName() != "ptr_rc" && Rec->getName() != "unknown")
|
||||
Rec->getName() != "ptr_rc" && Rec->getName() != "unknown" &&
|
||||
Rec->getName() != "discard")
|
||||
throw "Unknown operand class '" + Rec->getName() +
|
||||
"' in instruction '" + R->getName() + "' instruction!";
|
||||
|
||||
|
@@ -947,22 +947,20 @@ public:
|
||||
// instruction operands to do this.
|
||||
std::vector<std::string> AllOps;
|
||||
unsigned NumEAInputs = 0; // # of synthesized 'execute always' inputs.
|
||||
unsigned NumDiscardedInputs = 0; // # of 'discard' inputs to skip.
|
||||
for (unsigned ChildNo = 0, InstOpNo = NumResults;
|
||||
InstOpNo != II.OperandList.size(); ++InstOpNo) {
|
||||
std::vector<std::string> Ops;
|
||||
|
||||
// If this is a normal operand or a predicate operand without
|
||||
// 'execute always', emit it.
|
||||
// Determine what to emit for this operand.
|
||||
Record *OperandNode = II.OperandList[InstOpNo].Rec;
|
||||
if ((!OperandNode->isSubClassOf("PredicateOperand") &&
|
||||
!OperandNode->isSubClassOf("OptionalDefOperand")) ||
|
||||
CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
|
||||
Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
|
||||
InFlagDecled, ResNodeDecled);
|
||||
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
||||
++ChildNo;
|
||||
} else {
|
||||
// Otherwise, this is a predicate or optional def operand, emit the
|
||||
if (OperandNode->getName() == "discard") {
|
||||
// This is a "discard" operand; emit nothing. Just note it.
|
||||
++NumDiscardedInputs;
|
||||
} else if ((OperandNode->isSubClassOf("PredicateOperand") ||
|
||||
OperandNode->isSubClassOf("OptionalDefOperand")) &&
|
||||
!CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
|
||||
// This is a predicate or optional def operand; emit the
|
||||
// 'default ops' operands.
|
||||
const DAGDefaultOperand &DefaultOp =
|
||||
CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec);
|
||||
@@ -972,6 +970,13 @@ public:
|
||||
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
||||
NumEAInputs += Ops.size();
|
||||
}
|
||||
} else {
|
||||
// Otherwise this is a normal operand or a predicate operand without
|
||||
// 'execute always'; emit it.
|
||||
Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
|
||||
InFlagDecled, ResNodeDecled);
|
||||
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
||||
++ChildNo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1049,19 +1054,23 @@ public:
|
||||
if (NodeHasOutFlag)
|
||||
Code += ", MVT::Flag";
|
||||
|
||||
// Figure out how many fixed inputs the node has. This is important to
|
||||
// know which inputs are the variable ones if present.
|
||||
unsigned NumInputs = AllOps.size();
|
||||
NumInputs += NodeHasChain;
|
||||
|
||||
// Inputs.
|
||||
if (HasVarOps) {
|
||||
// Figure out how many fixed inputs the node has. This is important
|
||||
// to know which inputs are the variable ones if present. Include
|
||||
// the 'discard' and chain inputs in the count, and adjust for the
|
||||
// number of operands that are 'execute always'. This is the index
|
||||
// where we should start copying operands into the 'variable_ops'
|
||||
// portion of the output.
|
||||
unsigned InputIndex = AllOps.size() +
|
||||
NumDiscardedInputs +
|
||||
NodeHasChain -
|
||||
NumEAInputs;
|
||||
|
||||
for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
|
||||
emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
|
||||
AllOps.clear();
|
||||
}
|
||||
|
||||
if (HasVarOps) {
|
||||
// Figure out whether any operands at the end of the op list are not
|
||||
// part of the variable section.
|
||||
std::string EndAdjust;
|
||||
@@ -1070,7 +1079,7 @@ public:
|
||||
else if (NodeHasOptInFlag)
|
||||
EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
|
||||
|
||||
emitCode("for (unsigned i = " + utostr(NumInputs - NumEAInputs) +
|
||||
emitCode("for (unsigned i = " + utostr(InputIndex) +
|
||||
", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
|
||||
|
||||
emitCode(" AddToISelQueue(N.getOperand(i));");
|
||||
|
@@ -85,6 +85,10 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
||||
Record *OpR = OperandList[j].Rec;
|
||||
std::string Res;
|
||||
|
||||
// Discard "discard" operands.
|
||||
if (OpR->getName() == "discard")
|
||||
continue;
|
||||
|
||||
if (OpR->isSubClassOf("RegisterClass"))
|
||||
Res += getQualifiedName(OpR) + "RegClassID, ";
|
||||
else
|
||||
@@ -201,6 +205,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
|
||||
// Each logical operand can be multiple MI operands.
|
||||
MinOperands = Inst.OperandList.back().MIOperandNo +
|
||||
Inst.OperandList.back().MINumOperands;
|
||||
|
||||
// Subtract the number of "discard" operands, which we'll be skipping
|
||||
// when emitting OperandInfo records.
|
||||
for (unsigned j = 0, e = Inst.OperandList.size(); j != e; ++j) {
|
||||
Record *OpR = Inst.OperandList[j].Rec;
|
||||
if (OpR->getName() == "discard")
|
||||
--MinOperands;
|
||||
}
|
||||
|
||||
OS << " { ";
|
||||
OS << Num << ",\t" << MinOperands << ",\t"
|
||||
|
Reference in New Issue
Block a user