blob: 2f66ba7cd4b25c8d4ff88d77c2c72e16b0ddc28e [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
Jamie Madill03d863c2016-07-27 18:15:53 -040066TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
67 : preVisit(preVisit),
68 inVisit(inVisit),
69 postVisit(postVisit),
70 mDepth(0),
71 mMaxDepth(0),
72 mInGlobalScope(true),
73 mTemporaryIndex(nullptr)
74{
75}
76
77TIntermTraverser::~TIntermTraverser()
78{
79}
80
Olli Etuaho56eea882015-05-18 12:41:03 +030081void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
82{
Olli Etuaho64f0be92015-06-03 17:38:34 +030083 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +030084}
85
86void TIntermTraverser::incrementParentBlockPos()
87{
Olli Etuaho64f0be92015-06-03 17:38:34 +030088 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +030089}
90
91void TIntermTraverser::popParentBlock()
92{
93 ASSERT(!mParentBlockStack.empty());
94 mParentBlockStack.pop_back();
95}
96
97void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
98{
Olli Etuaho5d91dda2015-06-18 15:47:46 +030099 TIntermSequence emptyInsertionsAfter;
100 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
101}
102
103void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
104 const TIntermSequence &insertionsAfter)
105{
Olli Etuaho56eea882015-05-18 12:41:03 +0300106 ASSERT(!mParentBlockStack.empty());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300107 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
108 insertionsBefore, insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300109 mInsertions.push_back(insert);
110}
111
Jamie Madill1048e432016-07-23 18:51:28 -0400112void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
113{
114 TIntermSequence insertions;
115 insertions.push_back(statement);
116 insertStatementsInParentBlock(insertions);
117}
118
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300119TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300120{
121 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
122 TInfoSinkBase symbolNameOut;
123 ASSERT(mTemporaryIndex != nullptr);
124 symbolNameOut << "s" << (*mTemporaryIndex);
125 TString symbolName = symbolNameOut.c_str();
126
127 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
128 node->setInternal(true);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300129 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300130 return node;
131}
132
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300133TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
134{
135 return createTempSymbol(type, EvqTemporary);
136}
137
Olli Etuaho4f1af782015-05-25 11:55:07 +0300138TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
139{
140 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
141 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
142 return tempDeclaration;
143}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300144
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300145TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300146{
147 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300148 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300149 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
150 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
151 tempInit->setLeft(tempSymbol);
152 tempInit->setRight(initializer);
153 tempInit->setType(tempSymbol->getType());
154 tempDeclaration->getSequence()->push_back(tempInit);
155 return tempDeclaration;
156}
157
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300158TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
159{
160 return createTempInitDeclaration(initializer, EvqTemporary);
161}
162
Olli Etuahod4f303e2015-05-20 17:09:06 +0300163TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
164{
165 ASSERT(rightNode != nullptr);
166 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
167 TIntermBinary *assignment = new TIntermBinary(EOpAssign);
168 assignment->setLeft(tempSymbol);
169 assignment->setRight(rightNode);
170 assignment->setType(tempSymbol->getType());
171 return assignment;
172}
173
174void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
175{
176 mTemporaryIndex = temporaryIndex;
177}
178
179void TIntermTraverser::nextTemporaryIndex()
180{
181 ASSERT(mTemporaryIndex != nullptr);
182 ++(*mTemporaryIndex);
183}
184
Olli Etuaho5f579b12015-08-14 17:44:43 +0300185void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300186{
187 mFunctionMap[name] = paramSequence;
188}
189
Olli Etuaho3fc93372015-08-11 14:50:59 +0300190bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300191{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300192 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuaho5f579b12015-08-14 17:44:43 +0300193 return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300194}
195
Olli Etuaho3fc93372015-08-11 14:50:59 +0300196TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300197{
198 ASSERT(isInFunctionMap(callNode));
Olli Etuaho5f579b12015-08-14 17:44:43 +0300199 return mFunctionMap[callNode->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300200}
201
Olli Etuaho3fc93372015-08-11 14:50:59 +0300202void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300203{
204 mInFunctionCallOutParameter = inOutParameter;
205}
206
Olli Etuaho3fc93372015-08-11 14:50:59 +0300207bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300208{
209 return mInFunctionCallOutParameter;
210}
211
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212//
213// Traverse the intermediate representation tree, and
214// call a node type specific function for each node.
215// Done recursively through the member function Traverse().
216// Node types can be skipped if their function to call is 0,
217// but their subtree will still be traversed.
218// Nodes with children can have their whole subtree skipped
219// if preVisit is turned on and the type specific function
220// returns false.
221//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222
223//
224// Traversal functions for terminals are straighforward....
225//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300226void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300228 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229}
230
Olli Etuaho27446bd2015-08-10 14:59:53 +0300231void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300233 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234}
235
236//
237// Traverse a binary node.
238//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300239void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700241 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700243 //
244 // visit the node before children if pre-visiting.
245 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300246 if (preVisit)
247 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700249 //
250 // Visit the children, in the right order.
251 //
252 if (visit)
253 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300254 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255
Olli Etuaho3fc93372015-08-11 14:50:59 +0300256 if (node->getLeft())
257 node->getLeft()->traverse(this);
258
259 if (inVisit)
260 visit = visitBinary(InVisit, node);
261
262 if (visit && node->getRight())
263 node->getRight()->traverse(this);
264
265 decrementDepth();
266 }
267
268 //
269 // Visit the node after the children, if requested and the traversal
270 // hasn't been cancelled yet.
271 //
272 if (visit && postVisit)
273 visitBinary(PostVisit, node);
274}
275
276void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
277{
278 bool visit = true;
279
280 //
281 // visit the node before children if pre-visiting.
282 //
283 if (preVisit)
284 visit = visitBinary(PreVisit, node);
285
286 //
287 // Visit the children, in the right order.
288 //
289 if (visit)
290 {
291 incrementDepth(node);
292
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300293 // Some binary operations like indexing can be inside an expression which must be an
294 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300295 bool parentOperatorRequiresLValue = operatorRequiresLValue();
296 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
297 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300298 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300299 ASSERT(!isLValueRequiredHere());
300 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300301 }
302
Olli Etuaho27446bd2015-08-10 14:59:53 +0300303 if (node->getLeft())
304 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305
Olli Etuaho27446bd2015-08-10 14:59:53 +0300306 if (inVisit)
307 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308
Olli Etuaho27446bd2015-08-10 14:59:53 +0300309 if (node->isAssignment())
310 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300311
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300312 // Index is not required to be an l-value even when the surrounding expression is required
313 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300314 TOperator op = node->getOp();
315 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
316 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300317 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300318 setOperatorRequiresLValue(false);
319 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300320 }
321
Olli Etuaho27446bd2015-08-10 14:59:53 +0300322 if (visit && node->getRight())
323 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700324
Olli Etuaho27446bd2015-08-10 14:59:53 +0300325 setOperatorRequiresLValue(parentOperatorRequiresLValue);
326 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300327
Olli Etuaho27446bd2015-08-10 14:59:53 +0300328 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700329 }
330
331 //
332 // Visit the node after the children, if requested and the traversal
333 // hasn't been cancelled yet.
334 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300335 if (visit && postVisit)
336 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337}
338
339//
340// Traverse a unary node. Same comments in binary node apply here.
341//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300342void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700344 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345
Olli Etuaho27446bd2015-08-10 14:59:53 +0300346 if (preVisit)
347 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348
Olli Etuahoa26ad582015-08-04 13:51:47 +0300349 if (visit)
350 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300351 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300352
Olli Etuaho3fc93372015-08-11 14:50:59 +0300353 node->getOperand()->traverse(this);
354
355 decrementDepth();
356 }
357
358 if (visit && postVisit)
359 visitUnary(PostVisit, node);
360}
361
362void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
363{
364 bool visit = true;
365
366 if (preVisit)
367 visit = visitUnary(PreVisit, node);
368
369 if (visit)
370 {
371 incrementDepth(node);
372
Olli Etuaho27446bd2015-08-10 14:59:53 +0300373 ASSERT(!operatorRequiresLValue());
374 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300375 {
376 case EOpPostIncrement:
377 case EOpPostDecrement:
378 case EOpPreIncrement:
379 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300380 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300381 break;
382 default:
383 break;
384 }
385
Olli Etuaho27446bd2015-08-10 14:59:53 +0300386 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300387
Olli Etuaho27446bd2015-08-10 14:59:53 +0300388 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300389
Olli Etuaho27446bd2015-08-10 14:59:53 +0300390 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700391 }
392
Olli Etuaho27446bd2015-08-10 14:59:53 +0300393 if (visit && postVisit)
394 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395}
396
397//
398// Traverse an aggregate node. Same comments in binary node apply here.
399//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300400void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401{
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 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300405
406 if (preVisit)
407 visit = visitAggregate(PreVisit, node);
408
409 if (visit)
410 {
411 incrementDepth(node);
412
413 if (node->getOp() == EOpSequence)
414 pushParentBlock(node);
Olli Etuahod4f4c112016-04-15 15:11:24 +0300415 else if (node->getOp() == EOpFunction)
416 mInGlobalScope = false;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300417
418 for (auto *child : *sequence)
419 {
420 child->traverse(this);
421 if (visit && inVisit)
422 {
423 if (child != sequence->back())
424 visit = visitAggregate(InVisit, node);
425 }
426
427 if (node->getOp() == EOpSequence)
428 incrementParentBlockPos();
429 }
430
431 if (node->getOp() == EOpSequence)
432 popParentBlock();
Olli Etuahod4f4c112016-04-15 15:11:24 +0300433 else if (node->getOp() == EOpFunction)
434 mInGlobalScope = true;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300435
436 decrementDepth();
437 }
438
439 if (visit && postVisit)
440 visitAggregate(PostVisit, node);
441}
442
443void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
444{
445 bool visit = true;
446
447 TIntermSequence *sequence = node->getSequence();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300448 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300449 {
450 case EOpFunction:
451 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300452 TIntermAggregate *params = sequence->front()->getAsAggregate();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300453 ASSERT(params != nullptr);
454 ASSERT(params->getOp() == EOpParameters);
Olli Etuaho5f579b12015-08-14 17:44:43 +0300455 addToFunctionMap(node->getNameObj(), params->getSequence());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300456 break;
457 }
458 case EOpPrototype:
Olli Etuaho5f579b12015-08-14 17:44:43 +0300459 addToFunctionMap(node->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300460 break;
461 default:
462 break;
463 }
464
Olli Etuaho27446bd2015-08-10 14:59:53 +0300465 if (preVisit)
466 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000467
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700468 if (visit)
469 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300470 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300471 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700472 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300473 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300474 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300475 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300476 // The function is not user-defined - it is likely built-in texture function.
477 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300478 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700479 }
480 }
481
Olli Etuaho27446bd2015-08-10 14:59:53 +0300482 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300483
Olli Etuahoa26ad582015-08-04 13:51:47 +0300484 if (inFunctionMap)
485 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300486 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300487 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300488 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300489 {
490 ASSERT(paramIter != params->end());
491 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300492 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300493
Olli Etuaho27446bd2015-08-10 14:59:53 +0300494 child->traverse(this);
495 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300496 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300497 if (child != sequence->back())
498 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300499 }
500
501 ++paramIter;
502 }
503
Olli Etuaho27446bd2015-08-10 14:59:53 +0300504 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300505 }
506 else
507 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300508 if (node->getOp() == EOpSequence)
509 pushParentBlock(node);
Olli Etuahod4f4c112016-04-15 15:11:24 +0300510 else if (node->getOp() == EOpFunction)
511 mInGlobalScope = false;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300512
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300513 // Find the built-in function corresponding to this op so that we can determine the
514 // in/out qualifiers of its parameters.
515 TFunction *builtInFunc = nullptr;
516 TString opString = GetOperatorString(node->getOp());
517 if (!node->isConstructor() && !opString.empty())
518 {
519 // The return type doesn't affect the mangled name of the function, which is used
520 // to look it up from the symbol table.
521 TType dummyReturnType;
522 TFunction call(&opString, &dummyReturnType, node->getOp());
523 for (auto *child : *sequence)
524 {
525 TType *paramType = child->getAsTyped()->getTypePointer();
526 TConstParameter p(paramType);
527 call.addParameter(p);
528 }
529
530 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
531 if (sym != nullptr && sym->isFunction())
532 {
533 builtInFunc = static_cast<TFunction *>(sym);
534 ASSERT(builtInFunc->getParamCount() == sequence->size());
535 }
536 }
537
538 size_t paramIndex = 0;
539
Olli Etuaho27446bd2015-08-10 14:59:53 +0300540 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300541 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300542 TQualifier qualifier = EvqIn;
543 if (builtInFunc != nullptr)
544 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
545 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300546 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300547
Olli Etuaho27446bd2015-08-10 14:59:53 +0300548 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300549 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300550 if (child != sequence->back())
551 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300552 }
553
Olli Etuaho27446bd2015-08-10 14:59:53 +0300554 if (node->getOp() == EOpSequence)
555 incrementParentBlockPos();
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300556
557 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300558 }
559
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300560 setInFunctionCallOutParameter(false);
561
Olli Etuaho27446bd2015-08-10 14:59:53 +0300562 if (node->getOp() == EOpSequence)
563 popParentBlock();
Olli Etuahod4f4c112016-04-15 15:11:24 +0300564 else if (node->getOp() == EOpFunction)
565 mInGlobalScope = true;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300566 }
567
Olli Etuaho27446bd2015-08-10 14:59:53 +0300568 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700569 }
570
Olli Etuaho27446bd2015-08-10 14:59:53 +0300571 if (visit && postVisit)
572 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000573}
574
575//
576// Traverse a selection node. Same comments in binary node apply here.
577//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300578void TIntermTraverser::traverseSelection(TIntermSelection *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000579{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700580 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000581
Olli Etuaho27446bd2015-08-10 14:59:53 +0300582 if (preVisit)
583 visit = visitSelection(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000584
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700585 if (visit)
586 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300587 incrementDepth(node);
588 node->getCondition()->traverse(this);
589 if (node->getTrueBlock())
590 node->getTrueBlock()->traverse(this);
591 if (node->getFalseBlock())
592 node->getFalseBlock()->traverse(this);
593 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700594 }
595
Olli Etuaho27446bd2015-08-10 14:59:53 +0300596 if (visit && postVisit)
597 visitSelection(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598}
599
600//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200601// Traverse a switch node. Same comments in binary node apply here.
602//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300603void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200604{
605 bool visit = true;
606
Olli Etuaho27446bd2015-08-10 14:59:53 +0300607 if (preVisit)
608 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200609
610 if (visit)
611 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300612 incrementDepth(node);
613 node->getInit()->traverse(this);
614 if (inVisit)
615 visit = visitSwitch(InVisit, node);
616 if (visit && node->getStatementList())
617 node->getStatementList()->traverse(this);
618 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200619 }
620
Olli Etuaho27446bd2015-08-10 14:59:53 +0300621 if (visit && postVisit)
622 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200623}
624
625//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300626// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200627//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300628void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200629{
630 bool visit = true;
631
Olli Etuaho27446bd2015-08-10 14:59:53 +0300632 if (preVisit)
633 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200634
Olli Etuaho27446bd2015-08-10 14:59:53 +0300635 if (visit && node->getCondition())
636 node->getCondition()->traverse(this);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200637
Olli Etuaho27446bd2015-08-10 14:59:53 +0300638 if (visit && postVisit)
639 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200640}
641
642//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643// Traverse a loop node. Same comments in binary node apply here.
644//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300645void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700647 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000648
Olli Etuaho27446bd2015-08-10 14:59:53 +0300649 if (preVisit)
650 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700652 if (visit)
653 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300654 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655
Olli Etuaho27446bd2015-08-10 14:59:53 +0300656 if (node->getInit())
657 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000658
Olli Etuaho27446bd2015-08-10 14:59:53 +0300659 if (node->getCondition())
660 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661
Olli Etuaho27446bd2015-08-10 14:59:53 +0300662 if (node->getBody())
663 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700664
Olli Etuaho27446bd2015-08-10 14:59:53 +0300665 if (node->getExpression())
666 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000667
Olli Etuaho27446bd2015-08-10 14:59:53 +0300668 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700669 }
670
Olli Etuaho27446bd2015-08-10 14:59:53 +0300671 if (visit && postVisit)
672 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000673}
674
675//
676// Traverse a branch node. Same comments in binary node apply here.
677//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300678void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000679{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700680 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000681
Olli Etuaho27446bd2015-08-10 14:59:53 +0300682 if (preVisit)
683 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684
Olli Etuaho27446bd2015-08-10 14:59:53 +0300685 if (visit && node->getExpression())
686 {
687 incrementDepth(node);
688 node->getExpression()->traverse(this);
689 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700690 }
691
Olli Etuaho27446bd2015-08-10 14:59:53 +0300692 if (visit && postVisit)
693 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000694}
695
Olli Etuaho27446bd2015-08-10 14:59:53 +0300696void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400697{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300698 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400699}