summaryrefslogtreecommitdiffstats
path: root/utils/TableGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-09-14 20:53:42 +0000
committerChris Lattner <sabre@nondot.org>2005-09-14 20:53:42 +0000
commitd8a3bde6fdae7b98a2ad3d92e094238d72b5c284 (patch)
treeea41b236ea70f553886b9fb4392040460a12d591 /utils/TableGen
parent4345a4a452c3ba3d99d374026e77b21382df44fe (diff)
downloadexternal_llvm-d8a3bde6fdae7b98a2ad3d92e094238d72b5c284.zip
external_llvm-d8a3bde6fdae7b98a2ad3d92e094238d72b5c284.tar.gz
external_llvm-d8a3bde6fdae7b98a2ad3d92e094238d72b5c284.tar.bz2
Parse significantly more of the instruction pattern, now collecting and
verifying information about the operands. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23353 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp183
-rw-r--r--utils/TableGen/DAGISelEmitter.h4
2 files changed, 141 insertions, 46 deletions
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 2de78a7..0687598 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -340,6 +340,7 @@ TreePattern::TreePattern(Record *TheRec, const std::vector<DagInit *> &RawPat,
}
void TreePattern::error(const std::string &Msg) const {
+ dump();
throw "In " + TheRecord->getName() + ": " + Msg;
}
@@ -625,6 +626,102 @@ void DAGISelEmitter::ParseAndResolvePatternFragments(std::ostream &OS) {
}
}
+/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
+/// instruction input.
+static void HandleUse(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string, TreePatternNode*> &InstInputs) {
+ // No name -> not interesting.
+ if (Pat->getName().empty()) return;
+
+ Record *Rec;
+ if (Pat->isLeaf()) {
+ DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
+ if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!");
+ Rec = DI->getDef();
+ } else {
+ assert(Pat->getNumChildren() == 0 && "can't be a use with children!");
+ Rec = Pat->getOperator();
+ }
+
+ TreePatternNode *&Slot = InstInputs[Pat->getName()];
+ if (!Slot) {
+ Slot = Pat;
+ } else {
+ Record *SlotRec;
+ if (Slot->isLeaf()) {
+ Rec = dynamic_cast<DefInit*>(Slot->getLeafValue())->getDef();
+ } else {
+ assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
+ SlotRec = Slot->getOperator();
+ }
+
+ // Ensure that the inputs agree if we've already seen this input.
+ if (Rec != SlotRec)
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ if (Slot->getType() != Pat->getType())
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ }
+}
+
+/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is
+/// part of "I", the instruction), computing the set of inputs and outputs of
+/// the pattern. Report errors if we see anything naughty.
+void DAGISelEmitter::
+FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string, TreePatternNode*> &InstInputs,
+ std::map<std::string, Record*> &InstResults) {
+ if (Pat->isLeaf()) {
+ HandleUse(I, Pat, InstInputs);
+ return;
+ } else if (Pat->getOperator()->getName() != "set") {
+ // If this is not a set, verify that the children nodes are not void typed,
+ // and recurse.
+ for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
+ if (Pat->getChild(i)->getType() == MVT::isVoid)
+ I->error("Cannot have void nodes inside of patterns!");
+ FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults);
+ }
+
+ // If this is a non-leaf node with no children, treat it basically as if
+ // it were a leaf. This handles nodes like (imm).
+ if (Pat->getNumChildren() == 0)
+ HandleUse(I, Pat, InstInputs);
+
+ return;
+ }
+
+ // Otherwise, this is a set, validate and collect instruction results.
+ if (Pat->getNumChildren() == 0)
+ I->error("set requires operands!");
+ else if (Pat->getNumChildren() & 1)
+ I->error("set requires an even number of operands");
+
+ // Check the set destinations.
+ unsigned NumValues = Pat->getNumChildren()/2;
+ for (unsigned i = 0; i != NumValues; ++i) {
+ TreePatternNode *Dest = Pat->getChild(i);
+ if (!Dest->isLeaf())
+ I->error("set destination should be a virtual register!");
+
+ DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
+ if (!Val)
+ I->error("set destination should be a virtual register!");
+
+ if (!Val->getDef()->isSubClassOf("RegisterClass"))
+ I->error("set destination should be a virtual register!");
+ if (Dest->getName().empty())
+ I->error("set destination must have a name!");
+ if (InstResults.count(Dest->getName()))
+ I->error("cannot set '" + Dest->getName() +"' multiple times");
+ InstResults[Dest->getName()] = Val->getDef();
+
+ // Verify and collect info from the computation.
+ FindPatternInputsAndOutputs(I, Pat->getChild(i+NumValues),
+ InstInputs, InstResults);
+ }
+}
+
+
/// ParseAndResolveInstructions - Parse all of the instructions, inlining and
/// resolving any fragments involved. This populates the Instructions list with
/// fully resolved instructions.
@@ -654,12 +751,16 @@ void DAGISelEmitter::ParseAndResolveInstructions() {
I->error("Could not infer all types in pattern!");
}
- // SetDestinations - Keep track of all the virtual registers that are 'set'
+ // InstInputs - Keep track of all of the inputs of the instruction, along
+ // with the record they are declared as.
+ std::map<std::string, TreePatternNode*> InstInputs;
+
+ // InstResults - Keep track of all the virtual registers that are 'set'
// in the instruction, including what reg class they are.
- std::map<std::string, Record*> SetDestinations;
-
+ std::map<std::string, Record*> InstResults;
+
// Verify that the top-level forms in the instruction are of void type, and
- // fill in the SetDestinations map.
+ // fill in the InstResults map.
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
TreePatternNode *Pat = I->getTree(j);
if (Pat->getType() != MVT::isVoid) {
@@ -667,40 +768,15 @@ void DAGISelEmitter::ParseAndResolveInstructions() {
I->error("Top-level forms in instruction pattern should have"
" void types");
}
-
- // Investigate sets.
- if (Pat->getOperator()->getName() == "set") {
- if (Pat->getNumChildren() == 0)
- I->error("set requires operands!");
- else if (Pat->getNumChildren() & 1)
- I->error("set requires an even number of operands");
-
- // Check the set destinations.
- unsigned NumValues = Pat->getNumChildren()/2;
- for (unsigned i = 0; i != NumValues; ++i) {
- TreePatternNode *Dest = Pat->getChild(i);
- if (!Dest->isLeaf())
- I->error("set destination should be a virtual register!");
-
- DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
- if (!Val)
- I->error("set destination should be a virtual register!");
-
- if (!Val->getDef()->isSubClassOf("RegisterClass"))
- I->error("set destination should be a virtual register!");
- if (Dest->getName().empty())
- I->error("set destination must have a name!");
- if (SetDestinations.count(Dest->getName()))
- I->error("cannot set '" + Dest->getName() +"' multiple times");
- SetDestinations[Dest->getName()] = Val->getDef();
- }
- }
+
+ // Find inputs and outputs, and verify the structure of the uses/defs.
+ FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults);
}
- // Now that we have operands that are sets, inspect the operands list for
- // the instruction. This determines the order that operands are added to
- // the machine instruction the node corresponds to.
- unsigned NumResults = SetDestinations.size();
+ // Now that we have inputs and outputs of the pattern, inspect the operands
+ // list for the instruction. This determines the order that operands are
+ // added to the machine instruction the node corresponds to.
+ unsigned NumResults = InstResults.size();
// Parse the operands list from the (ops) list, validating it.
std::vector<std::string> &Args = I->getArgList();
@@ -709,12 +785,16 @@ void DAGISelEmitter::ParseAndResolveInstructions() {
// Check that all of the results occur first in the list.
for (unsigned i = 0; i != NumResults; ++i) {
+ if (NumResults == CGI.OperandList.size())
+ I->error("'" + InstResults.begin()->first +
+ "' set but does not appear in operand list!");
+
const std::string &OpName = CGI.OperandList[i].Name;
if (OpName.empty())
I->error("Operand #" + utostr(i) + " in operands list has no name!");
- // Check that it exists in SetDestinations.
- Record *R = SetDestinations[OpName];
+ // Check that it exists in InstResults.
+ Record *R = InstResults[OpName];
if (R == 0)
I->error("Operand $" + OpName + " should be a set destination: all "
"outputs must occur before inputs in operand list!");
@@ -723,20 +803,31 @@ void DAGISelEmitter::ParseAndResolveInstructions() {
I->error("Operand $" + OpName + " class mismatch!");
// Okay, this one checks out.
- SetDestinations.erase(OpName);
+ InstResults.erase(OpName);
}
-
- if (!SetDestinations.empty())
- I->error("'" + SetDestinations.begin()->first +
- "' set but does not appear in operand list!");
- unsigned NumOperands = 0;
-
+ // Loop over the inputs next.
+ for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) {
+ const std::string &OpName = CGI.OperandList[i].Name;
+ if (OpName.empty())
+ I->error("Operand #" + utostr(i) + " in operands list has no name!");
+
+ if (!InstInputs.count(OpName))
+ I->error("Operand $" + OpName +
+ " does not appear in the instruction pattern");
+ TreePatternNode *InVal = InstInputs[OpName];
+ if (CGI.OperandList[i].Ty != InVal->getType())
+ I->error("Operand $" + OpName +
+ "'s type disagrees between the operand and pattern");
+ }
+
+ unsigned NumOperands = CGI.OperandList.size()-NumResults;
+
DEBUG(I->dump());
Instructions.push_back(DAGInstruction(I, NumResults, NumOperands));
}
- // If we can, convert the instructions to be a patterns that are matched!
+ // If we can, convert the instructions to be patterns that are matched!
for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
TreePattern *I = Instructions[i].getPattern();
diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h
index d475e8e..e948ce0 100644
--- a/utils/TableGen/DAGISelEmitter.h
+++ b/utils/TableGen/DAGISelEmitter.h
@@ -330,6 +330,10 @@ private:
void ParseNodeTransforms(std::ostream &OS);
void ParseAndResolvePatternFragments(std::ostream &OS);
void ParseAndResolveInstructions();
+ void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string,
+ TreePatternNode*> &InstInputs,
+ std::map<std::string, Record*> &InstResults);
void EmitInstructionSelector(std::ostream &OS);
};