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