blob: 7f213fc3610bc7c61c4621cfa3e8e16bb4a78a55 [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"
Olli Etuahod4f303e2015-05-20 17:09:06 +03008#include "compiler/translator/InfoSink.h"
Olli Etuaho217fe6e2015-08-05 13:25:08 +03009#include "compiler/translator/SymbolTable.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000010
Olli Etuaho27446bd2015-08-10 14:59:53 +030011void TIntermSymbol::traverse(TIntermTraverser *it)
12{
13 it->traverseSymbol(this);
14}
15
16void TIntermRaw::traverse(TIntermTraverser *it)
17{
18 it->traverseRaw(this);
19}
20
21void TIntermConstantUnion::traverse(TIntermTraverser *it)
22{
23 it->traverseConstantUnion(this);
24}
25
26void TIntermBinary::traverse(TIntermTraverser *it)
27{
28 it->traverseBinary(this);
29}
30
31void TIntermUnary::traverse(TIntermTraverser *it)
32{
33 it->traverseUnary(this);
34}
35
36void TIntermSelection::traverse(TIntermTraverser *it)
37{
38 it->traverseSelection(this);
39}
40
41void TIntermSwitch::traverse(TIntermTraverser *it)
42{
43 it->traverseSwitch(this);
44}
45
46void TIntermCase::traverse(TIntermTraverser *it)
47{
48 it->traverseCase(this);
49}
50
51void TIntermAggregate::traverse(TIntermTraverser *it)
52{
53 it->traverseAggregate(this);
54}
55
56void TIntermLoop::traverse(TIntermTraverser *it)
57{
58 it->traverseLoop(this);
59}
60
61void TIntermBranch::traverse(TIntermTraverser *it)
62{
63 it->traverseBranch(this);
64}
65
Olli Etuaho56eea882015-05-18 12:41:03 +030066void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
67{
Olli Etuaho64f0be92015-06-03 17:38:34 +030068 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +030069}
70
71void TIntermTraverser::incrementParentBlockPos()
72{
Olli Etuaho64f0be92015-06-03 17:38:34 +030073 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +030074}
75
76void TIntermTraverser::popParentBlock()
77{
78 ASSERT(!mParentBlockStack.empty());
79 mParentBlockStack.pop_back();
80}
81
82void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
83{
84 ASSERT(!mParentBlockStack.empty());
85 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos, insertions);
86 mInsertions.push_back(insert);
87}
88
Olli Etuahoa4aa4e32015-06-04 15:54:30 +030089TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +030090{
91 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
92 TInfoSinkBase symbolNameOut;
93 ASSERT(mTemporaryIndex != nullptr);
94 symbolNameOut << "s" << (*mTemporaryIndex);
95 TString symbolName = symbolNameOut.c_str();
96
97 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
98 node->setInternal(true);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +030099 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300100 return node;
101}
102
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300103TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
104{
105 return createTempSymbol(type, EvqTemporary);
106}
107
Olli Etuaho4f1af782015-05-25 11:55:07 +0300108TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
109{
110 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
111 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
112 return tempDeclaration;
113}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300114
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300115TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300116{
117 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300118 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300119 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
120 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
121 tempInit->setLeft(tempSymbol);
122 tempInit->setRight(initializer);
123 tempInit->setType(tempSymbol->getType());
124 tempDeclaration->getSequence()->push_back(tempInit);
125 return tempDeclaration;
126}
127
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300128TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
129{
130 return createTempInitDeclaration(initializer, EvqTemporary);
131}
132
Olli Etuahod4f303e2015-05-20 17:09:06 +0300133TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
134{
135 ASSERT(rightNode != nullptr);
136 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
137 TIntermBinary *assignment = new TIntermBinary(EOpAssign);
138 assignment->setLeft(tempSymbol);
139 assignment->setRight(rightNode);
140 assignment->setType(tempSymbol->getType());
141 return assignment;
142}
143
144void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
145{
146 mTemporaryIndex = temporaryIndex;
147}
148
149void TIntermTraverser::nextTemporaryIndex()
150{
151 ASSERT(mTemporaryIndex != nullptr);
152 ++(*mTemporaryIndex);
153}
154
Olli Etuaho3fc93372015-08-11 14:50:59 +0300155void TLValueTrackingTraverser::addToFunctionMap(const TString &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300156{
157 mFunctionMap[name] = paramSequence;
158}
159
Olli Etuaho3fc93372015-08-11 14:50:59 +0300160bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300161{
162 ASSERT(callNode->getOp() == EOpFunctionCall || callNode->getOp() == EOpInternalFunctionCall);
163 return (mFunctionMap.find(callNode->getName()) != mFunctionMap.end());
164}
165
Olli Etuaho3fc93372015-08-11 14:50:59 +0300166TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300167{
168 ASSERT(isInFunctionMap(callNode));
169 return mFunctionMap[callNode->getName()];
170}
171
Olli Etuaho3fc93372015-08-11 14:50:59 +0300172void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300173{
174 mInFunctionCallOutParameter = inOutParameter;
175}
176
Olli Etuaho3fc93372015-08-11 14:50:59 +0300177bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300178{
179 return mInFunctionCallOutParameter;
180}
181
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182//
183// Traverse the intermediate representation tree, and
184// call a node type specific function for each node.
185// Done recursively through the member function Traverse().
186// Node types can be skipped if their function to call is 0,
187// but their subtree will still be traversed.
188// Nodes with children can have their whole subtree skipped
189// if preVisit is turned on and the type specific function
190// returns false.
191//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192
193//
194// Traversal functions for terminals are straighforward....
195//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300196void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300198 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199}
200
Olli Etuaho27446bd2015-08-10 14:59:53 +0300201void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300203 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204}
205
206//
207// Traverse a binary node.
208//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300209void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700211 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700213 //
214 // visit the node before children if pre-visiting.
215 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300216 if (preVisit)
217 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700219 //
220 // Visit the children, in the right order.
221 //
222 if (visit)
223 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300224 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225
Olli Etuaho3fc93372015-08-11 14:50:59 +0300226 if (node->getLeft())
227 node->getLeft()->traverse(this);
228
229 if (inVisit)
230 visit = visitBinary(InVisit, node);
231
232 if (visit && node->getRight())
233 node->getRight()->traverse(this);
234
235 decrementDepth();
236 }
237
238 //
239 // Visit the node after the children, if requested and the traversal
240 // hasn't been cancelled yet.
241 //
242 if (visit && postVisit)
243 visitBinary(PostVisit, node);
244}
245
246void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
247{
248 bool visit = true;
249
250 //
251 // visit the node before children if pre-visiting.
252 //
253 if (preVisit)
254 visit = visitBinary(PreVisit, node);
255
256 //
257 // Visit the children, in the right order.
258 //
259 if (visit)
260 {
261 incrementDepth(node);
262
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300263 // Some binary operations like indexing can be inside an expression which must be an
264 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300265 bool parentOperatorRequiresLValue = operatorRequiresLValue();
266 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
267 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300268 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300269 ASSERT(!isLValueRequiredHere());
270 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300271 }
272
Olli Etuaho27446bd2015-08-10 14:59:53 +0300273 if (node->getLeft())
274 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275
Olli Etuaho27446bd2015-08-10 14:59:53 +0300276 if (inVisit)
277 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278
Olli Etuaho27446bd2015-08-10 14:59:53 +0300279 if (node->isAssignment())
280 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300281
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300282 // Index is not required to be an l-value even when the surrounding expression is required
283 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300284 TOperator op = node->getOp();
285 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
286 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300287 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300288 setOperatorRequiresLValue(false);
289 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300290 }
291
Olli Etuaho27446bd2015-08-10 14:59:53 +0300292 if (visit && node->getRight())
293 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700294
Olli Etuaho27446bd2015-08-10 14:59:53 +0300295 setOperatorRequiresLValue(parentOperatorRequiresLValue);
296 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300297
Olli Etuaho27446bd2015-08-10 14:59:53 +0300298 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700299 }
300
301 //
302 // Visit the node after the children, if requested and the traversal
303 // hasn't been cancelled yet.
304 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300305 if (visit && postVisit)
306 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307}
308
309//
310// Traverse a unary node. Same comments in binary node apply here.
311//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300312void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700314 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315
Olli Etuaho27446bd2015-08-10 14:59:53 +0300316 if (preVisit)
317 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318
Olli Etuahoa26ad582015-08-04 13:51:47 +0300319 if (visit)
320 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300321 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300322
Olli Etuaho3fc93372015-08-11 14:50:59 +0300323 node->getOperand()->traverse(this);
324
325 decrementDepth();
326 }
327
328 if (visit && postVisit)
329 visitUnary(PostVisit, node);
330}
331
332void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
333{
334 bool visit = true;
335
336 if (preVisit)
337 visit = visitUnary(PreVisit, node);
338
339 if (visit)
340 {
341 incrementDepth(node);
342
Olli Etuaho27446bd2015-08-10 14:59:53 +0300343 ASSERT(!operatorRequiresLValue());
344 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300345 {
346 case EOpPostIncrement:
347 case EOpPostDecrement:
348 case EOpPreIncrement:
349 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300350 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300351 break;
352 default:
353 break;
354 }
355
Olli Etuaho27446bd2015-08-10 14:59:53 +0300356 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300357
Olli Etuaho27446bd2015-08-10 14:59:53 +0300358 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300359
Olli Etuaho27446bd2015-08-10 14:59:53 +0300360 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700361 }
362
Olli Etuaho27446bd2015-08-10 14:59:53 +0300363 if (visit && postVisit)
364 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365}
366
367//
368// Traverse an aggregate node. Same comments in binary node apply here.
369//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300370void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000371{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700372 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373
Olli Etuaho27446bd2015-08-10 14:59:53 +0300374 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300375
376 if (preVisit)
377 visit = visitAggregate(PreVisit, node);
378
379 if (visit)
380 {
381 incrementDepth(node);
382
383 if (node->getOp() == EOpSequence)
384 pushParentBlock(node);
385
386 for (auto *child : *sequence)
387 {
388 child->traverse(this);
389 if (visit && inVisit)
390 {
391 if (child != sequence->back())
392 visit = visitAggregate(InVisit, node);
393 }
394
395 if (node->getOp() == EOpSequence)
396 incrementParentBlockPos();
397 }
398
399 if (node->getOp() == EOpSequence)
400 popParentBlock();
401
402 decrementDepth();
403 }
404
405 if (visit && postVisit)
406 visitAggregate(PostVisit, node);
407}
408
409void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
410{
411 bool visit = true;
412
413 TIntermSequence *sequence = node->getSequence();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300414 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300415 {
416 case EOpFunction:
417 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300418 TIntermAggregate *params = sequence->front()->getAsAggregate();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300419 ASSERT(params != nullptr);
420 ASSERT(params->getOp() == EOpParameters);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300421 addToFunctionMap(node->getName(), params->getSequence());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300422 break;
423 }
424 case EOpPrototype:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300425 addToFunctionMap(node->getName(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300426 break;
427 default:
428 break;
429 }
430
Olli Etuaho27446bd2015-08-10 14:59:53 +0300431 if (preVisit)
432 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700434 if (visit)
435 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300436 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300437 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700438 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300439 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300440 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300441 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300442 // The function is not user-defined - it is likely built-in texture function.
443 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300444 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700445 }
446 }
447
Olli Etuaho27446bd2015-08-10 14:59:53 +0300448 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300449
Olli Etuahoa26ad582015-08-04 13:51:47 +0300450 if (inFunctionMap)
451 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300452 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300453 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300454 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300455 {
456 ASSERT(paramIter != params->end());
457 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300458 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300459
Olli Etuaho27446bd2015-08-10 14:59:53 +0300460 child->traverse(this);
461 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300462 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300463 if (child != sequence->back())
464 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300465 }
466
467 ++paramIter;
468 }
469
Olli Etuaho27446bd2015-08-10 14:59:53 +0300470 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300471 }
472 else
473 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300474 if (node->getOp() == EOpSequence)
475 pushParentBlock(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300476
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300477 // Find the built-in function corresponding to this op so that we can determine the
478 // in/out qualifiers of its parameters.
479 TFunction *builtInFunc = nullptr;
480 TString opString = GetOperatorString(node->getOp());
481 if (!node->isConstructor() && !opString.empty())
482 {
483 // The return type doesn't affect the mangled name of the function, which is used
484 // to look it up from the symbol table.
485 TType dummyReturnType;
486 TFunction call(&opString, &dummyReturnType, node->getOp());
487 for (auto *child : *sequence)
488 {
489 TType *paramType = child->getAsTyped()->getTypePointer();
490 TConstParameter p(paramType);
491 call.addParameter(p);
492 }
493
494 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
495 if (sym != nullptr && sym->isFunction())
496 {
497 builtInFunc = static_cast<TFunction *>(sym);
498 ASSERT(builtInFunc->getParamCount() == sequence->size());
499 }
500 }
501
502 size_t paramIndex = 0;
503
Olli Etuaho27446bd2015-08-10 14:59:53 +0300504 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300505 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300506 TQualifier qualifier = EvqIn;
507 if (builtInFunc != nullptr)
508 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
509 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300510 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300511
Olli Etuaho27446bd2015-08-10 14:59:53 +0300512 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300513 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300514 if (child != sequence->back())
515 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300516 }
517
Olli Etuaho27446bd2015-08-10 14:59:53 +0300518 if (node->getOp() == EOpSequence)
519 incrementParentBlockPos();
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300520
521 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300522 }
523
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300524 setInFunctionCallOutParameter(false);
525
Olli Etuaho27446bd2015-08-10 14:59:53 +0300526 if (node->getOp() == EOpSequence)
527 popParentBlock();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300528 }
529
Olli Etuaho27446bd2015-08-10 14:59:53 +0300530 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700531 }
532
Olli Etuaho27446bd2015-08-10 14:59:53 +0300533 if (visit && postVisit)
534 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000535}
536
537//
538// Traverse a selection node. Same comments in binary node apply here.
539//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300540void TIntermTraverser::traverseSelection(TIntermSelection *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000541{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700542 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000543
Olli Etuaho27446bd2015-08-10 14:59:53 +0300544 if (preVisit)
545 visit = visitSelection(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000546
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700547 if (visit)
548 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300549 incrementDepth(node);
550 node->getCondition()->traverse(this);
551 if (node->getTrueBlock())
552 node->getTrueBlock()->traverse(this);
553 if (node->getFalseBlock())
554 node->getFalseBlock()->traverse(this);
555 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700556 }
557
Olli Etuaho27446bd2015-08-10 14:59:53 +0300558 if (visit && postVisit)
559 visitSelection(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000560}
561
562//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200563// Traverse a switch node. Same comments in binary node apply here.
564//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300565void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200566{
567 bool visit = true;
568
Olli Etuaho27446bd2015-08-10 14:59:53 +0300569 if (preVisit)
570 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200571
572 if (visit)
573 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300574 incrementDepth(node);
575 node->getInit()->traverse(this);
576 if (inVisit)
577 visit = visitSwitch(InVisit, node);
578 if (visit && node->getStatementList())
579 node->getStatementList()->traverse(this);
580 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200581 }
582
Olli Etuaho27446bd2015-08-10 14:59:53 +0300583 if (visit && postVisit)
584 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200585}
586
587//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300588// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200589//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300590void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200591{
592 bool visit = true;
593
Olli Etuaho27446bd2015-08-10 14:59:53 +0300594 if (preVisit)
595 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200596
Olli Etuaho27446bd2015-08-10 14:59:53 +0300597 if (visit && node->getCondition())
598 node->getCondition()->traverse(this);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200599
Olli Etuaho27446bd2015-08-10 14:59:53 +0300600 if (visit && postVisit)
601 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200602}
603
604//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000605// Traverse a loop node. Same comments in binary node apply here.
606//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300607void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000608{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700609 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000610
Olli Etuaho27446bd2015-08-10 14:59:53 +0300611 if (preVisit)
612 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000613
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700614 if (visit)
615 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300616 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000617
Olli Etuaho27446bd2015-08-10 14:59:53 +0300618 if (node->getInit())
619 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000620
Olli Etuaho27446bd2015-08-10 14:59:53 +0300621 if (node->getCondition())
622 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000623
Olli Etuaho27446bd2015-08-10 14:59:53 +0300624 if (node->getBody())
625 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700626
Olli Etuaho27446bd2015-08-10 14:59:53 +0300627 if (node->getExpression())
628 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629
Olli Etuaho27446bd2015-08-10 14:59:53 +0300630 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700631 }
632
Olli Etuaho27446bd2015-08-10 14:59:53 +0300633 if (visit && postVisit)
634 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635}
636
637//
638// Traverse a branch node. Same comments in binary node apply here.
639//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300640void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700642 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643
Olli Etuaho27446bd2015-08-10 14:59:53 +0300644 if (preVisit)
645 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646
Olli Etuaho27446bd2015-08-10 14:59:53 +0300647 if (visit && node->getExpression())
648 {
649 incrementDepth(node);
650 node->getExpression()->traverse(this);
651 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700652 }
653
Olli Etuaho27446bd2015-08-10 14:59:53 +0300654 if (visit && postVisit)
655 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656}
657
Olli Etuaho27446bd2015-08-10 14:59:53 +0300658void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400659{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300660 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400661}