blob: 53ff8f907b7e61eb0a3e901164136321ef38d67a [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
Olli Etuahocccf2b02017-07-05 14:50:54 +03007#include "compiler/translator/IntermTraverse.h"
8
Olli Etuahod4f303e2015-05-20 17:09:06 +03009#include "compiler/translator/InfoSink.h"
Olli Etuaho180f43c2017-10-09 17:00:44 +030010#include "compiler/translator/IntermNode_util.h"
Olli Etuaho217fe6e2015-08-05 13:25:08 +030011#include "compiler/translator/SymbolTable.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012
Jamie Madill45bcc782016-11-07 13:58:48 -050013namespace sh
14{
15
Olli Etuaho27446bd2015-08-10 14:59:53 +030016void TIntermSymbol::traverse(TIntermTraverser *it)
17{
18 it->traverseSymbol(this);
19}
20
21void TIntermRaw::traverse(TIntermTraverser *it)
22{
23 it->traverseRaw(this);
24}
25
26void TIntermConstantUnion::traverse(TIntermTraverser *it)
27{
28 it->traverseConstantUnion(this);
29}
30
Olli Etuahob6fa0432016-09-28 16:28:05 +010031void TIntermSwizzle::traverse(TIntermTraverser *it)
32{
33 it->traverseSwizzle(this);
34}
35
Olli Etuaho27446bd2015-08-10 14:59:53 +030036void TIntermBinary::traverse(TIntermTraverser *it)
37{
38 it->traverseBinary(this);
39}
40
41void TIntermUnary::traverse(TIntermTraverser *it)
42{
43 it->traverseUnary(this);
44}
45
Olli Etuahod0bad2c2016-09-09 18:01:16 +030046void TIntermTernary::traverse(TIntermTraverser *it)
47{
48 it->traverseTernary(this);
49}
50
Olli Etuaho57961272016-09-14 13:57:46 +030051void TIntermIfElse::traverse(TIntermTraverser *it)
Olli Etuaho27446bd2015-08-10 14:59:53 +030052{
Olli Etuaho57961272016-09-14 13:57:46 +030053 it->traverseIfElse(this);
Olli Etuaho27446bd2015-08-10 14:59:53 +030054}
55
56void TIntermSwitch::traverse(TIntermTraverser *it)
57{
58 it->traverseSwitch(this);
59}
60
61void TIntermCase::traverse(TIntermTraverser *it)
62{
63 it->traverseCase(this);
64}
65
Olli Etuaho336b1472016-10-05 16:37:55 +010066void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
67{
68 it->traverseFunctionDefinition(this);
69}
70
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010071void TIntermBlock::traverse(TIntermTraverser *it)
72{
73 it->traverseBlock(this);
74}
75
Olli Etuahobf4e1b72016-12-09 11:30:15 +000076void TIntermInvariantDeclaration::traverse(TIntermTraverser *it)
77{
78 it->traverseInvariantDeclaration(this);
79}
80
Olli Etuaho13389b62016-10-16 11:48:18 +010081void TIntermDeclaration::traverse(TIntermTraverser *it)
82{
83 it->traverseDeclaration(this);
84}
85
Olli Etuaho16c745a2017-01-16 17:02:27 +000086void TIntermFunctionPrototype::traverse(TIntermTraverser *it)
87{
88 it->traverseFunctionPrototype(this);
89}
90
Olli Etuaho27446bd2015-08-10 14:59:53 +030091void TIntermAggregate::traverse(TIntermTraverser *it)
92{
93 it->traverseAggregate(this);
94}
95
96void TIntermLoop::traverse(TIntermTraverser *it)
97{
98 it->traverseLoop(this);
99}
100
101void TIntermBranch::traverse(TIntermTraverser *it)
102{
103 it->traverseBranch(this);
104}
105
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300106TIntermTraverser::TIntermTraverser(bool preVisit,
107 bool inVisit,
108 bool postVisit,
109 TSymbolTable *symbolTable)
Jamie Madill03d863c2016-07-27 18:15:53 -0400110 : preVisit(preVisit),
111 inVisit(inVisit),
112 postVisit(postVisit),
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000113 mDepth(-1),
Jamie Madill03d863c2016-07-27 18:15:53 -0400114 mMaxDepth(0),
115 mInGlobalScope(true),
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300116 mSymbolTable(symbolTable),
Olli Etuaho4dd06d52017-07-05 12:41:06 +0300117 mTemporaryId(nullptr)
Jamie Madill03d863c2016-07-27 18:15:53 -0400118{
119}
120
121TIntermTraverser::~TIntermTraverser()
122{
123}
124
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100125void TIntermTraverser::pushParentBlock(TIntermBlock *node)
Olli Etuaho56eea882015-05-18 12:41:03 +0300126{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300127 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +0300128}
129
130void TIntermTraverser::incrementParentBlockPos()
131{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300132 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +0300133}
134
135void TIntermTraverser::popParentBlock()
136{
137 ASSERT(!mParentBlockStack.empty());
138 mParentBlockStack.pop_back();
139}
140
141void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
142{
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300143 TIntermSequence emptyInsertionsAfter;
144 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
145}
146
147void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
148 const TIntermSequence &insertionsAfter)
149{
Olli Etuaho56eea882015-05-18 12:41:03 +0300150 ASSERT(!mParentBlockStack.empty());
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000151 ParentBlock &parentBlock = mParentBlockStack.back();
152 if (mPath.back() == parentBlock.node)
153 {
154 ASSERT(mParentBlockStack.size() >= 2u);
155 // The current node is a block node, so the parent block is not the topmost one in the block
156 // stack, but the one below that.
157 parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u);
158 }
159 NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore,
160 insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300161 mInsertions.push_back(insert);
162}
163
Jamie Madill1048e432016-07-23 18:51:28 -0400164void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
165{
166 TIntermSequence insertions;
167 insertions.push_back(statement);
168 insertStatementsInParentBlock(insertions);
169}
170
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300171TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300172{
Olli Etuaho4dd06d52017-07-05 12:41:06 +0300173 ASSERT(mTemporaryId != nullptr);
Olli Etuaho180f43c2017-10-09 17:00:44 +0300174 // nextTemporaryId() needs to be called when the code wants to start using another temporary
175 // symbol.
176 return CreateTempSymbolNode(*mTemporaryId, type, qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300177}
178
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300179TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
180{
181 return createTempSymbol(type, EvqTemporary);
182}
183
Olli Etuaho13389b62016-10-16 11:48:18 +0100184TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
Olli Etuaho4f1af782015-05-25 11:55:07 +0300185{
Olli Etuaho180f43c2017-10-09 17:00:44 +0300186 ASSERT(mTemporaryId != nullptr);
Olli Etuaho13389b62016-10-16 11:48:18 +0100187 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
Olli Etuaho180f43c2017-10-09 17:00:44 +0300188 tempDeclaration->appendDeclarator(CreateTempSymbolNode(*mTemporaryId, type, EvqTemporary));
Olli Etuaho4f1af782015-05-25 11:55:07 +0300189 return tempDeclaration;
190}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300191
Olli Etuaho13389b62016-10-16 11:48:18 +0100192TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
193 TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300194{
Olli Etuaho180f43c2017-10-09 17:00:44 +0300195 ASSERT(mTemporaryId != nullptr);
196 return CreateTempInitDeclarationNode(*mTemporaryId, initializer, qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300197}
198
Olli Etuaho13389b62016-10-16 11:48:18 +0100199TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300200{
201 return createTempInitDeclaration(initializer, EvqTemporary);
202}
203
Olli Etuahod4f303e2015-05-20 17:09:06 +0300204TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
205{
206 ASSERT(rightNode != nullptr);
207 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300208 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300209 return assignment;
210}
211
Olli Etuaho4dd06d52017-07-05 12:41:06 +0300212void TIntermTraverser::nextTemporaryId()
Olli Etuahod4f303e2015-05-20 17:09:06 +0300213{
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300214 ASSERT(mSymbolTable);
215 if (!mTemporaryId)
216 {
217 mTemporaryId = new TSymbolUniqueId(mSymbolTable);
218 return;
219 }
220 *mTemporaryId = TSymbolUniqueId(mSymbolTable);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300221}
222
Olli Etuahofe486322017-03-21 09:30:54 +0000223void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id,
224 TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300225{
Olli Etuahofe486322017-03-21 09:30:54 +0000226 mFunctionMap[id.get()] = paramSequence;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300227}
228
Olli Etuaho3fc93372015-08-11 14:50:59 +0300229bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300230{
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800231 ASSERT(callNode->getOp() == EOpCallFunctionInAST);
Olli Etuahofe486322017-03-21 09:30:54 +0000232 return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) !=
Olli Etuahobd674552016-10-06 13:28:42 +0100233 mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300234}
235
Olli Etuaho3fc93372015-08-11 14:50:59 +0300236TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300237{
238 ASSERT(isInFunctionMap(callNode));
Olli Etuahofe486322017-03-21 09:30:54 +0000239 return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300240}
241
Olli Etuaho3fc93372015-08-11 14:50:59 +0300242void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300243{
244 mInFunctionCallOutParameter = inOutParameter;
245}
246
Olli Etuaho3fc93372015-08-11 14:50:59 +0300247bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300248{
249 return mInFunctionCallOutParameter;
250}
251
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252//
253// Traverse the intermediate representation tree, and
254// call a node type specific function for each node.
255// Done recursively through the member function Traverse().
256// Node types can be skipped if their function to call is 0,
257// but their subtree will still be traversed.
258// Nodes with children can have their whole subtree skipped
259// if preVisit is turned on and the type specific function
260// returns false.
261//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
263//
264// Traversal functions for terminals are straighforward....
265//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300266void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000267{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000268 ScopedNodeInTraversalPath addToPath(this, node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300269 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270}
271
Olli Etuaho27446bd2015-08-10 14:59:53 +0300272void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000274 ScopedNodeInTraversalPath addToPath(this, node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300275 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276}
277
Olli Etuahob6fa0432016-09-28 16:28:05 +0100278void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
279{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000280 ScopedNodeInTraversalPath addToPath(this, node);
281
Olli Etuahob6fa0432016-09-28 16:28:05 +0100282 bool visit = true;
283
284 if (preVisit)
285 visit = visitSwizzle(PreVisit, node);
286
287 if (visit)
288 {
Olli Etuahob6fa0432016-09-28 16:28:05 +0100289 node->getOperand()->traverse(this);
Olli Etuahob6fa0432016-09-28 16:28:05 +0100290 }
291
292 if (visit && postVisit)
293 visitSwizzle(PostVisit, node);
294}
295
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296//
297// Traverse a binary node.
298//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300299void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000301 ScopedNodeInTraversalPath addToPath(this, node);
302
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700303 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700305 //
306 // visit the node before children if pre-visiting.
307 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300308 if (preVisit)
309 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700311 //
312 // Visit the children, in the right order.
313 //
314 if (visit)
315 {
Olli Etuaho3fc93372015-08-11 14:50:59 +0300316 if (node->getLeft())
317 node->getLeft()->traverse(this);
318
319 if (inVisit)
320 visit = visitBinary(InVisit, node);
321
322 if (visit && node->getRight())
323 node->getRight()->traverse(this);
Olli Etuaho3fc93372015-08-11 14:50:59 +0300324 }
325
326 //
327 // Visit the node after the children, if requested and the traversal
328 // hasn't been cancelled yet.
329 //
330 if (visit && postVisit)
331 visitBinary(PostVisit, node);
332}
333
334void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
335{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000336 ScopedNodeInTraversalPath addToPath(this, node);
337
Olli Etuaho3fc93372015-08-11 14:50:59 +0300338 bool visit = true;
339
340 //
341 // visit the node before children if pre-visiting.
342 //
343 if (preVisit)
344 visit = visitBinary(PreVisit, node);
345
346 //
347 // Visit the children, in the right order.
348 //
349 if (visit)
350 {
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300351 // Some binary operations like indexing can be inside an expression which must be an
352 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300353 bool parentOperatorRequiresLValue = operatorRequiresLValue();
354 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
355 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300356 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300357 ASSERT(!isLValueRequiredHere());
358 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300359 }
360
Olli Etuaho27446bd2015-08-10 14:59:53 +0300361 if (node->getLeft())
362 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
Olli Etuaho27446bd2015-08-10 14:59:53 +0300364 if (inVisit)
365 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366
Olli Etuaho27446bd2015-08-10 14:59:53 +0300367 if (node->isAssignment())
368 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300369
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300370 // Index is not required to be an l-value even when the surrounding expression is required
371 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300372 TOperator op = node->getOp();
373 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
374 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300375 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300376 setOperatorRequiresLValue(false);
377 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300378 }
379
Olli Etuaho27446bd2015-08-10 14:59:53 +0300380 if (visit && node->getRight())
381 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700382
Olli Etuaho27446bd2015-08-10 14:59:53 +0300383 setOperatorRequiresLValue(parentOperatorRequiresLValue);
384 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700385 }
386
387 //
388 // Visit the node after the children, if requested and the traversal
389 // hasn't been cancelled yet.
390 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300391 if (visit && postVisit)
392 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393}
394
395//
396// Traverse a unary node. Same comments in binary node apply here.
397//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300398void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000400 ScopedNodeInTraversalPath addToPath(this, node);
401
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700402 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403
Olli Etuaho27446bd2015-08-10 14:59:53 +0300404 if (preVisit)
405 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000406
Olli Etuahoa26ad582015-08-04 13:51:47 +0300407 if (visit)
408 {
Olli Etuaho3fc93372015-08-11 14:50:59 +0300409 node->getOperand()->traverse(this);
Olli Etuaho3fc93372015-08-11 14:50:59 +0300410 }
411
412 if (visit && postVisit)
413 visitUnary(PostVisit, node);
414}
415
416void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
417{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000418 ScopedNodeInTraversalPath addToPath(this, node);
419
Olli Etuaho3fc93372015-08-11 14:50:59 +0300420 bool visit = true;
421
422 if (preVisit)
423 visit = visitUnary(PreVisit, node);
424
425 if (visit)
426 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300427 ASSERT(!operatorRequiresLValue());
428 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300429 {
430 case EOpPostIncrement:
431 case EOpPostDecrement:
432 case EOpPreIncrement:
433 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300434 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300435 break;
436 default:
437 break;
438 }
439
Olli Etuaho27446bd2015-08-10 14:59:53 +0300440 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300441
Olli Etuaho27446bd2015-08-10 14:59:53 +0300442 setOperatorRequiresLValue(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700443 }
444
Olli Etuaho27446bd2015-08-10 14:59:53 +0300445 if (visit && postVisit)
446 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447}
448
Olli Etuaho336b1472016-10-05 16:37:55 +0100449// Traverse a function definition node.
450void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
451{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000452 ScopedNodeInTraversalPath addToPath(this, node);
453
Olli Etuaho336b1472016-10-05 16:37:55 +0100454 bool visit = true;
455
456 if (preVisit)
457 visit = visitFunctionDefinition(PreVisit, node);
458
459 if (visit)
460 {
Olli Etuaho336b1472016-10-05 16:37:55 +0100461 mInGlobalScope = false;
462
Olli Etuaho8ad9e752017-01-16 19:55:20 +0000463 node->getFunctionPrototype()->traverse(this);
Olli Etuaho336b1472016-10-05 16:37:55 +0100464 if (inVisit)
465 visit = visitFunctionDefinition(InVisit, node);
466 node->getBody()->traverse(this);
467
468 mInGlobalScope = true;
Olli Etuaho336b1472016-10-05 16:37:55 +0100469 }
470
471 if (visit && postVisit)
472 visitFunctionDefinition(PostVisit, node);
473}
474
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100475// Traverse a block node.
476void TIntermTraverser::traverseBlock(TIntermBlock *node)
477{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000478 ScopedNodeInTraversalPath addToPath(this, node);
479 pushParentBlock(node);
480
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100481 bool visit = true;
482
483 TIntermSequence *sequence = node->getSequence();
484
485 if (preVisit)
486 visit = visitBlock(PreVisit, node);
487
488 if (visit)
489 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100490 for (auto *child : *sequence)
491 {
492 child->traverse(this);
493 if (visit && inVisit)
494 {
495 if (child != sequence->back())
496 visit = visitBlock(InVisit, node);
497 }
498
499 incrementParentBlockPos();
500 }
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100501 }
502
503 if (visit && postVisit)
504 visitBlock(PostVisit, node);
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000505
506 popParentBlock();
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100507}
508
Olli Etuahobf4e1b72016-12-09 11:30:15 +0000509void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node)
510{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000511 ScopedNodeInTraversalPath addToPath(this, node);
512
Olli Etuahobf4e1b72016-12-09 11:30:15 +0000513 bool visit = true;
514
515 if (preVisit)
516 {
517 visit = visitInvariantDeclaration(PreVisit, node);
518 }
519
520 if (visit)
521 {
522 node->getSymbol()->traverse(this);
523 if (postVisit)
524 {
525 visitInvariantDeclaration(PostVisit, node);
526 }
527 }
528}
529
Olli Etuaho13389b62016-10-16 11:48:18 +0100530// Traverse a declaration node.
531void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
532{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000533 ScopedNodeInTraversalPath addToPath(this, node);
534
Olli Etuaho13389b62016-10-16 11:48:18 +0100535 bool visit = true;
536
537 TIntermSequence *sequence = node->getSequence();
538
539 if (preVisit)
540 visit = visitDeclaration(PreVisit, node);
541
542 if (visit)
543 {
Olli Etuaho13389b62016-10-16 11:48:18 +0100544 for (auto *child : *sequence)
545 {
546 child->traverse(this);
547 if (visit && inVisit)
548 {
549 if (child != sequence->back())
550 visit = visitDeclaration(InVisit, node);
551 }
552 }
Olli Etuaho13389b62016-10-16 11:48:18 +0100553 }
554
555 if (visit && postVisit)
556 visitDeclaration(PostVisit, node);
557}
558
Olli Etuaho16c745a2017-01-16 17:02:27 +0000559void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
560{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000561 ScopedNodeInTraversalPath addToPath(this, node);
562
Olli Etuaho16c745a2017-01-16 17:02:27 +0000563 bool visit = true;
564
565 TIntermSequence *sequence = node->getSequence();
566
567 if (preVisit)
568 visit = visitFunctionPrototype(PreVisit, node);
569
570 if (visit)
571 {
Olli Etuaho16c745a2017-01-16 17:02:27 +0000572 for (auto *child : *sequence)
573 {
574 child->traverse(this);
575 if (visit && inVisit)
576 {
577 if (child != sequence->back())
578 visit = visitFunctionPrototype(InVisit, node);
579 }
580 }
Olli Etuaho16c745a2017-01-16 17:02:27 +0000581 }
582
583 if (visit && postVisit)
584 visitFunctionPrototype(PostVisit, node);
585}
586
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300588void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000589{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000590 ScopedNodeInTraversalPath addToPath(this, node);
591
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700592 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593
Olli Etuaho27446bd2015-08-10 14:59:53 +0300594 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300595
596 if (preVisit)
597 visit = visitAggregate(PreVisit, node);
598
599 if (visit)
600 {
Olli Etuaho3fc93372015-08-11 14:50:59 +0300601 for (auto *child : *sequence)
602 {
603 child->traverse(this);
604 if (visit && inVisit)
605 {
606 if (child != sequence->back())
607 visit = visitAggregate(InVisit, node);
608 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300609 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300610 }
611
612 if (visit && postVisit)
613 visitAggregate(PostVisit, node);
614}
615
Olli Etuahocccf2b02017-07-05 14:50:54 +0300616bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a,
617 const NodeInsertMultipleEntry &b)
618{
619 if (a.parent != b.parent)
620 {
621 return a.parent > b.parent;
622 }
623 return a.position > b.position;
624}
625
626void TIntermTraverser::updateTree()
627{
628 // Sort the insertions so that insertion position is decreasing. This way multiple insertions to
629 // the same parent node are handled correctly.
630 std::sort(mInsertions.begin(), mInsertions.end(), CompareInsertion);
631 for (size_t ii = 0; ii < mInsertions.size(); ++ii)
632 {
633 // We can't know here what the intended ordering of two insertions to the same position is,
634 // so it is not supported.
635 ASSERT(ii == 0 || mInsertions[ii].position != mInsertions[ii - 1].position ||
636 mInsertions[ii].parent != mInsertions[ii - 1].parent);
637 const NodeInsertMultipleEntry &insertion = mInsertions[ii];
638 ASSERT(insertion.parent);
639 if (!insertion.insertionsAfter.empty())
640 {
641 bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
642 insertion.insertionsAfter);
643 ASSERT(inserted);
644 }
645 if (!insertion.insertionsBefore.empty())
646 {
647 bool inserted =
648 insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
649 ASSERT(inserted);
650 }
651 }
652 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
653 {
654 const NodeUpdateEntry &replacement = mReplacements[ii];
655 ASSERT(replacement.parent);
656 bool replaced =
657 replacement.parent->replaceChildNode(replacement.original, replacement.replacement);
658 ASSERT(replaced);
659
660 if (!replacement.originalBecomesChildOfReplacement)
661 {
662 // In AST traversing, a parent is visited before its children.
663 // After we replace a node, if its immediate child is to
664 // be replaced, we need to make sure we don't update the replaced
665 // node; instead, we update the replacement node.
666 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
667 {
668 NodeUpdateEntry &replacement2 = mReplacements[jj];
669 if (replacement2.parent == replacement.original)
670 replacement2.parent = replacement.replacement;
671 }
672 }
673 }
674 for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
675 {
676 const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
677 ASSERT(replacement.parent);
678 bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original,
679 replacement.replacements);
680 ASSERT(replaced);
681 }
682
683 clearReplacementQueue();
684}
685
686void TIntermTraverser::clearReplacementQueue()
687{
688 mReplacements.clear();
689 mMultiReplacements.clear();
690 mInsertions.clear();
691}
692
Olli Etuahoea39a222017-07-06 12:47:59 +0300693void TIntermTraverser::queueReplacement(TIntermNode *replacement, OriginalNode originalStatus)
Olli Etuahocccf2b02017-07-05 14:50:54 +0300694{
Olli Etuahoea39a222017-07-06 12:47:59 +0300695 queueReplacementWithParent(getParentNode(), mPath.back(), replacement, originalStatus);
Olli Etuahocccf2b02017-07-05 14:50:54 +0300696}
697
698void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
699 TIntermNode *original,
700 TIntermNode *replacement,
701 OriginalNode originalStatus)
702{
703 bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
704 mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
705}
706
Olli Etuahocccf2b02017-07-05 14:50:54 +0300707TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisit,
708 bool inVisit,
709 bool postVisit,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300710 TSymbolTable *symbolTable,
Olli Etuahocccf2b02017-07-05 14:50:54 +0300711 int shaderVersion)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300712 : TIntermTraverser(preVisit, inVisit, postVisit, symbolTable),
Olli Etuahocccf2b02017-07-05 14:50:54 +0300713 mOperatorRequiresLValue(false),
714 mInFunctionCallOutParameter(false),
Olli Etuahocccf2b02017-07-05 14:50:54 +0300715 mShaderVersion(shaderVersion)
716{
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300717 ASSERT(symbolTable);
Olli Etuahocccf2b02017-07-05 14:50:54 +0300718}
719
Olli Etuaho16c745a2017-01-16 17:02:27 +0000720void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
721{
722 TIntermSequence *sequence = node->getSequence();
Olli Etuahofe486322017-03-21 09:30:54 +0000723 addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence);
Olli Etuaho16c745a2017-01-16 17:02:27 +0000724
725 TIntermTraverser::traverseFunctionPrototype(node);
726}
727
Olli Etuaho3fc93372015-08-11 14:50:59 +0300728void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
729{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000730 ScopedNodeInTraversalPath addToPath(this, node);
731
Olli Etuaho3fc93372015-08-11 14:50:59 +0300732 bool visit = true;
733
734 TIntermSequence *sequence = node->getSequence();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300735
Olli Etuaho27446bd2015-08-10 14:59:53 +0300736 if (preVisit)
737 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700739 if (visit)
740 {
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800741 if (node->getOp() == EOpCallFunctionInAST)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700742 {
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800743 if (isInFunctionMap(node))
Olli Etuaho64f0be92015-06-03 17:38:34 +0300744 {
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800745 TIntermSequence *params = getFunctionParameters(node);
746 TIntermSequence::iterator paramIter = params->begin();
747 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300748 {
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800749 ASSERT(paramIter != params->end());
750 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
751 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300752
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800753 child->traverse(this);
754 if (visit && inVisit)
755 {
756 if (child != sequence->back())
757 visit = visitAggregate(InVisit, node);
758 }
759
760 ++paramIter;
761 }
762 }
763 else
764 {
765 // The node might not be in the function map in case we're in the middle of
766 // transforming the AST, and have inserted function call nodes without inserting the
767 // function definitions yet.
768 setInFunctionCallOutParameter(false);
769 for (auto *child : *sequence)
770 {
771 child->traverse(this);
772 if (visit && inVisit)
773 {
774 if (child != sequence->back())
775 visit = visitAggregate(InVisit, node);
776 }
777 }
Olli Etuahoa26ad582015-08-04 13:51:47 +0300778 }
779
Olli Etuaho27446bd2015-08-10 14:59:53 +0300780 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300781 }
782 else
783 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300784 // Find the built-in function corresponding to this op so that we can determine the
785 // in/out qualifiers of its parameters.
786 TFunction *builtInFunc = nullptr;
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800787 if (!node->isFunctionCall() && !node->isConstructor())
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300788 {
Olli Etuahof2209f72017-04-01 12:45:55 +0300789 builtInFunc = static_cast<TFunction *>(
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300790 mSymbolTable->findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion));
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300791 }
792
793 size_t paramIndex = 0;
794
Olli Etuaho27446bd2015-08-10 14:59:53 +0300795 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300796 {
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800797 // This assumes that raw functions called with
798 // EOpCallInternalRawFunction don't have out parameters.
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300799 TQualifier qualifier = EvqIn;
800 if (builtInFunc != nullptr)
801 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
802 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300803 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300804
Olli Etuaho27446bd2015-08-10 14:59:53 +0300805 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300806 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300807 if (child != sequence->back())
808 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300809 }
810
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300811 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300812 }
813
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300814 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300815 }
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700816 }
817
Olli Etuaho27446bd2015-08-10 14:59:53 +0300818 if (visit && postVisit)
819 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820}
821
822//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300823// Traverse a ternary node. Same comments in binary node apply here.
824//
825void TIntermTraverser::traverseTernary(TIntermTernary *node)
826{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000827 ScopedNodeInTraversalPath addToPath(this, node);
828
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300829 bool visit = true;
830
831 if (preVisit)
832 visit = visitTernary(PreVisit, node);
833
834 if (visit)
835 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300836 node->getCondition()->traverse(this);
837 if (node->getTrueExpression())
838 node->getTrueExpression()->traverse(this);
839 if (node->getFalseExpression())
840 node->getFalseExpression()->traverse(this);
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300841 }
842
843 if (visit && postVisit)
844 visitTernary(PostVisit, node);
845}
846
Olli Etuaho57961272016-09-14 13:57:46 +0300847// Traverse an if-else node. Same comments in binary node apply here.
848void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000849{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000850 ScopedNodeInTraversalPath addToPath(this, node);
851
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700852 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853
Olli Etuaho27446bd2015-08-10 14:59:53 +0300854 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300855 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000856
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700857 if (visit)
858 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300859 node->getCondition()->traverse(this);
860 if (node->getTrueBlock())
861 node->getTrueBlock()->traverse(this);
862 if (node->getFalseBlock())
863 node->getFalseBlock()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700864 }
865
Olli Etuaho27446bd2015-08-10 14:59:53 +0300866 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300867 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000868}
869
870//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200871// Traverse a switch node. Same comments in binary node apply here.
872//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300873void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200874{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000875 ScopedNodeInTraversalPath addToPath(this, node);
876
Olli Etuahoa3a36662015-02-17 13:46:51 +0200877 bool visit = true;
878
Olli Etuaho27446bd2015-08-10 14:59:53 +0300879 if (preVisit)
880 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200881
882 if (visit)
883 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300884 node->getInit()->traverse(this);
885 if (inVisit)
886 visit = visitSwitch(InVisit, node);
887 if (visit && node->getStatementList())
888 node->getStatementList()->traverse(this);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200889 }
890
Olli Etuaho27446bd2015-08-10 14:59:53 +0300891 if (visit && postVisit)
892 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200893}
894
895//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300896// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200897//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300898void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200899{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000900 ScopedNodeInTraversalPath addToPath(this, node);
901
Olli Etuahoa3a36662015-02-17 13:46:51 +0200902 bool visit = true;
903
Olli Etuaho27446bd2015-08-10 14:59:53 +0300904 if (preVisit)
905 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200906
Olli Etuaho27446bd2015-08-10 14:59:53 +0300907 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100908 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300909 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100910 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200911
Olli Etuaho27446bd2015-08-10 14:59:53 +0300912 if (visit && postVisit)
913 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200914}
915
916//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000917// Traverse a loop node. Same comments in binary node apply here.
918//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300919void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000921 ScopedNodeInTraversalPath addToPath(this, node);
922
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700923 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000924
Olli Etuaho27446bd2015-08-10 14:59:53 +0300925 if (preVisit)
926 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700928 if (visit)
929 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300930 if (node->getInit())
931 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000932
Olli Etuaho27446bd2015-08-10 14:59:53 +0300933 if (node->getCondition())
934 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000935
Olli Etuaho27446bd2015-08-10 14:59:53 +0300936 if (node->getBody())
937 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700938
Olli Etuaho27446bd2015-08-10 14:59:53 +0300939 if (node->getExpression())
940 node->getExpression()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700941 }
942
Olli Etuaho27446bd2015-08-10 14:59:53 +0300943 if (visit && postVisit)
944 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000945}
946
947//
948// Traverse a branch node. Same comments in binary node apply here.
949//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300950void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000952 ScopedNodeInTraversalPath addToPath(this, node);
953
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700954 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000955
Olli Etuaho27446bd2015-08-10 14:59:53 +0300956 if (preVisit)
957 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000958
Olli Etuaho27446bd2015-08-10 14:59:53 +0300959 if (visit && node->getExpression())
960 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300961 node->getExpression()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700962 }
963
Olli Etuaho27446bd2015-08-10 14:59:53 +0300964 if (visit && postVisit)
965 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966}
967
Olli Etuaho27446bd2015-08-10 14:59:53 +0300968void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400969{
Olli Etuaho1d9dcc22017-01-19 11:25:32 +0000970 ScopedNodeInTraversalPath addToPath(this, node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300971 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400972}
Jamie Madill45bcc782016-11-07 13:58:48 -0500973
974} // namespace sh