blob: 2f401daee74a2b6968988af9d6cc1a7ce52e7090 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Jamie Madillb1a85f42014-08-19 15:23:24 -04007#include "compiler/translator/IntermNode.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00008
Olli Etuaho56eea882015-05-18 12:41:03 +03009void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
10{
11 if (rightToLeft)
12 mParentBlockStack.push_back(ParentBlock(node, node->getSequence()->size() - 1));
13 else
14 mParentBlockStack.push_back(ParentBlock(node, 0));
15}
16
17void TIntermTraverser::incrementParentBlockPos()
18{
19 if (rightToLeft)
20 --mParentBlockStack.back().pos;
21 else
22 ++mParentBlockStack.back().pos;
23}
24
25void TIntermTraverser::popParentBlock()
26{
27 ASSERT(!mParentBlockStack.empty());
28 mParentBlockStack.pop_back();
29}
30
31void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
32{
33 ASSERT(!mParentBlockStack.empty());
34 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos, insertions);
35 mInsertions.push_back(insert);
36}
37
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038//
39// Traverse the intermediate representation tree, and
40// call a node type specific function for each node.
41// Done recursively through the member function Traverse().
42// Node types can be skipped if their function to call is 0,
43// but their subtree will still be traversed.
44// Nodes with children can have their whole subtree skipped
45// if preVisit is turned on and the type specific function
46// returns false.
47//
48// preVisit, postVisit, and rightToLeft control what order
49// nodes are visited in.
50//
51
52//
53// Traversal functions for terminals are straighforward....
54//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070055void TIntermSymbol::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000056{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070057 it->visitSymbol(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000058}
59
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070060void TIntermConstantUnion::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000061{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070062 it->visitConstantUnion(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063}
64
65//
66// Traverse a binary node.
67//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070068void TIntermBinary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070070 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000071
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070072 //
73 // visit the node before children if pre-visiting.
74 //
75 if (it->preVisit)
76 visit = it->visitBinary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070078 //
79 // Visit the children, in the right order.
80 //
81 if (visit)
82 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -070083 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070085 if (it->rightToLeft)
86 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070087 if (mRight)
88 mRight->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070090 if (it->inVisit)
91 visit = it->visitBinary(InVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092
Zhenyao Moe40d1e92014-07-16 17:40:36 -070093 if (visit && mLeft)
94 mLeft->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -070095 }
96 else
97 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070098 if (mLeft)
99 mLeft->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700101 if (it->inVisit)
102 visit = it->visitBinary(InVisit, this);
103
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700104 if (visit && mRight)
105 mRight->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700106 }
107
108 it->decrementDepth();
109 }
110
111 //
112 // Visit the node after the children, if requested and the traversal
113 // hasn't been cancelled yet.
114 //
115 if (visit && it->postVisit)
116 it->visitBinary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117}
118
119//
120// Traverse a unary node. Same comments in binary node apply here.
121//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700122void TIntermUnary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700124 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700126 if (it->preVisit)
127 visit = it->visitUnary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700129 if (visit) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700130 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700131 mOperand->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700132 it->decrementDepth();
133 }
134
135 if (visit && it->postVisit)
136 it->visitUnary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137}
138
139//
140// Traverse an aggregate node. Same comments in binary node apply here.
141//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700142void TIntermAggregate::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700144 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700146 if (it->preVisit)
147 visit = it->visitAggregate(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700149 if (visit)
150 {
Olli Etuaho56eea882015-05-18 12:41:03 +0300151 if (mOp == EOpSequence)
152 it->pushParentBlock(this);
153
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700154 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700156 if (it->rightToLeft)
157 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700158 for (TIntermSequence::reverse_iterator sit = mSequence.rbegin();
159 sit != mSequence.rend(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700160 {
161 (*sit)->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700163 if (visit && it->inVisit)
164 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700165 if (*sit != mSequence.front())
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700166 visit = it->visitAggregate(InVisit, this);
167 }
Olli Etuaho56eea882015-05-18 12:41:03 +0300168 if (mOp == EOpSequence)
169 {
170 it->incrementParentBlockPos();
171 }
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700172 }
173 }
174 else
175 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700176 for (TIntermSequence::iterator sit = mSequence.begin();
177 sit != mSequence.end(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700178 {
179 (*sit)->traverse(it);
180
181 if (visit && it->inVisit)
182 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700183 if (*sit != mSequence.back())
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700184 visit = it->visitAggregate(InVisit, this);
185 }
Olli Etuaho56eea882015-05-18 12:41:03 +0300186 if (mOp == EOpSequence)
187 {
188 it->incrementParentBlockPos();
189 }
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700190 }
191 }
192
193 it->decrementDepth();
Olli Etuaho56eea882015-05-18 12:41:03 +0300194
195 if (mOp == EOpSequence)
196 it->popParentBlock();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700197 }
198
199 if (visit && it->postVisit)
200 it->visitAggregate(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201}
202
203//
204// Traverse a selection node. Same comments in binary node apply here.
205//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700206void TIntermSelection::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700208 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700210 if (it->preVisit)
211 visit = it->visitSelection(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700213 if (visit)
214 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700215 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700216 if (it->rightToLeft)
217 {
218 if (mFalseBlock)
219 mFalseBlock->traverse(it);
220 if (mTrueBlock)
221 mTrueBlock->traverse(it);
222 mCondition->traverse(it);
223 }
224 else
225 {
226 mCondition->traverse(it);
227 if (mTrueBlock)
228 mTrueBlock->traverse(it);
229 if (mFalseBlock)
230 mFalseBlock->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700231 }
232 it->decrementDepth();
233 }
234
235 if (visit && it->postVisit)
236 it->visitSelection(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237}
238
239//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200240// Traverse a switch node. Same comments in binary node apply here.
241//
242void TIntermSwitch::traverse(TIntermTraverser *it)
243{
244 bool visit = true;
245
246 if (it->preVisit)
247 visit = it->visitSwitch(PreVisit, this);
248
249 if (visit)
250 {
251 it->incrementDepth(this);
252 if (it->rightToLeft)
253 {
254 if (mStatementList)
255 mStatementList->traverse(it);
256 if (it->inVisit)
257 visit = it->visitSwitch(InVisit, this);
258 if (visit)
259 mInit->traverse(it);
260 }
261 else
262 {
263 mInit->traverse(it);
264 if (it->inVisit)
265 visit = it->visitSwitch(InVisit, this);
266 if (visit && mStatementList)
267 mStatementList->traverse(it);
268 }
269 it->decrementDepth();
270 }
271
272 if (visit && it->postVisit)
273 it->visitSwitch(PostVisit, this);
274}
275
276//
277// Traverse a switch node. Same comments in binary node apply here.
278//
279void TIntermCase::traverse(TIntermTraverser *it)
280{
281 bool visit = true;
282
283 if (it->preVisit)
284 visit = it->visitCase(PreVisit, this);
285
286 if (visit && mCondition)
287 mCondition->traverse(it);
288
289 if (visit && it->postVisit)
290 it->visitCase(PostVisit, this);
291}
292
293//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294// Traverse a loop node. Same comments in binary node apply here.
295//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700296void TIntermLoop::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700298 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700300 if (it->preVisit)
301 visit = it->visitLoop(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700303 if (visit)
304 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700305 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700307 if (it->rightToLeft)
308 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700309 if (mExpr)
310 mExpr->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700312 if (mBody)
313 mBody->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700315 if (mCond)
316 mCond->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700317
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700318 if (mInit)
319 mInit->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700320 }
321 else
322 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700323 if (mInit)
324 mInit->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700325
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700326 if (mCond)
327 mCond->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700329 if (mBody)
330 mBody->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000331
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700332 if (mExpr)
333 mExpr->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700334 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700336 it->decrementDepth();
337 }
338
339 if (visit && it->postVisit)
340 it->visitLoop(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341}
342
343//
344// Traverse a branch node. Same comments in binary node apply here.
345//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700346void TIntermBranch::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000347{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700348 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700350 if (it->preVisit)
351 visit = it->visitBranch(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700353 if (visit && mExpression) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700354 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700355 mExpression->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700356 it->decrementDepth();
357 }
358
359 if (visit && it->postVisit)
360 it->visitBranch(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361}
362
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400363void TIntermRaw::traverse(TIntermTraverser *it)
364{
365 it->visitRaw(this);
366}