blob: 09c8e6e877ce74c609adb4de3cd602fb1bc2f10d [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// 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.
John Bauman89401822014-05-06 15:04:28 -040014
Nicolas Capenscc863da2015-01-21 15:50:55 -050015#include "intermediate.h"
John Bauman89401822014-05-06 15:04:28 -040016
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//
34void TIntermSymbol::traverse(TIntermTraverser* it)
35{
36 it->visitSymbol(this);
37}
38
39void TIntermConstantUnion::traverse(TIntermTraverser* it)
40{
41 it->visitConstantUnion(this);
42}
43
44//
45// Traverse a binary node.
46//
47void 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 }
Nicolas Capens0bac2852016-05-07 06:09:58 -040058
John Bauman89401822014-05-06 15:04:28 -040059 //
60 // Visit the children, in the right order.
61 //
62 if(visit)
63 {
Alexis Hetu76a343a2015-06-04 17:21:22 -040064 it->incrementDepth(this);
John Bauman89401822014-05-06 15:04:28 -040065
Nicolas Capens0bac2852016-05-07 06:09:58 -040066 if(it->rightToLeft)
John Bauman89401822014-05-06 15:04:28 -040067 {
68 if(right)
69 {
70 right->traverse(it);
71 }
Nicolas Capens0bac2852016-05-07 06:09:58 -040072
John Bauman89401822014-05-06 15:04:28 -040073 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 }
Nicolas Capens0bac2852016-05-07 06:09:58 -040089
John Bauman89401822014-05-06 15:04:28 -040090 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//
117void TIntermUnary::traverse(TIntermTraverser* it)
118{
119 bool visit = true;
120
121 if (it->preVisit)
122 visit = it->visitUnary(PreVisit, this);
123
124 if (visit) {
Alexis Hetu76a343a2015-06-04 17:21:22 -0400125 it->incrementDepth(this);
John Bauman89401822014-05-06 15:04:28 -0400126 operand->traverse(it);
127 it->decrementDepth();
128 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400129
John Bauman89401822014-05-06 15:04:28 -0400130 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//
137void TIntermAggregate::traverse(TIntermTraverser* it)
138{
139 bool visit = true;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400140
John Bauman89401822014-05-06 15:04:28 -0400141 if(it->preVisit)
142 {
143 visit = it->visitAggregate(PreVisit, this);
144 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400145
John Bauman89401822014-05-06 15:04:28 -0400146 if(visit)
147 {
Alexis Hetu76a343a2015-06-04 17:21:22 -0400148 it->incrementDepth(this);
John Bauman89401822014-05-06 15:04:28 -0400149
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 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400180
John Bauman89401822014-05-06 15:04:28 -0400181 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//
193void TIntermSelection::traverse(TIntermTraverser* it)
194{
195 bool visit = true;
196
197 if (it->preVisit)
198 visit = it->visitSelection(PreVisit, this);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400199
John Bauman89401822014-05-06 15:04:28 -0400200 if (visit) {
Alexis Hetu76a343a2015-06-04 17:21:22 -0400201 it->incrementDepth(this);
John Bauman89401822014-05-06 15:04:28 -0400202 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//
Alexis Hetu76a343a2015-06-04 17:21:22 -0400223// Traverse a switch node. Same comments in binary node apply here.
224//
225void 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->rightToLeft)
236 {
237 if(mStatementList)
238 mStatementList->traverse(it);
239 if(it->inVisit)
240 visit = it->visitSwitch(InVisit, this);
241 if(visit)
242 mInit->traverse(it);
243 }
244 else
245 {
246 mInit->traverse(it);
247 if(it->inVisit)
248 visit = it->visitSwitch(InVisit, this);
249 if(visit && mStatementList)
250 mStatementList->traverse(it);
251 }
252 it->decrementDepth();
253 }
254
255 if(visit && it->postVisit)
256 it->visitSwitch(PostVisit, this);
257}
258
259//
260// Traverse a switch node. Same comments in binary node apply here.
261//
262void TIntermCase::traverse(TIntermTraverser *it)
263{
264 bool visit = true;
265
266 if(it->preVisit)
267 visit = it->visitCase(PreVisit, this);
268
269 if(visit && mCondition)
270 mCondition->traverse(it);
271
272 if(visit && it->postVisit)
273 it->visitCase(PostVisit, this);
274}
275
276//
John Bauman89401822014-05-06 15:04:28 -0400277// Traverse a loop node. Same comments in binary node apply here.
278//
279void TIntermLoop::traverse(TIntermTraverser* it)
280{
281 bool visit = true;
282
283 if(it->preVisit)
284 {
285 visit = it->visitLoop(PreVisit, this);
286 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400287
John Bauman89401822014-05-06 15:04:28 -0400288 if(visit)
289 {
Alexis Hetu76a343a2015-06-04 17:21:22 -0400290 it->incrementDepth(this);
John Bauman89401822014-05-06 15:04:28 -0400291
292 if(it->rightToLeft)
293 {
294 if(expr)
295 {
296 expr->traverse(it);
297 }
298
299 if(body)
300 {
301 body->traverse(it);
302 }
303
304 if(cond)
305 {
306 cond->traverse(it);
307 }
308 }
309 else
310 {
311 if(cond)
312 {
313 cond->traverse(it);
314 }
315
316 if(body)
317 {
318 body->traverse(it);
319 }
320
321 if(expr)
322 {
323 expr->traverse(it);
324 }
325 }
326
327 it->decrementDepth();
328 }
329
330 if(visit && it->postVisit)
331 {
332 it->visitLoop(PostVisit, this);
333 }
334}
335
336//
337// Traverse a branch node. Same comments in binary node apply here.
338//
339void TIntermBranch::traverse(TIntermTraverser* it)
340{
341 bool visit = true;
342
343 if (it->preVisit)
344 visit = it->visitBranch(PreVisit, this);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400345
John Bauman89401822014-05-06 15:04:28 -0400346 if (visit && expression) {
Alexis Hetu76a343a2015-06-04 17:21:22 -0400347 it->incrementDepth(this);
John Bauman89401822014-05-06 15:04:28 -0400348 expression->traverse(it);
349 it->decrementDepth();
350 }
351
352 if (visit && it->postVisit)
353 it->visitBranch(PostVisit, this);
354}
355