blob: e09441410c06f3c71cf96f1ecf3ad0fb7b4bd7fc [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
Olli Etuahob6fa0432016-09-28 16:28:05 +010026void TIntermSwizzle::traverse(TIntermTraverser *it)
27{
28 it->traverseSwizzle(this);
29}
30
Olli Etuaho27446bd2015-08-10 14:59:53 +030031void TIntermBinary::traverse(TIntermTraverser *it)
32{
33 it->traverseBinary(this);
34}
35
36void TIntermUnary::traverse(TIntermTraverser *it)
37{
38 it->traverseUnary(this);
39}
40
Olli Etuahod0bad2c2016-09-09 18:01:16 +030041void TIntermTernary::traverse(TIntermTraverser *it)
42{
43 it->traverseTernary(this);
44}
45
Olli Etuaho57961272016-09-14 13:57:46 +030046void TIntermIfElse::traverse(TIntermTraverser *it)
Olli Etuaho27446bd2015-08-10 14:59:53 +030047{
Olli Etuaho57961272016-09-14 13:57:46 +030048 it->traverseIfElse(this);
Olli Etuaho27446bd2015-08-10 14:59:53 +030049}
50
51void TIntermSwitch::traverse(TIntermTraverser *it)
52{
53 it->traverseSwitch(this);
54}
55
56void TIntermCase::traverse(TIntermTraverser *it)
57{
58 it->traverseCase(this);
59}
60
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010061void TIntermBlock::traverse(TIntermTraverser *it)
62{
63 it->traverseBlock(this);
64}
65
Olli Etuaho27446bd2015-08-10 14:59:53 +030066void TIntermAggregate::traverse(TIntermTraverser *it)
67{
68 it->traverseAggregate(this);
69}
70
71void TIntermLoop::traverse(TIntermTraverser *it)
72{
73 it->traverseLoop(this);
74}
75
76void TIntermBranch::traverse(TIntermTraverser *it)
77{
78 it->traverseBranch(this);
79}
80
Jamie Madill03d863c2016-07-27 18:15:53 -040081TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
82 : preVisit(preVisit),
83 inVisit(inVisit),
84 postVisit(postVisit),
85 mDepth(0),
86 mMaxDepth(0),
87 mInGlobalScope(true),
88 mTemporaryIndex(nullptr)
89{
90}
91
92TIntermTraverser::~TIntermTraverser()
93{
94}
95
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010096void TIntermTraverser::pushParentBlock(TIntermBlock *node)
Olli Etuaho56eea882015-05-18 12:41:03 +030097{
Olli Etuaho64f0be92015-06-03 17:38:34 +030098 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +030099}
100
101void TIntermTraverser::incrementParentBlockPos()
102{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300103 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +0300104}
105
106void TIntermTraverser::popParentBlock()
107{
108 ASSERT(!mParentBlockStack.empty());
109 mParentBlockStack.pop_back();
110}
111
112void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
113{
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300114 TIntermSequence emptyInsertionsAfter;
115 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
116}
117
118void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
119 const TIntermSequence &insertionsAfter)
120{
Olli Etuaho56eea882015-05-18 12:41:03 +0300121 ASSERT(!mParentBlockStack.empty());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300122 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
123 insertionsBefore, insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300124 mInsertions.push_back(insert);
125}
126
Jamie Madill1048e432016-07-23 18:51:28 -0400127void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
128{
129 TIntermSequence insertions;
130 insertions.push_back(statement);
131 insertStatementsInParentBlock(insertions);
132}
133
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300134TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300135{
136 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
137 TInfoSinkBase symbolNameOut;
138 ASSERT(mTemporaryIndex != nullptr);
139 symbolNameOut << "s" << (*mTemporaryIndex);
140 TString symbolName = symbolNameOut.c_str();
141
142 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
143 node->setInternal(true);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300144 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300145 return node;
146}
147
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300148TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
149{
150 return createTempSymbol(type, EvqTemporary);
151}
152
Olli Etuaho4f1af782015-05-25 11:55:07 +0300153TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
154{
155 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
156 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
157 return tempDeclaration;
158}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300159
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300160TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300161{
162 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300163 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300164 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300165 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300166 tempDeclaration->getSequence()->push_back(tempInit);
167 return tempDeclaration;
168}
169
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300170TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
171{
172 return createTempInitDeclaration(initializer, EvqTemporary);
173}
174
Olli Etuahod4f303e2015-05-20 17:09:06 +0300175TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
176{
177 ASSERT(rightNode != nullptr);
178 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300179 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300180 return assignment;
181}
182
183void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
184{
185 mTemporaryIndex = temporaryIndex;
186}
187
188void TIntermTraverser::nextTemporaryIndex()
189{
190 ASSERT(mTemporaryIndex != nullptr);
191 ++(*mTemporaryIndex);
192}
193
Olli Etuaho5f579b12015-08-14 17:44:43 +0300194void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300195{
196 mFunctionMap[name] = paramSequence;
197}
198
Olli Etuaho3fc93372015-08-11 14:50:59 +0300199bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300200{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300201 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuaho5f579b12015-08-14 17:44:43 +0300202 return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300203}
204
Olli Etuaho3fc93372015-08-11 14:50:59 +0300205TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300206{
207 ASSERT(isInFunctionMap(callNode));
Olli Etuaho5f579b12015-08-14 17:44:43 +0300208 return mFunctionMap[callNode->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300209}
210
Olli Etuaho3fc93372015-08-11 14:50:59 +0300211void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300212{
213 mInFunctionCallOutParameter = inOutParameter;
214}
215
Olli Etuaho3fc93372015-08-11 14:50:59 +0300216bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300217{
218 return mInFunctionCallOutParameter;
219}
220
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221//
222// Traverse the intermediate representation tree, and
223// call a node type specific function for each node.
224// Done recursively through the member function Traverse().
225// Node types can be skipped if their function to call is 0,
226// but their subtree will still be traversed.
227// Nodes with children can have their whole subtree skipped
228// if preVisit is turned on and the type specific function
229// returns false.
230//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231
232//
233// Traversal functions for terminals are straighforward....
234//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300235void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300237 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238}
239
Olli Etuaho27446bd2015-08-10 14:59:53 +0300240void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300242 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243}
244
Olli Etuahob6fa0432016-09-28 16:28:05 +0100245void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
246{
247 bool visit = true;
248
249 if (preVisit)
250 visit = visitSwizzle(PreVisit, node);
251
252 if (visit)
253 {
254 incrementDepth(node);
255
256 node->getOperand()->traverse(this);
257
258 decrementDepth();
259 }
260
261 if (visit && postVisit)
262 visitSwizzle(PostVisit, node);
263}
264
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265//
266// Traverse a binary node.
267//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300268void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700270 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700272 //
273 // visit the node before children if pre-visiting.
274 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300275 if (preVisit)
276 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700278 //
279 // Visit the children, in the right order.
280 //
281 if (visit)
282 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300283 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284
Olli Etuaho3fc93372015-08-11 14:50:59 +0300285 if (node->getLeft())
286 node->getLeft()->traverse(this);
287
288 if (inVisit)
289 visit = visitBinary(InVisit, node);
290
291 if (visit && node->getRight())
292 node->getRight()->traverse(this);
293
294 decrementDepth();
295 }
296
297 //
298 // Visit the node after the children, if requested and the traversal
299 // hasn't been cancelled yet.
300 //
301 if (visit && postVisit)
302 visitBinary(PostVisit, node);
303}
304
305void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
306{
307 bool visit = true;
308
309 //
310 // visit the node before children if pre-visiting.
311 //
312 if (preVisit)
313 visit = visitBinary(PreVisit, node);
314
315 //
316 // Visit the children, in the right order.
317 //
318 if (visit)
319 {
320 incrementDepth(node);
321
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300322 // Some binary operations like indexing can be inside an expression which must be an
323 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300324 bool parentOperatorRequiresLValue = operatorRequiresLValue();
325 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
326 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300327 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300328 ASSERT(!isLValueRequiredHere());
329 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300330 }
331
Olli Etuaho27446bd2015-08-10 14:59:53 +0300332 if (node->getLeft())
333 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334
Olli Etuaho27446bd2015-08-10 14:59:53 +0300335 if (inVisit)
336 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337
Olli Etuaho27446bd2015-08-10 14:59:53 +0300338 if (node->isAssignment())
339 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300340
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300341 // Index is not required to be an l-value even when the surrounding expression is required
342 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300343 TOperator op = node->getOp();
344 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
345 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300346 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300347 setOperatorRequiresLValue(false);
348 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300349 }
350
Olli Etuaho27446bd2015-08-10 14:59:53 +0300351 if (visit && node->getRight())
352 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700353
Olli Etuaho27446bd2015-08-10 14:59:53 +0300354 setOperatorRequiresLValue(parentOperatorRequiresLValue);
355 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300356
Olli Etuaho27446bd2015-08-10 14:59:53 +0300357 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700358 }
359
360 //
361 // Visit the node after the children, if requested and the traversal
362 // hasn't been cancelled yet.
363 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300364 if (visit && postVisit)
365 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366}
367
368//
369// Traverse a unary node. Same comments in binary node apply here.
370//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300371void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700373 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374
Olli Etuaho27446bd2015-08-10 14:59:53 +0300375 if (preVisit)
376 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000377
Olli Etuahoa26ad582015-08-04 13:51:47 +0300378 if (visit)
379 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300380 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300381
Olli Etuaho3fc93372015-08-11 14:50:59 +0300382 node->getOperand()->traverse(this);
383
384 decrementDepth();
385 }
386
387 if (visit && postVisit)
388 visitUnary(PostVisit, node);
389}
390
391void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
392{
393 bool visit = true;
394
395 if (preVisit)
396 visit = visitUnary(PreVisit, node);
397
398 if (visit)
399 {
400 incrementDepth(node);
401
Olli Etuaho27446bd2015-08-10 14:59:53 +0300402 ASSERT(!operatorRequiresLValue());
403 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300404 {
405 case EOpPostIncrement:
406 case EOpPostDecrement:
407 case EOpPreIncrement:
408 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300409 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300410 break;
411 default:
412 break;
413 }
414
Olli Etuaho27446bd2015-08-10 14:59:53 +0300415 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300416
Olli Etuaho27446bd2015-08-10 14:59:53 +0300417 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300418
Olli Etuaho27446bd2015-08-10 14:59:53 +0300419 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700420 }
421
Olli Etuaho27446bd2015-08-10 14:59:53 +0300422 if (visit && postVisit)
423 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000424}
425
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100426// Traverse a block node.
427void TIntermTraverser::traverseBlock(TIntermBlock *node)
428{
429 bool visit = true;
430
431 TIntermSequence *sequence = node->getSequence();
432
433 if (preVisit)
434 visit = visitBlock(PreVisit, node);
435
436 if (visit)
437 {
438 incrementDepth(node);
439 pushParentBlock(node);
440
441 for (auto *child : *sequence)
442 {
443 child->traverse(this);
444 if (visit && inVisit)
445 {
446 if (child != sequence->back())
447 visit = visitBlock(InVisit, node);
448 }
449
450 incrementParentBlockPos();
451 }
452
453 popParentBlock();
454 decrementDepth();
455 }
456
457 if (visit && postVisit)
458 visitBlock(PostVisit, node);
459}
460
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000461// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300462void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700464 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465
Olli Etuaho27446bd2015-08-10 14:59:53 +0300466 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300467
468 if (preVisit)
469 visit = visitAggregate(PreVisit, node);
470
471 if (visit)
472 {
473 incrementDepth(node);
474
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100475 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300476 mInGlobalScope = false;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300477
478 for (auto *child : *sequence)
479 {
480 child->traverse(this);
481 if (visit && inVisit)
482 {
483 if (child != sequence->back())
484 visit = visitAggregate(InVisit, node);
485 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300486 }
487
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100488 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300489 mInGlobalScope = true;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300490
491 decrementDepth();
492 }
493
494 if (visit && postVisit)
495 visitAggregate(PostVisit, node);
496}
497
498void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
499{
500 bool visit = true;
501
502 TIntermSequence *sequence = node->getSequence();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300503 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300504 {
505 case EOpFunction:
506 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300507 TIntermAggregate *params = sequence->front()->getAsAggregate();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300508 ASSERT(params != nullptr);
509 ASSERT(params->getOp() == EOpParameters);
Olli Etuaho5f579b12015-08-14 17:44:43 +0300510 addToFunctionMap(node->getNameObj(), params->getSequence());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300511 break;
512 }
513 case EOpPrototype:
Olli Etuaho5f579b12015-08-14 17:44:43 +0300514 addToFunctionMap(node->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300515 break;
516 default:
517 break;
518 }
519
Olli Etuaho27446bd2015-08-10 14:59:53 +0300520 if (preVisit)
521 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000522
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700523 if (visit)
524 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300525 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300526 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700527 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300528 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300529 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300530 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300531 // The function is not user-defined - it is likely built-in texture function.
532 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300533 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700534 }
535 }
536
Olli Etuaho27446bd2015-08-10 14:59:53 +0300537 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300538
Olli Etuahoa26ad582015-08-04 13:51:47 +0300539 if (inFunctionMap)
540 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300541 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300542 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300543 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300544 {
545 ASSERT(paramIter != params->end());
546 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300547 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300548
Olli Etuaho27446bd2015-08-10 14:59:53 +0300549 child->traverse(this);
550 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300551 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300552 if (child != sequence->back())
553 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300554 }
555
556 ++paramIter;
557 }
558
Olli Etuaho27446bd2015-08-10 14:59:53 +0300559 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300560 }
561 else
562 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100563 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300564 mInGlobalScope = false;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300565
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300566 // Find the built-in function corresponding to this op so that we can determine the
567 // in/out qualifiers of its parameters.
568 TFunction *builtInFunc = nullptr;
569 TString opString = GetOperatorString(node->getOp());
570 if (!node->isConstructor() && !opString.empty())
571 {
572 // The return type doesn't affect the mangled name of the function, which is used
573 // to look it up from the symbol table.
574 TType dummyReturnType;
575 TFunction call(&opString, &dummyReturnType, node->getOp());
576 for (auto *child : *sequence)
577 {
578 TType *paramType = child->getAsTyped()->getTypePointer();
579 TConstParameter p(paramType);
580 call.addParameter(p);
581 }
582
583 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
584 if (sym != nullptr && sym->isFunction())
585 {
586 builtInFunc = static_cast<TFunction *>(sym);
587 ASSERT(builtInFunc->getParamCount() == sequence->size());
588 }
589 }
590
591 size_t paramIndex = 0;
592
Olli Etuaho27446bd2015-08-10 14:59:53 +0300593 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300594 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300595 TQualifier qualifier = EvqIn;
596 if (builtInFunc != nullptr)
597 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
598 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300599 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300600
Olli Etuaho27446bd2015-08-10 14:59:53 +0300601 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300602 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300603 if (child != sequence->back())
604 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300605 }
606
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300607 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300608 }
609
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300610 setInFunctionCallOutParameter(false);
611
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100612 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300613 mInGlobalScope = true;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300614 }
615
Olli Etuaho27446bd2015-08-10 14:59:53 +0300616 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700617 }
618
Olli Etuaho27446bd2015-08-10 14:59:53 +0300619 if (visit && postVisit)
620 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000621}
622
623//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300624// Traverse a ternary node. Same comments in binary node apply here.
625//
626void TIntermTraverser::traverseTernary(TIntermTernary *node)
627{
628 bool visit = true;
629
630 if (preVisit)
631 visit = visitTernary(PreVisit, node);
632
633 if (visit)
634 {
635 incrementDepth(node);
636 node->getCondition()->traverse(this);
637 if (node->getTrueExpression())
638 node->getTrueExpression()->traverse(this);
639 if (node->getFalseExpression())
640 node->getFalseExpression()->traverse(this);
641 decrementDepth();
642 }
643
644 if (visit && postVisit)
645 visitTernary(PostVisit, node);
646}
647
Olli Etuaho57961272016-09-14 13:57:46 +0300648// Traverse an if-else node. Same comments in binary node apply here.
649void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000650{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700651 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652
Olli Etuaho27446bd2015-08-10 14:59:53 +0300653 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300654 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700656 if (visit)
657 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300658 incrementDepth(node);
659 node->getCondition()->traverse(this);
660 if (node->getTrueBlock())
661 node->getTrueBlock()->traverse(this);
662 if (node->getFalseBlock())
663 node->getFalseBlock()->traverse(this);
664 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700665 }
666
Olli Etuaho27446bd2015-08-10 14:59:53 +0300667 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300668 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000669}
670
671//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200672// Traverse a switch node. Same comments in binary node apply here.
673//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300674void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200675{
676 bool visit = true;
677
Olli Etuaho27446bd2015-08-10 14:59:53 +0300678 if (preVisit)
679 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200680
681 if (visit)
682 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300683 incrementDepth(node);
684 node->getInit()->traverse(this);
685 if (inVisit)
686 visit = visitSwitch(InVisit, node);
687 if (visit && node->getStatementList())
688 node->getStatementList()->traverse(this);
689 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200690 }
691
Olli Etuaho27446bd2015-08-10 14:59:53 +0300692 if (visit && postVisit)
693 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200694}
695
696//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300697// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200698//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300699void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200700{
701 bool visit = true;
702
Olli Etuaho27446bd2015-08-10 14:59:53 +0300703 if (preVisit)
704 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200705
Olli Etuaho27446bd2015-08-10 14:59:53 +0300706 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100707 {
708 incrementDepth(node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300709 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100710 decrementDepth();
711 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200712
Olli Etuaho27446bd2015-08-10 14:59:53 +0300713 if (visit && postVisit)
714 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200715}
716
717//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000718// Traverse a loop node. Same comments in binary node apply here.
719//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300720void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700722 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723
Olli Etuaho27446bd2015-08-10 14:59:53 +0300724 if (preVisit)
725 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700727 if (visit)
728 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300729 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730
Olli Etuaho27446bd2015-08-10 14:59:53 +0300731 if (node->getInit())
732 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000733
Olli Etuaho27446bd2015-08-10 14:59:53 +0300734 if (node->getCondition())
735 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736
Olli Etuaho27446bd2015-08-10 14:59:53 +0300737 if (node->getBody())
738 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700739
Olli Etuaho27446bd2015-08-10 14:59:53 +0300740 if (node->getExpression())
741 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742
Olli Etuaho27446bd2015-08-10 14:59:53 +0300743 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700744 }
745
Olli Etuaho27446bd2015-08-10 14:59:53 +0300746 if (visit && postVisit)
747 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748}
749
750//
751// Traverse a branch node. Same comments in binary node apply here.
752//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300753void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000754{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700755 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000756
Olli Etuaho27446bd2015-08-10 14:59:53 +0300757 if (preVisit)
758 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000759
Olli Etuaho27446bd2015-08-10 14:59:53 +0300760 if (visit && node->getExpression())
761 {
762 incrementDepth(node);
763 node->getExpression()->traverse(this);
764 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700765 }
766
Olli Etuaho27446bd2015-08-10 14:59:53 +0300767 if (visit && postVisit)
768 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000769}
770
Olli Etuaho27446bd2015-08-10 14:59:53 +0300771void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400772{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300773 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400774}