Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
michael@0 | 1 | // |
michael@0 | 2 | // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. |
michael@0 | 3 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 4 | // found in the LICENSE file. |
michael@0 | 5 | // |
michael@0 | 6 | |
michael@0 | 7 | #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H |
michael@0 | 8 | #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H |
michael@0 | 9 | |
michael@0 | 10 | #include "compiler/intermediate.h" |
michael@0 | 11 | |
michael@0 | 12 | #include <set> |
michael@0 | 13 | #include <stack> |
michael@0 | 14 | |
michael@0 | 15 | class TGraphNode; |
michael@0 | 16 | class TGraphParentNode; |
michael@0 | 17 | class TGraphArgument; |
michael@0 | 18 | class TGraphFunctionCall; |
michael@0 | 19 | class TGraphSymbol; |
michael@0 | 20 | class TGraphSelection; |
michael@0 | 21 | class TGraphLoop; |
michael@0 | 22 | class TGraphLogicalOp; |
michael@0 | 23 | class TDependencyGraphTraverser; |
michael@0 | 24 | class TDependencyGraphOutput; |
michael@0 | 25 | |
michael@0 | 26 | typedef std::set<TGraphNode*> TGraphNodeSet; |
michael@0 | 27 | typedef std::vector<TGraphNode*> TGraphNodeVector; |
michael@0 | 28 | typedef std::vector<TGraphSymbol*> TGraphSymbolVector; |
michael@0 | 29 | typedef std::vector<TGraphFunctionCall*> TFunctionCallVector; |
michael@0 | 30 | |
michael@0 | 31 | // |
michael@0 | 32 | // Base class for all dependency graph nodes. |
michael@0 | 33 | // |
michael@0 | 34 | class TGraphNode { |
michael@0 | 35 | public: |
michael@0 | 36 | TGraphNode(TIntermNode* node) : intermNode(node) {} |
michael@0 | 37 | virtual ~TGraphNode() {} |
michael@0 | 38 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 39 | protected: |
michael@0 | 40 | TIntermNode* intermNode; |
michael@0 | 41 | }; |
michael@0 | 42 | |
michael@0 | 43 | // |
michael@0 | 44 | // Base class for dependency graph nodes that may have children. |
michael@0 | 45 | // |
michael@0 | 46 | class TGraphParentNode : public TGraphNode { |
michael@0 | 47 | public: |
michael@0 | 48 | TGraphParentNode(TIntermNode* node) : TGraphNode(node) {} |
michael@0 | 49 | virtual ~TGraphParentNode() {} |
michael@0 | 50 | void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); } |
michael@0 | 51 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 52 | private: |
michael@0 | 53 | TGraphNodeSet mDependentNodes; |
michael@0 | 54 | }; |
michael@0 | 55 | |
michael@0 | 56 | // |
michael@0 | 57 | // Handle function call arguments. |
michael@0 | 58 | // |
michael@0 | 59 | class TGraphArgument : public TGraphParentNode { |
michael@0 | 60 | public: |
michael@0 | 61 | TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber) |
michael@0 | 62 | : TGraphParentNode(intermFunctionCall) |
michael@0 | 63 | , mArgumentNumber(argumentNumber) {} |
michael@0 | 64 | virtual ~TGraphArgument() {} |
michael@0 | 65 | const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } |
michael@0 | 66 | int getArgumentNumber() const { return mArgumentNumber; } |
michael@0 | 67 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 68 | private: |
michael@0 | 69 | int mArgumentNumber; |
michael@0 | 70 | }; |
michael@0 | 71 | |
michael@0 | 72 | // |
michael@0 | 73 | // Handle function calls. |
michael@0 | 74 | // |
michael@0 | 75 | class TGraphFunctionCall : public TGraphParentNode { |
michael@0 | 76 | public: |
michael@0 | 77 | TGraphFunctionCall(TIntermAggregate* intermFunctionCall) |
michael@0 | 78 | : TGraphParentNode(intermFunctionCall) {} |
michael@0 | 79 | virtual ~TGraphFunctionCall() {} |
michael@0 | 80 | const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } |
michael@0 | 81 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 82 | }; |
michael@0 | 83 | |
michael@0 | 84 | // |
michael@0 | 85 | // Handle symbols. |
michael@0 | 86 | // |
michael@0 | 87 | class TGraphSymbol : public TGraphParentNode { |
michael@0 | 88 | public: |
michael@0 | 89 | TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {} |
michael@0 | 90 | virtual ~TGraphSymbol() {} |
michael@0 | 91 | const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); } |
michael@0 | 92 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 93 | }; |
michael@0 | 94 | |
michael@0 | 95 | // |
michael@0 | 96 | // Handle if statements and ternary operators. |
michael@0 | 97 | // |
michael@0 | 98 | class TGraphSelection : public TGraphNode { |
michael@0 | 99 | public: |
michael@0 | 100 | TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {} |
michael@0 | 101 | virtual ~TGraphSelection() {} |
michael@0 | 102 | const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); } |
michael@0 | 103 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 104 | }; |
michael@0 | 105 | |
michael@0 | 106 | // |
michael@0 | 107 | // Handle for, do-while, and while loops. |
michael@0 | 108 | // |
michael@0 | 109 | class TGraphLoop : public TGraphNode { |
michael@0 | 110 | public: |
michael@0 | 111 | TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {} |
michael@0 | 112 | virtual ~TGraphLoop() {} |
michael@0 | 113 | const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); } |
michael@0 | 114 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 115 | }; |
michael@0 | 116 | |
michael@0 | 117 | // |
michael@0 | 118 | // Handle logical and, or. |
michael@0 | 119 | // |
michael@0 | 120 | class TGraphLogicalOp : public TGraphNode { |
michael@0 | 121 | public: |
michael@0 | 122 | TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {} |
michael@0 | 123 | virtual ~TGraphLogicalOp() {} |
michael@0 | 124 | const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); } |
michael@0 | 125 | const char* getOpString() const; |
michael@0 | 126 | virtual void traverse(TDependencyGraphTraverser* graphTraverser); |
michael@0 | 127 | }; |
michael@0 | 128 | |
michael@0 | 129 | // |
michael@0 | 130 | // A dependency graph of symbols, function calls, conditions etc. |
michael@0 | 131 | // |
michael@0 | 132 | // This class provides an interface to the entry points of the dependency graph. |
michael@0 | 133 | // |
michael@0 | 134 | // Dependency graph nodes should be created by using one of the provided "create..." methods. |
michael@0 | 135 | // This class (and nobody else) manages the memory of the created nodes. |
michael@0 | 136 | // Nodes may not be removed after being added, so all created nodes will exist while the |
michael@0 | 137 | // TDependencyGraph instance exists. |
michael@0 | 138 | // |
michael@0 | 139 | class TDependencyGraph { |
michael@0 | 140 | public: |
michael@0 | 141 | TDependencyGraph(TIntermNode* intermNode); |
michael@0 | 142 | ~TDependencyGraph(); |
michael@0 | 143 | TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); } |
michael@0 | 144 | TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); } |
michael@0 | 145 | |
michael@0 | 146 | TGraphSymbolVector::const_iterator beginSamplerSymbols() const |
michael@0 | 147 | { |
michael@0 | 148 | return mSamplerSymbols.begin(); |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | TGraphSymbolVector::const_iterator endSamplerSymbols() const |
michael@0 | 152 | { |
michael@0 | 153 | return mSamplerSymbols.end(); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const |
michael@0 | 157 | { |
michael@0 | 158 | return mUserDefinedFunctionCalls.begin(); |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const |
michael@0 | 162 | { |
michael@0 | 163 | return mUserDefinedFunctionCalls.end(); |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber); |
michael@0 | 167 | TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall); |
michael@0 | 168 | TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol); |
michael@0 | 169 | TGraphSelection* createSelection(TIntermSelection* intermSelection); |
michael@0 | 170 | TGraphLoop* createLoop(TIntermLoop* intermLoop); |
michael@0 | 171 | TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp); |
michael@0 | 172 | private: |
michael@0 | 173 | typedef TMap<int, TGraphSymbol*> TSymbolIdMap; |
michael@0 | 174 | typedef std::pair<int, TGraphSymbol*> TSymbolIdPair; |
michael@0 | 175 | |
michael@0 | 176 | TGraphNodeVector mAllNodes; |
michael@0 | 177 | TGraphSymbolVector mSamplerSymbols; |
michael@0 | 178 | TFunctionCallVector mUserDefinedFunctionCalls; |
michael@0 | 179 | TSymbolIdMap mSymbolIdMap; |
michael@0 | 180 | }; |
michael@0 | 181 | |
michael@0 | 182 | // |
michael@0 | 183 | // For traversing the dependency graph. Users should derive from this, |
michael@0 | 184 | // put their traversal specific data in it, and then pass it to a |
michael@0 | 185 | // traverse method. |
michael@0 | 186 | // |
michael@0 | 187 | // When using this, just fill in the methods for nodes you want visited. |
michael@0 | 188 | // |
michael@0 | 189 | class TDependencyGraphTraverser { |
michael@0 | 190 | public: |
michael@0 | 191 | TDependencyGraphTraverser() : mDepth(0) {} |
michael@0 | 192 | |
michael@0 | 193 | virtual void visitSymbol(TGraphSymbol* symbol) {}; |
michael@0 | 194 | virtual void visitArgument(TGraphArgument* selection) {}; |
michael@0 | 195 | virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {}; |
michael@0 | 196 | virtual void visitSelection(TGraphSelection* selection) {}; |
michael@0 | 197 | virtual void visitLoop(TGraphLoop* loop) {}; |
michael@0 | 198 | virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {}; |
michael@0 | 199 | |
michael@0 | 200 | int getDepth() const { return mDepth; } |
michael@0 | 201 | void incrementDepth() { ++mDepth; } |
michael@0 | 202 | void decrementDepth() { --mDepth; } |
michael@0 | 203 | |
michael@0 | 204 | void clearVisited() { mVisited.clear(); } |
michael@0 | 205 | void markVisited(TGraphNode* node) { mVisited.insert(node); } |
michael@0 | 206 | bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); } |
michael@0 | 207 | private: |
michael@0 | 208 | int mDepth; |
michael@0 | 209 | TGraphNodeSet mVisited; |
michael@0 | 210 | }; |
michael@0 | 211 | |
michael@0 | 212 | #endif |