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