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.
7
#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
8
#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
10
#include "compiler/depgraph/DependencyGraph.h"
13
// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a
16
class TDependencyGraphBuilder : public TIntermTraverser {
18
static void build(TIntermNode* node, TDependencyGraph* graph);
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*);
27
typedef std::stack<TGraphSymbol*> TSymbolStack;
28
typedef std::set<TGraphParentNode*> TParentNodeSet;
31
// For collecting the dependent nodes of assignments, conditions, etc.
32
// while traversing the intermediate tree.
34
// This data structure is stack of sets. Each set contains dependency graph parent nodes.
39
~TNodeSetStack() { clear(); }
41
// This should only be called after a pushSet.
42
// Returns NULL if the top set is empty.
43
TParentNodeSet* getTopSet() const
45
ASSERT(!nodeSets.empty());
46
TParentNodeSet* topSet = nodeSets.top();
47
return !topSet->empty() ? topSet : NULL;
50
void pushSet() { nodeSets.push(new TParentNodeSet()); }
53
ASSERT(!nodeSets.empty());
54
delete nodeSets.top();
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.
63
ASSERT(!nodeSets.empty());
64
TParentNodeSet* oldTopSet = nodeSets.top();
67
if (!nodeSets.empty()) {
68
TParentNodeSet* newTopSet = nodeSets.top();
69
newTopSet->insert(oldTopSet->begin(), oldTopSet->end());
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)
84
nodeSets.top()->insert(node);
89
while (!nodeSets.empty())
94
typedef std::stack<TParentNodeSet*> TParentNodeSetStack;
96
TParentNodeSetStack nodeSets;
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.
103
class TNodeSetMaintainer {
105
TNodeSetMaintainer(TDependencyGraphBuilder* factory)
106
: sets(factory->mNodeSets) { sets.pushSet(); }
107
~TNodeSetMaintainer() { sets.popSet(); }
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.
117
class TNodeSetPropagatingMaintainer {
119
TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory)
120
: sets(factory->mNodeSets) { sets.pushSet(); }
121
~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); }
127
// An instance of this class keeps track of the leftmost symbol while we're exploring an
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
136
class TLeftmostSymbolMaintainer {
138
TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree)
139
: leftmostSymbols(factory->mLeftmostSymbols)
141
needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree;
142
if (needsPlaceholderSymbol)
143
leftmostSymbols.push(&subtree);
146
~TLeftmostSymbolMaintainer()
148
if (needsPlaceholderSymbol)
149
leftmostSymbols.pop();
153
TSymbolStack& leftmostSymbols;
154
bool needsPlaceholderSymbol;
157
TDependencyGraphBuilder(TDependencyGraph* graph)
158
: TIntermTraverser(true, false, false)
160
, mRightSubtree(NULL)
162
void build(TIntermNode* intermNode) { intermNode->traverse(this); }
164
void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const;
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*);
173
TGraphSymbol mLeftSubtree;
174
TGraphSymbol mRightSubtree;
176
TDependencyGraph* mGraph;
177
TNodeSetStack mNodeSets;
178
TSymbolStack mLeftmostSymbols;
181
#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H