1 //
2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 // Copyright (C) 2013 LunarG, Inc.
4 // Copyright (c) 2002-2010 The ANGLE Project Authors.
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 // Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above
16 // copyright notice, this list of conditions and the following
17 // disclaimer in the documentation and/or other materials provided
18 // with the distribution.
19 //
20 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
21 // contributors may be used to endorse or promote products derived
22 // from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
36 //
37
38 #include "../Include/intermediate.h"
39
40 namespace glslang {
41
42 //
43 // Traverse the intermediate representation tree, and
44 // call a node type specific function for each node.
45 // Done recursively through the member function Traverse().
46 // Node types can be skipped if their function to call is 0,
47 // but their subtree will still be traversed.
48 // Nodes with children can have their whole subtree skipped
49 // if preVisit is turned on and the type specific function
50 // returns false.
51 //
52 // preVisit, postVisit, and rightToLeft control what order
53 // nodes are visited in.
54 //
55
56 //
57 // Traversal functions for terminals are straightforward....
58 //
traverse(TIntermTraverser *)59 void TIntermMethod::traverse(TIntermTraverser*)
60 {
61 // Tree should always resolve all methods as a non-method.
62 }
63
traverse(TIntermTraverser * it)64 void TIntermSymbol::traverse(TIntermTraverser *it)
65 {
66 it->visitSymbol(this);
67 }
68
traverse(TIntermTraverser * it)69 void TIntermConstantUnion::traverse(TIntermTraverser *it)
70 {
71 it->visitConstantUnion(this);
72 }
73
getAccessName() const74 const TString& TIntermSymbol::getAccessName() const {
75 if (getBasicType() == EbtBlock)
76 return getType().getTypeName();
77 else
78 return getName();
79 }
80
81 //
82 // Traverse a binary node.
83 //
traverse(TIntermTraverser * it)84 void TIntermBinary::traverse(TIntermTraverser *it)
85 {
86 bool visit = true;
87
88 //
89 // visit the node before children if pre-visiting.
90 //
91 if (it->preVisit)
92 visit = it->visitBinary(EvPreVisit, this);
93
94 //
95 // Visit the children, in the right order.
96 //
97 if (visit) {
98 it->incrementDepth(this);
99
100 if (it->rightToLeft) {
101 if (right)
102 right->traverse(it);
103
104 if (it->inVisit)
105 visit = it->visitBinary(EvInVisit, this);
106
107 if (visit && left)
108 left->traverse(it);
109 } else {
110 if (left)
111 left->traverse(it);
112
113 if (it->inVisit)
114 visit = it->visitBinary(EvInVisit, this);
115
116 if (visit && right)
117 right->traverse(it);
118 }
119
120 it->decrementDepth();
121 }
122
123 //
124 // Visit the node after the children, if requested and the traversal
125 // hasn't been canceled yet.
126 //
127 if (visit && it->postVisit)
128 it->visitBinary(EvPostVisit, this);
129 }
130
131 //
132 // Traverse a unary node. Same comments in binary node apply here.
133 //
traverse(TIntermTraverser * it)134 void TIntermUnary::traverse(TIntermTraverser *it)
135 {
136 bool visit = true;
137
138 if (it->preVisit)
139 visit = it->visitUnary(EvPreVisit, this);
140
141 if (visit) {
142 it->incrementDepth(this);
143 operand->traverse(it);
144 it->decrementDepth();
145 }
146
147 if (visit && it->postVisit)
148 it->visitUnary(EvPostVisit, this);
149 }
150
151 //
152 // Traverse an aggregate node. Same comments in binary node apply here.
153 //
traverse(TIntermTraverser * it)154 void TIntermAggregate::traverse(TIntermTraverser *it)
155 {
156 bool visit = true;
157
158 if (it->preVisit)
159 visit = it->visitAggregate(EvPreVisit, this);
160
161 if (visit) {
162 it->incrementDepth(this);
163
164 if (it->rightToLeft) {
165 for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) {
166 (*sit)->traverse(it);
167
168 if (visit && it->inVisit) {
169 if (*sit != sequence.front())
170 visit = it->visitAggregate(EvInVisit, this);
171 }
172 }
173 } else {
174 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) {
175 (*sit)->traverse(it);
176
177 if (visit && it->inVisit) {
178 if (*sit != sequence.back())
179 visit = it->visitAggregate(EvInVisit, this);
180 }
181 }
182 }
183
184 it->decrementDepth();
185 }
186
187 if (visit && it->postVisit)
188 it->visitAggregate(EvPostVisit, this);
189 }
190
191 //
192 // Traverse a selection node. Same comments in binary node apply here.
193 //
traverse(TIntermTraverser * it)194 void TIntermSelection::traverse(TIntermTraverser *it)
195 {
196 bool visit = true;
197
198 if (it->preVisit)
199 visit = it->visitSelection(EvPreVisit, this);
200
201 if (visit) {
202 it->incrementDepth(this);
203 if (it->rightToLeft) {
204 if (falseBlock)
205 falseBlock->traverse(it);
206 if (trueBlock)
207 trueBlock->traverse(it);
208 condition->traverse(it);
209 } else {
210 condition->traverse(it);
211 if (trueBlock)
212 trueBlock->traverse(it);
213 if (falseBlock)
214 falseBlock->traverse(it);
215 }
216 it->decrementDepth();
217 }
218
219 if (visit && it->postVisit)
220 it->visitSelection(EvPostVisit, this);
221 }
222
223 //
224 // Traverse a loop node. Same comments in binary node apply here.
225 //
traverse(TIntermTraverser * it)226 void TIntermLoop::traverse(TIntermTraverser *it)
227 {
228 bool visit = true;
229
230 if (it->preVisit)
231 visit = it->visitLoop(EvPreVisit, this);
232
233 if (visit) {
234 it->incrementDepth(this);
235
236 if (it->rightToLeft) {
237 if (terminal)
238 terminal->traverse(it);
239
240 if (body)
241 body->traverse(it);
242
243 if (test)
244 test->traverse(it);
245 } else {
246 if (test)
247 test->traverse(it);
248
249 if (body)
250 body->traverse(it);
251
252 if (terminal)
253 terminal->traverse(it);
254 }
255
256 it->decrementDepth();
257 }
258
259 if (visit && it->postVisit)
260 it->visitLoop(EvPostVisit, this);
261 }
262
263 //
264 // Traverse a branch node. Same comments in binary node apply here.
265 //
traverse(TIntermTraverser * it)266 void TIntermBranch::traverse(TIntermTraverser *it)
267 {
268 bool visit = true;
269
270 if (it->preVisit)
271 visit = it->visitBranch(EvPreVisit, this);
272
273 if (visit && expression) {
274 it->incrementDepth(this);
275 expression->traverse(it);
276 it->decrementDepth();
277 }
278
279 if (visit && it->postVisit)
280 it->visitBranch(EvPostVisit, this);
281 }
282
283 //
284 // Traverse a switch node.
285 //
traverse(TIntermTraverser * it)286 void TIntermSwitch::traverse(TIntermTraverser* it)
287 {
288 bool visit = true;
289
290 if (it->preVisit)
291 visit = it->visitSwitch(EvPreVisit, this);
292
293 if (visit) {
294 it->incrementDepth(this);
295 if (it->rightToLeft) {
296 body->traverse(it);
297 condition->traverse(it);
298 } else {
299 condition->traverse(it);
300 body->traverse(it);
301 }
302 it->decrementDepth();
303 }
304
305 if (visit && it->postVisit)
306 it->visitSwitch(EvPostVisit, this);
307 }
308
309 } // end namespace glslang
310