1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "intermediate.h"
16
17 //
18 // Traverse the intermediate representation tree, and
19 // call a node type specific function for each node.
20 // Done recursively through the member function Traverse().
21 // Node types can be skipped if their function to call is 0,
22 // but their subtree will still be traversed.
23 // Nodes with children can have their whole subtree skipped
24 // if preVisit is turned on and the type specific function
25 // returns false.
26 //
27 // preVisit, postVisit, and rightToLeft control what order
28 // nodes are visited in.
29 //
30
31 //
32 // Traversal functions for terminals are straighforward....
33 //
traverse(TIntermTraverser * it)34 void TIntermSymbol::traverse(TIntermTraverser* it)
35 {
36 it->visitSymbol(this);
37 }
38
traverse(TIntermTraverser * it)39 void TIntermConstantUnion::traverse(TIntermTraverser* it)
40 {
41 it->visitConstantUnion(this);
42 }
43
44 //
45 // Traverse a binary node.
46 //
traverse(TIntermTraverser * it)47 void TIntermBinary::traverse(TIntermTraverser* it)
48 {
49 bool visit = true;
50
51 //
52 // visit the node before children if pre-visiting.
53 //
54 if(it->preVisit)
55 {
56 visit = it->visitBinary(PreVisit, this);
57 }
58
59 //
60 // Visit the children, in the right order.
61 //
62 if(visit)
63 {
64 it->incrementDepth(this);
65
66 if(it->rightToLeft)
67 {
68 if(right)
69 {
70 right->traverse(it);
71 }
72
73 if(it->inVisit)
74 {
75 visit = it->visitBinary(InVisit, this);
76 }
77
78 if(visit && left)
79 {
80 left->traverse(it);
81 }
82 }
83 else
84 {
85 if(left)
86 {
87 left->traverse(it);
88 }
89
90 if(it->inVisit)
91 {
92 visit = it->visitBinary(InVisit, this);
93 }
94
95 if(visit && right)
96 {
97 right->traverse(it);
98 }
99 }
100
101 it->decrementDepth();
102 }
103
104 //
105 // Visit the node after the children, if requested and the traversal
106 // hasn't been cancelled yet.
107 //
108 if(visit && it->postVisit)
109 {
110 it->visitBinary(PostVisit, this);
111 }
112 }
113
114 //
115 // Traverse a unary node. Same comments in binary node apply here.
116 //
traverse(TIntermTraverser * it)117 void TIntermUnary::traverse(TIntermTraverser* it)
118 {
119 bool visit = true;
120
121 if (it->preVisit)
122 visit = it->visitUnary(PreVisit, this);
123
124 if (visit) {
125 it->incrementDepth(this);
126 operand->traverse(it);
127 it->decrementDepth();
128 }
129
130 if (visit && it->postVisit)
131 it->visitUnary(PostVisit, this);
132 }
133
134 //
135 // Traverse an aggregate node. Same comments in binary node apply here.
136 //
traverse(TIntermTraverser * it)137 void TIntermAggregate::traverse(TIntermTraverser* it)
138 {
139 bool visit = true;
140
141 if(it->preVisit)
142 {
143 visit = it->visitAggregate(PreVisit, this);
144 }
145
146 if(visit)
147 {
148 it->incrementDepth(this);
149
150 if(it->rightToLeft)
151 {
152 for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
153 {
154 (*sit)->traverse(it);
155
156 if(visit && it->inVisit)
157 {
158 if(*sit != sequence.front())
159 {
160 visit = it->visitAggregate(InVisit, this);
161 }
162 }
163 }
164 }
165 else
166 {
167 for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
168 {
169 (*sit)->traverse(it);
170
171 if(visit && it->inVisit)
172 {
173 if(*sit != sequence.back())
174 {
175 visit = it->visitAggregate(InVisit, this);
176 }
177 }
178 }
179 }
180
181 it->decrementDepth();
182 }
183
184 if(visit && it->postVisit)
185 {
186 it->visitAggregate(PostVisit, this);
187 }
188 }
189
190 //
191 // Traverse a selection node. Same comments in binary node apply here.
192 //
traverse(TIntermTraverser * it)193 void TIntermSelection::traverse(TIntermTraverser* it)
194 {
195 bool visit = true;
196
197 if (it->preVisit)
198 visit = it->visitSelection(PreVisit, this);
199
200 if (visit) {
201 it->incrementDepth(this);
202 if (it->rightToLeft) {
203 if (falseBlock)
204 falseBlock->traverse(it);
205 if (trueBlock)
206 trueBlock->traverse(it);
207 condition->traverse(it);
208 } else {
209 condition->traverse(it);
210 if (trueBlock)
211 trueBlock->traverse(it);
212 if (falseBlock)
213 falseBlock->traverse(it);
214 }
215 it->decrementDepth();
216 }
217
218 if (visit && it->postVisit)
219 it->visitSelection(PostVisit, this);
220 }
221
222 //
223 // Traverse a switch node. Same comments in binary node apply here.
224 //
traverse(TIntermTraverser * it)225 void TIntermSwitch::traverse(TIntermTraverser *it)
226 {
227 bool visit = true;
228
229 if(it->preVisit)
230 visit = it->visitSwitch(PreVisit, this);
231
232 if(visit)
233 {
234 it->incrementDepth(this);
235 if(it->inVisit)
236 visit = it->visitSwitch(InVisit, this);
237 it->decrementDepth();
238 }
239
240 if(visit && it->postVisit)
241 it->visitSwitch(PostVisit, this);
242 }
243
244 //
245 // Traverse a switch node. Same comments in binary node apply here.
246 //
traverse(TIntermTraverser * it)247 void TIntermCase::traverse(TIntermTraverser *it)
248 {
249 bool visit = true;
250
251 if(it->preVisit)
252 visit = it->visitCase(PreVisit, this);
253
254 if(visit && mCondition)
255 mCondition->traverse(it);
256
257 if(visit && it->postVisit)
258 it->visitCase(PostVisit, this);
259 }
260
261 //
262 // Traverse a loop node. Same comments in binary node apply here.
263 //
traverse(TIntermTraverser * it)264 void TIntermLoop::traverse(TIntermTraverser* it)
265 {
266 bool visit = true;
267
268 if(it->preVisit)
269 {
270 visit = it->visitLoop(PreVisit, this);
271 }
272
273 if(visit)
274 {
275 it->incrementDepth(this);
276
277 if(it->rightToLeft)
278 {
279 if(expr)
280 {
281 expr->traverse(it);
282 }
283
284 if(body)
285 {
286 body->traverse(it);
287 }
288
289 if(cond)
290 {
291 cond->traverse(it);
292 }
293 }
294 else
295 {
296 if(cond)
297 {
298 cond->traverse(it);
299 }
300
301 if(body)
302 {
303 body->traverse(it);
304 }
305
306 if(expr)
307 {
308 expr->traverse(it);
309 }
310 }
311
312 it->decrementDepth();
313 }
314
315 if(visit && it->postVisit)
316 {
317 it->visitLoop(PostVisit, this);
318 }
319 }
320
321 //
322 // Traverse a branch node. Same comments in binary node apply here.
323 //
traverse(TIntermTraverser * it)324 void TIntermBranch::traverse(TIntermTraverser* it)
325 {
326 bool visit = true;
327
328 if (it->preVisit)
329 visit = it->visitBranch(PreVisit, this);
330
331 if (visit && expression) {
332 it->incrementDepth(this);
333 expression->traverse(it);
334 it->decrementDepth();
335 }
336
337 if (visit && it->postVisit)
338 it->visitBranch(PostVisit, this);
339 }
340
341