|
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_BUILDER_H |
|
8 #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H |
|
9 |
|
10 #include "compiler/depgraph/DependencyGraph.h" |
|
11 |
|
12 // |
|
13 // Creates a dependency graph of symbols, function calls, conditions etc. by traversing a |
|
14 // intermediate tree. |
|
15 // |
|
16 class TDependencyGraphBuilder : public TIntermTraverser { |
|
17 public: |
|
18 static void build(TIntermNode* node, TDependencyGraph* graph); |
|
19 |
|
20 virtual void visitSymbol(TIntermSymbol*); |
|
21 virtual bool visitBinary(Visit visit, TIntermBinary*); |
|
22 virtual bool visitSelection(Visit visit, TIntermSelection*); |
|
23 virtual bool visitAggregate(Visit visit, TIntermAggregate*); |
|
24 virtual bool visitLoop(Visit visit, TIntermLoop*); |
|
25 |
|
26 private: |
|
27 typedef std::stack<TGraphSymbol*> TSymbolStack; |
|
28 typedef std::set<TGraphParentNode*> TParentNodeSet; |
|
29 |
|
30 // |
|
31 // For collecting the dependent nodes of assignments, conditions, etc. |
|
32 // while traversing the intermediate tree. |
|
33 // |
|
34 // This data structure is stack of sets. Each set contains dependency graph parent nodes. |
|
35 // |
|
36 class TNodeSetStack { |
|
37 public: |
|
38 TNodeSetStack() {}; |
|
39 ~TNodeSetStack() { clear(); } |
|
40 |
|
41 // This should only be called after a pushSet. |
|
42 // Returns NULL if the top set is empty. |
|
43 TParentNodeSet* getTopSet() const |
|
44 { |
|
45 ASSERT(!nodeSets.empty()); |
|
46 TParentNodeSet* topSet = nodeSets.top(); |
|
47 return !topSet->empty() ? topSet : NULL; |
|
48 } |
|
49 |
|
50 void pushSet() { nodeSets.push(new TParentNodeSet()); } |
|
51 void popSet() |
|
52 { |
|
53 ASSERT(!nodeSets.empty()); |
|
54 delete nodeSets.top(); |
|
55 nodeSets.pop(); |
|
56 } |
|
57 |
|
58 // Pops the top set and adds its contents to the new top set. |
|
59 // This should only be called after a pushSet. |
|
60 // If there is no set below the top set, the top set is just deleted. |
|
61 void popSetIntoNext() |
|
62 { |
|
63 ASSERT(!nodeSets.empty()); |
|
64 TParentNodeSet* oldTopSet = nodeSets.top(); |
|
65 nodeSets.pop(); |
|
66 |
|
67 if (!nodeSets.empty()) { |
|
68 TParentNodeSet* newTopSet = nodeSets.top(); |
|
69 newTopSet->insert(oldTopSet->begin(), oldTopSet->end()); |
|
70 } |
|
71 |
|
72 delete oldTopSet; |
|
73 } |
|
74 |
|
75 // Does nothing if there is no top set. |
|
76 // This can be called when there is no top set if we are visiting |
|
77 // symbols that are not under an assignment or condition. |
|
78 // We don't need to track those symbols. |
|
79 void insertIntoTopSet(TGraphParentNode* node) |
|
80 { |
|
81 if (nodeSets.empty()) |
|
82 return; |
|
83 |
|
84 nodeSets.top()->insert(node); |
|
85 } |
|
86 |
|
87 void clear() |
|
88 { |
|
89 while (!nodeSets.empty()) |
|
90 popSet(); |
|
91 } |
|
92 |
|
93 private: |
|
94 typedef std::stack<TParentNodeSet*> TParentNodeSetStack; |
|
95 |
|
96 TParentNodeSetStack nodeSets; |
|
97 }; |
|
98 |
|
99 // |
|
100 // An instance of this class pushes a new node set when instantiated. |
|
101 // When the instance goes out of scope, it and pops the node set. |
|
102 // |
|
103 class TNodeSetMaintainer { |
|
104 public: |
|
105 TNodeSetMaintainer(TDependencyGraphBuilder* factory) |
|
106 : sets(factory->mNodeSets) { sets.pushSet(); } |
|
107 ~TNodeSetMaintainer() { sets.popSet(); } |
|
108 protected: |
|
109 TNodeSetStack& sets; |
|
110 }; |
|
111 |
|
112 // |
|
113 // An instance of this class pushes a new node set when instantiated. |
|
114 // When the instance goes out of scope, it and pops the top node set and adds its contents to |
|
115 // the new top node set. |
|
116 // |
|
117 class TNodeSetPropagatingMaintainer { |
|
118 public: |
|
119 TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory) |
|
120 : sets(factory->mNodeSets) { sets.pushSet(); } |
|
121 ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); } |
|
122 protected: |
|
123 TNodeSetStack& sets; |
|
124 }; |
|
125 |
|
126 // |
|
127 // An instance of this class keeps track of the leftmost symbol while we're exploring an |
|
128 // assignment. |
|
129 // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree, |
|
130 // and kRightSubtree under a right subtree. |
|
131 // When it goes out of scope, it will pop the leftmost symbol at the top of the scope. |
|
132 // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol. |
|
133 // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost |
|
134 // symbol. |
|
135 // |
|
136 class TLeftmostSymbolMaintainer { |
|
137 public: |
|
138 TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree) |
|
139 : leftmostSymbols(factory->mLeftmostSymbols) |
|
140 { |
|
141 needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree; |
|
142 if (needsPlaceholderSymbol) |
|
143 leftmostSymbols.push(&subtree); |
|
144 } |
|
145 |
|
146 ~TLeftmostSymbolMaintainer() |
|
147 { |
|
148 if (needsPlaceholderSymbol) |
|
149 leftmostSymbols.pop(); |
|
150 } |
|
151 |
|
152 protected: |
|
153 TSymbolStack& leftmostSymbols; |
|
154 bool needsPlaceholderSymbol; |
|
155 }; |
|
156 |
|
157 TDependencyGraphBuilder(TDependencyGraph* graph) |
|
158 : TIntermTraverser(true, false, false) |
|
159 , mLeftSubtree(NULL) |
|
160 , mRightSubtree(NULL) |
|
161 , mGraph(graph) {} |
|
162 void build(TIntermNode* intermNode) { intermNode->traverse(this); } |
|
163 |
|
164 void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const; |
|
165 |
|
166 void visitAssignment(TIntermBinary*); |
|
167 void visitLogicalOp(TIntermBinary*); |
|
168 void visitBinaryChildren(TIntermBinary*); |
|
169 void visitFunctionDefinition(TIntermAggregate*); |
|
170 void visitFunctionCall(TIntermAggregate* intermFunctionCall); |
|
171 void visitAggregateChildren(TIntermAggregate*); |
|
172 |
|
173 TGraphSymbol mLeftSubtree; |
|
174 TGraphSymbol mRightSubtree; |
|
175 |
|
176 TDependencyGraph* mGraph; |
|
177 TNodeSetStack mNodeSets; |
|
178 TSymbolStack mLeftmostSymbols; |
|
179 }; |
|
180 |
|
181 #endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H |