aboutsummaryrefslogtreecommitdiffstats
path: root/support/tools/TableGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-08-07 23:16:20 +0000
committerChris Lattner <sabre@nondot.org>2003-08-07 23:16:20 +0000
commitef0ce6a4948f4494d2115b7d3593ad0f30037e6b (patch)
tree0aed25a6e2910aa7e553dded57d2df1230f8509e /support/tools/TableGen
parentd3464c19a8b6acecd8a9618489ec7612505fd4bd (diff)
downloadexternal_llvm-ef0ce6a4948f4494d2115b7d3593ad0f30037e6b.zip
external_llvm-ef0ce6a4948f4494d2115b7d3593ad0f30037e6b.tar.gz
external_llvm-ef0ce6a4948f4494d2115b7d3593ad0f30037e6b.tar.bz2
Finish implementation of nonterminal instantiation.
Tree patterns are now, finally, ready to use! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7699 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'support/tools/TableGen')
-rw-r--r--support/tools/TableGen/InstrSelectorEmitter.cpp128
-rw-r--r--support/tools/TableGen/InstrSelectorEmitter.h51
2 files changed, 158 insertions, 21 deletions
diff --git a/support/tools/TableGen/InstrSelectorEmitter.cpp b/support/tools/TableGen/InstrSelectorEmitter.cpp
index 250c897..3e30a52 100644
--- a/support/tools/TableGen/InstrSelectorEmitter.cpp
+++ b/support/tools/TableGen/InstrSelectorEmitter.cpp
@@ -38,6 +38,49 @@ bool TreePatternNode::updateNodeType(MVT::ValueType VT,
throw "Type inferfence contradiction found for pattern " + RecName;
}
+/// InstantiateNonterminals - If this pattern refers to any nonterminals which
+/// are not themselves completely resolved, clone the nonterminal and resolve it
+/// with the using context we provide.
+///
+void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
+ if (!isLeaf()) {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ Children[i]->InstantiateNonterminals(ISE);
+ return;
+ }
+
+ // If this is a leaf, it might be a reference to a nonterminal! Check now.
+ if (DefInit *DI = dynamic_cast<DefInit*>(getValue()))
+ if (DI->getDef()->isSubClassOf("Nonterminal")) {
+ Pattern *NT = ISE.getPattern(DI->getDef());
+ if (!NT->isResolved()) {
+ // We found an unresolved nonterminal reference. Ask the ISE to clone
+ // it for us, then update our reference to the fresh, new, resolved,
+ // nonterminal.
+
+ Value = new DefInit(ISE.InstantiateNonterminal(NT, getType()));
+ }
+ }
+}
+
+
+/// clone - Make a copy of this tree and all of its children.
+///
+TreePatternNode *TreePatternNode::clone() const {
+ TreePatternNode *New;
+ if (isLeaf()) {
+ New = new TreePatternNode(Value);
+ } else {
+ std::vector<TreePatternNode*> CChildren(Children.size());
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ CChildren[i] = Children[i]->clone();
+ New = new TreePatternNode(Operator, CChildren);
+ }
+ New->setType(Type);
+ return New;
+}
+
+
std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
if (N.isLeaf())
return OS << N.getType() << ":" << *N.getValue();
@@ -67,16 +110,13 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
// First, parse the pattern...
Tree = ParseTreePattern(RawPat);
-
- bool MadeChange, AnyUnset;
- do {
- MadeChange = false;
- AnyUnset = InferTypes(Tree, MadeChange);
- } while ((AnyUnset || MadeChange) && !(AnyUnset && !MadeChange));
+
+ // Run the type-inference engine...
+ InferAllTypes();
if (PTy == Instruction || PTy == Expander) {
// Check to make sure there is not any unset types in the tree pattern...
- if (AnyUnset) {
+ if (!isResolved()) {
std::cerr << "In pattern: " << *Tree << "\n";
error("Could not infer all types!");
}
@@ -92,13 +132,12 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
Result = RegInit->getDef();
Tree = Tree->getChild(1);
-
}
}
-
- Resolved = !AnyUnset;
}
+
+
void Pattern::error(const std::string &Msg) const {
std::string M = "In ";
switch (PTy) {
@@ -175,6 +214,15 @@ TreePatternNode *Pattern::ParseTreePattern(DagInit *DI) {
return new TreePatternNode(Operator, Children);
}
+void Pattern::InferAllTypes() {
+ bool MadeChange, AnyUnset;
+ do {
+ MadeChange = false;
+ AnyUnset = InferTypes(Tree, MadeChange);
+ } while ((AnyUnset || MadeChange) && !(AnyUnset && !MadeChange));
+ Resolved = !AnyUnset;
+}
+
// InferTypes - Perform type inference on the tree, returning true if there
// are any remaining untyped nodes and setting MadeChange if any changes were
@@ -240,15 +288,16 @@ bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
return AnyUnset | N->getType() == MVT::Other;
}
-/// InstantiateNonterminalsReferenced - If this pattern refers to any
-/// nonterminals which are not themselves completely resolved, clone the
-/// nonterminal and resolve it with the using context we provide.
+/// clone - This method is used to make an exact copy of the current pattern,
+/// then change the "TheRecord" instance variable to the specified record.
///
-void Pattern::InstantiateNonterminalsReferenced() {
-
+Pattern *Pattern::clone(Record *R) const {
+ assert(PTy == Nonterminal && "Can only clone nonterminals");
+ return new Pattern(Tree->clone(), R, Resolved, ISE);
}
+
std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
switch (P.getPatternType()) {
case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
@@ -362,10 +411,50 @@ void InstrSelectorEmitter::ReadExpanderPatterns() {
// information from the context that they are used in.
//
void InstrSelectorEmitter::InstantiateNonterminals() {
+ DEBUG(std::cerr << "Instantiating nonterminals:\n");
for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
E = Patterns.end(); I != E; ++I)
if (I->second->isResolved())
- I->second->InstantiateNonterminalsReferenced();
+ I->second->InstantiateNonterminals();
+}
+
+/// InstantiateNonterminal - This method takes the nonterminal specified by
+/// NT, which should not be completely resolved, clones it, applies ResultTy
+/// to its root, then runs the type inference stuff on it. This should
+/// produce a newly resolved nonterminal, which we make a record for and
+/// return. To be extra fancy and efficient, this only makes one clone for
+/// each type it is instantiated with.
+Record *InstrSelectorEmitter::InstantiateNonterminal(Pattern *NT,
+ MVT::ValueType ResultTy) {
+ assert(!NT->isResolved() && "Nonterminal is already resolved!");
+
+ // Check to see if we have already instantiated this pair...
+ Record* &Slot = InstantiatedNTs[std::make_pair(NT, ResultTy)];
+ if (Slot) return Slot;
+
+ DEBUG(std::cerr << " Nonterminal '" << NT->getRecord()->getName()
+ << "' for type '" << getName(ResultTy) << "'\n");
+
+ Record *New = new Record(NT->getRecord()->getName()+"_"+getName(ResultTy));
+
+ // Copy the pattern...
+ Pattern *NewPat = NT->clone(New);
+
+ // Apply the type to the root...
+ NewPat->getTree()->updateNodeType(ResultTy, New->getName());
+
+ // Infer types...
+ NewPat->InferAllTypes();
+
+ // Make sure everything is good to go now...
+ if (!NewPat->isResolved())
+ NewPat->error("Instantiating nonterminal did not resolve all types!");
+
+ // Add the pattern to the patterns map, add the record to the RecordKeeper,
+ // return the new record.
+ Patterns[New] = NewPat;
+ Records.addDef(New);
+ return Slot = New;
}
@@ -381,4 +470,11 @@ void InstrSelectorEmitter::run(std::ostream &OS) {
// Instantiate any unresolved nonterminals with information from the context
// that they are used in.
InstantiateNonterminals();
+
+
+ std::cerr << "Patterns aquired:\n";
+ for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
+ E = Patterns.end(); I != E; ++I)
+ if (I->second->isResolved())
+ std::cerr << " " << *I->second << "\n";
}
diff --git a/support/tools/TableGen/InstrSelectorEmitter.h b/support/tools/TableGen/InstrSelectorEmitter.h
index e8c8fad..0a8ca98 100644
--- a/support/tools/TableGen/InstrSelectorEmitter.h
+++ b/support/tools/TableGen/InstrSelectorEmitter.h
@@ -87,8 +87,16 @@ public:
return Value;
}
+ /// clone - Make a copy of this tree and all of its children.
+ ///
+ TreePatternNode *clone() const;
+
void dump() const;
+ /// InstantiateNonterminals - If this pattern refers to any nonterminals which
+ /// are not themselves completely resolved, clone the nonterminal and resolve
+ /// it with the using context we provide.
+ void InstantiateNonterminals(InstrSelectorEmitter &ISE);
// UpdateNodeType - Set the node type of N to VT if VT contains information.
// If N already contains a conflicting type, then throw an exception. This
@@ -145,6 +153,11 @@ public:
Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
InstrSelectorEmitter &ise);
+ /// Pattern - Constructor used for cloning nonterminal patterns
+ Pattern(TreePatternNode *tree, Record *rec, bool res,
+ InstrSelectorEmitter &ise) : PTy(Nonterminal), Tree(tree), Result(0),
+ TheRecord(rec), Resolved(res), ISE(ise){}
+
/// getPatternType - Return what flavor of Record this pattern originated from
///
PatternType getPatternType() const { return PTy; }
@@ -162,15 +175,30 @@ public:
bool isResolved() const { return Resolved; }
- /// InstantiateNonterminalsReferenced - If this pattern refers to any
- /// nonterminals which are not themselves completely resolved, clone the
- /// nonterminal and resolve it with the using context we provide.
- void InstantiateNonterminalsReferenced();
+ /// InferAllTypes - Runs the type inference engine on the current pattern,
+ /// stopping when nothing can be inferred, then updating the Resolved field.
+ void InferAllTypes();
+
+ /// InstantiateNonterminals - If this pattern refers to any nonterminals which
+ /// are not themselves completely resolved, clone the nonterminal and resolve
+ /// it with the using context we provide.
+ void InstantiateNonterminals() {
+ Tree->InstantiateNonterminals(ISE);
+ }
+
+ /// clone - This method is used to make an exact copy of the current pattern,
+ /// then change the "TheRecord" instance variable to the specified record.
+ ///
+ Pattern *clone(Record *R) const;
+
+ /// error - Throw an exception, prefixing it with information about this
+ /// pattern.
+ void error(const std::string &Msg) const;
+
private:
MVT::ValueType getIntrinsicType(Record *R) const;
TreePatternNode *ParseTreePattern(DagInit *DI);
bool InferTypes(TreePatternNode *N, bool &MadeChange);
- void error(const std::string &Msg) const;
};
std::ostream &operator<<(std::ostream &OS, const Pattern &P);
@@ -189,6 +217,11 @@ class InstrSelectorEmitter : public TableGenBackend {
/// Patterns - a list of all of the patterns defined by the target description
///
std::map<Record*, Pattern*> Patterns;
+
+ /// InstantiatedNTs - A data structure to keep track of which nonterminals
+ /// have been instantiated already...
+ ///
+ std::map<std::pair<Pattern*,MVT::ValueType>, Record*> InstantiatedNTs;
public:
InstrSelectorEmitter(RecordKeeper &R) : Records(R) {}
@@ -209,6 +242,14 @@ public:
/// nonterminal, but only if it hasn't been read in already.
Pattern *ReadNonterminal(Record *R);
+ /// InstantiateNonterminal - This method takes the nonterminal specified by
+ /// NT, which should not be completely resolved, clones it, applies ResultTy
+ /// to its root, then runs the type inference stuff on it. This should
+ /// produce a newly resolved nonterminal, which we make a record for and
+ /// return. To be extra fancy and efficient, this only makes one clone for
+ /// each type it is instantiated with.
+ Record *InstantiateNonterminal(Pattern *NT, MVT::ValueType ResultTy);
+
private:
// ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
// turning them into the more accessible NodeTypes data structure.