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