From 5709e512b19b9b97f3011197bda04ab8e1fe191b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 7 Aug 2003 21:02:56 +0000 Subject: [PATCH] Implement type-inference/checking for non-terminal references git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7686 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../tools/TableGen/InstrSelectorEmitter.cpp | 53 +++++++++++++------ support/tools/TableGen/InstrSelectorEmitter.h | 18 ++++++- utils/TableGen/InstrSelectorEmitter.cpp | 53 +++++++++++++------ utils/TableGen/InstrSelectorEmitter.h | 18 ++++++- 4 files changed, 106 insertions(+), 36 deletions(-) diff --git a/support/tools/TableGen/InstrSelectorEmitter.cpp b/support/tools/TableGen/InstrSelectorEmitter.cpp index d7d91f03b95..250c8975c13 100644 --- a/support/tools/TableGen/InstrSelectorEmitter.cpp +++ b/support/tools/TableGen/InstrSelectorEmitter.cpp @@ -99,7 +99,7 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec, Resolved = !AnyUnset; } -void Pattern::error(const std::string &Msg) { +void Pattern::error(const std::string &Msg) const { std::string M = "In "; switch (PTy) { case Nonterminal: M += "nonterminal "; break; @@ -109,17 +109,19 @@ void Pattern::error(const std::string &Msg) { throw M + TheRecord->getName() + ": " + Msg; } -static MVT::ValueType getIntrinsicType(Record *R) { +/// getIntrinsicType - Check to see if the specified record has an intrinsic +/// type which should be applied to it. This infer the type of register +/// references from the register file information, for example. +/// +MVT::ValueType Pattern::getIntrinsicType(Record *R) const { // Check to see if this is a register or a register class... - if (R->isSubClassOf("RegisterClass")) { + if (R->isSubClassOf("RegisterClass")) return getValueType(R->getValueAsDef("RegType")); - } else if (R->isSubClassOf("Register")) { + else if (R->isSubClassOf("Nonterminal")) + return ISE.ReadNonterminal(R)->getTree()->getType(); + else if (R->isSubClassOf("Register")) { std::cerr << "WARNING: Explicit registers not handled yet!\n"; return MVT::Other; - } else if (R->isSubClassOf("Nonterminal")) { - //std::cerr << "Warning nonterminal type not handled yet:" << R->getName() - // << "\n"; - return MVT::Other; } throw "Error: Unknown value used: " + R->getName(); @@ -238,6 +240,15 @@ 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. +/// +void Pattern::InstantiateNonterminalsReferenced() { + +} + + std::ostream &operator<<(std::ostream &OS, const Pattern &P) { switch (P.getPatternType()) { case Pattern::Nonterminal: OS << "Nonterminal pattern "; break; @@ -300,16 +311,23 @@ void InstrSelectorEmitter::ReadNodeTypes() { DEBUG(std::cerr << "DONE!\n"); } +Pattern *InstrSelectorEmitter::ReadNonterminal(Record *R) { + Pattern *&P = Patterns[R]; + if (P) return P; // Don't reread it! + + DagInit *DI = R->getValueAsDag("Pattern"); + P = new Pattern(Pattern::Nonterminal, DI, R, *this); + DEBUG(std::cerr << "Parsed " << *P << "\n"); + return P; +} + + // ReadNonTerminals - Read in all nonterminals and incorporate them into our // pattern database. void InstrSelectorEmitter::ReadNonterminals() { std::vector NTs = Records.getAllDerivedDefinitions("Nonterminal"); - for (unsigned i = 0, e = NTs.size(); i != e; ++i) { - DagInit *DI = NTs[i]->getValueAsDag("Pattern"); - - Patterns[NTs[i]] = new Pattern(Pattern::Nonterminal, DI, NTs[i], *this); - DEBUG(std::cerr << "Parsed " << *Patterns[NTs[i]] << "\n"); - } + for (unsigned i = 0, e = NTs.size(); i != e; ++i) + ReadNonterminal(NTs[i]); } @@ -342,11 +360,12 @@ void InstrSelectorEmitter::ReadExpanderPatterns() { // InstantiateNonterminals - Instantiate any unresolved nonterminals with // information from the context that they are used in. +// void InstrSelectorEmitter::InstantiateNonterminals() { for (std::map::iterator I = Patterns.begin(), - E = Patterns.end(); I != E; ++I) { - - } + E = Patterns.end(); I != E; ++I) + if (I->second->isResolved()) + I->second->InstantiateNonterminalsReferenced(); } diff --git a/support/tools/TableGen/InstrSelectorEmitter.h b/support/tools/TableGen/InstrSelectorEmitter.h index 8a8734b9349..e8c8fad33f5 100644 --- a/support/tools/TableGen/InstrSelectorEmitter.h +++ b/support/tools/TableGen/InstrSelectorEmitter.h @@ -162,10 +162,15 @@ 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(); private: + MVT::ValueType getIntrinsicType(Record *R) const; TreePatternNode *ParseTreePattern(DagInit *DI); bool InferTypes(TreePatternNode *N, bool &MadeChange); - void error(const std::string &Msg); + void error(const std::string &Msg) const; }; std::ostream &operator<<(std::ostream &OS, const Pattern &P); @@ -193,6 +198,17 @@ public: const CodeGenTarget &getTarget() const { return Target; } std::map &getNodeTypes() { return NodeTypes; } + /// getPattern - return the pattern corresponding to the specified record, or + /// null if there is none. + Pattern *getPattern(Record *R) const { + std::map::const_iterator I = Patterns.find(R); + return I != Patterns.end() ? I->second : 0; + } + + /// ReadNonterminal - This method parses the specified record as a + /// nonterminal, but only if it hasn't been read in already. + Pattern *ReadNonterminal(Record *R); + private: // ReadNodeTypes - Read in all of the node types in the current RecordKeeper, // turning them into the more accessible NodeTypes data structure. diff --git a/utils/TableGen/InstrSelectorEmitter.cpp b/utils/TableGen/InstrSelectorEmitter.cpp index d7d91f03b95..250c8975c13 100644 --- a/utils/TableGen/InstrSelectorEmitter.cpp +++ b/utils/TableGen/InstrSelectorEmitter.cpp @@ -99,7 +99,7 @@ Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec, Resolved = !AnyUnset; } -void Pattern::error(const std::string &Msg) { +void Pattern::error(const std::string &Msg) const { std::string M = "In "; switch (PTy) { case Nonterminal: M += "nonterminal "; break; @@ -109,17 +109,19 @@ void Pattern::error(const std::string &Msg) { throw M + TheRecord->getName() + ": " + Msg; } -static MVT::ValueType getIntrinsicType(Record *R) { +/// getIntrinsicType - Check to see if the specified record has an intrinsic +/// type which should be applied to it. This infer the type of register +/// references from the register file information, for example. +/// +MVT::ValueType Pattern::getIntrinsicType(Record *R) const { // Check to see if this is a register or a register class... - if (R->isSubClassOf("RegisterClass")) { + if (R->isSubClassOf("RegisterClass")) return getValueType(R->getValueAsDef("RegType")); - } else if (R->isSubClassOf("Register")) { + else if (R->isSubClassOf("Nonterminal")) + return ISE.ReadNonterminal(R)->getTree()->getType(); + else if (R->isSubClassOf("Register")) { std::cerr << "WARNING: Explicit registers not handled yet!\n"; return MVT::Other; - } else if (R->isSubClassOf("Nonterminal")) { - //std::cerr << "Warning nonterminal type not handled yet:" << R->getName() - // << "\n"; - return MVT::Other; } throw "Error: Unknown value used: " + R->getName(); @@ -238,6 +240,15 @@ 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. +/// +void Pattern::InstantiateNonterminalsReferenced() { + +} + + std::ostream &operator<<(std::ostream &OS, const Pattern &P) { switch (P.getPatternType()) { case Pattern::Nonterminal: OS << "Nonterminal pattern "; break; @@ -300,16 +311,23 @@ void InstrSelectorEmitter::ReadNodeTypes() { DEBUG(std::cerr << "DONE!\n"); } +Pattern *InstrSelectorEmitter::ReadNonterminal(Record *R) { + Pattern *&P = Patterns[R]; + if (P) return P; // Don't reread it! + + DagInit *DI = R->getValueAsDag("Pattern"); + P = new Pattern(Pattern::Nonterminal, DI, R, *this); + DEBUG(std::cerr << "Parsed " << *P << "\n"); + return P; +} + + // ReadNonTerminals - Read in all nonterminals and incorporate them into our // pattern database. void InstrSelectorEmitter::ReadNonterminals() { std::vector NTs = Records.getAllDerivedDefinitions("Nonterminal"); - for (unsigned i = 0, e = NTs.size(); i != e; ++i) { - DagInit *DI = NTs[i]->getValueAsDag("Pattern"); - - Patterns[NTs[i]] = new Pattern(Pattern::Nonterminal, DI, NTs[i], *this); - DEBUG(std::cerr << "Parsed " << *Patterns[NTs[i]] << "\n"); - } + for (unsigned i = 0, e = NTs.size(); i != e; ++i) + ReadNonterminal(NTs[i]); } @@ -342,11 +360,12 @@ void InstrSelectorEmitter::ReadExpanderPatterns() { // InstantiateNonterminals - Instantiate any unresolved nonterminals with // information from the context that they are used in. +// void InstrSelectorEmitter::InstantiateNonterminals() { for (std::map::iterator I = Patterns.begin(), - E = Patterns.end(); I != E; ++I) { - - } + E = Patterns.end(); I != E; ++I) + if (I->second->isResolved()) + I->second->InstantiateNonterminalsReferenced(); } diff --git a/utils/TableGen/InstrSelectorEmitter.h b/utils/TableGen/InstrSelectorEmitter.h index 8a8734b9349..e8c8fad33f5 100644 --- a/utils/TableGen/InstrSelectorEmitter.h +++ b/utils/TableGen/InstrSelectorEmitter.h @@ -162,10 +162,15 @@ 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(); private: + MVT::ValueType getIntrinsicType(Record *R) const; TreePatternNode *ParseTreePattern(DagInit *DI); bool InferTypes(TreePatternNode *N, bool &MadeChange); - void error(const std::string &Msg); + void error(const std::string &Msg) const; }; std::ostream &operator<<(std::ostream &OS, const Pattern &P); @@ -193,6 +198,17 @@ public: const CodeGenTarget &getTarget() const { return Target; } std::map &getNodeTypes() { return NodeTypes; } + /// getPattern - return the pattern corresponding to the specified record, or + /// null if there is none. + Pattern *getPattern(Record *R) const { + std::map::const_iterator I = Patterns.find(R); + return I != Patterns.end() ? I->second : 0; + } + + /// ReadNonterminal - This method parses the specified record as a + /// nonterminal, but only if it hasn't been read in already. + Pattern *ReadNonterminal(Record *R); + private: // ReadNodeTypes - Read in all of the node types in the current RecordKeeper, // turning them into the more accessible NodeTypes data structure. -- 2.34.1