blob: fcb447d0e72cfca48b8d45d5af9b2aef501672f0 [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 Etuahobd674552016-10-06 13:28:42 +0100202 return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
203 mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300204}
205
Olli Etuaho3fc93372015-08-11 14:50:59 +0300206TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300207{
208 ASSERT(isInFunctionMap(callNode));
Olli Etuahobd674552016-10-06 13:28:42 +0100209 return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300210}
211
Olli Etuaho3fc93372015-08-11 14:50:59 +0300212void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300213{
214 mInFunctionCallOutParameter = inOutParameter;
215}
216
Olli Etuaho3fc93372015-08-11 14:50:59 +0300217bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300218{
219 return mInFunctionCallOutParameter;
220}
221
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222//
223// Traverse the intermediate representation tree, and
224// call a node type specific function for each node.
225// Done recursively through the member function Traverse().
226// Node types can be skipped if their function to call is 0,
227// but their subtree will still be traversed.
228// Nodes with children can have their whole subtree skipped
229// if preVisit is turned on and the type specific function
230// returns false.
231//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232
233//
234// Traversal functions for terminals are straighforward....
235//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300236void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300238 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239}
240
Olli Etuaho27446bd2015-08-10 14:59:53 +0300241void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300243 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244}
245
Olli Etuahob6fa0432016-09-28 16:28:05 +0100246void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
247{
248 bool visit = true;
249
250 if (preVisit)
251 visit = visitSwizzle(PreVisit, node);
252
253 if (visit)
254 {
255 incrementDepth(node);
256
257 node->getOperand()->traverse(this);
258
259 decrementDepth();
260 }
261
262 if (visit && postVisit)
263 visitSwizzle(PostVisit, node);
264}
265
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266//
267// Traverse a binary node.
268//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300269void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700271 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700273 //
274 // visit the node before children if pre-visiting.
275 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300276 if (preVisit)
277 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700279 //
280 // Visit the children, in the right order.
281 //
282 if (visit)
283 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300284 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285
Olli Etuaho3fc93372015-08-11 14:50:59 +0300286 if (node->getLeft())
287 node->getLeft()->traverse(this);
288
289 if (inVisit)
290 visit = visitBinary(InVisit, node);
291
292 if (visit && node->getRight())
293 node->getRight()->traverse(this);
294
295 decrementDepth();
296 }
297
298 //
299 // Visit the node after the children, if requested and the traversal
300 // hasn't been cancelled yet.
301 //
302 if (visit && postVisit)
303 visitBinary(PostVisit, node);
304}
305
306void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
307{
308 bool visit = true;
309
310 //
311 // visit the node before children if pre-visiting.
312 //
313 if (preVisit)
314 visit = visitBinary(PreVisit, node);
315
316 //
317 // Visit the children, in the right order.
318 //
319 if (visit)
320 {
321 incrementDepth(node);
322
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300323 // Some binary operations like indexing can be inside an expression which must be an
324 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300325 bool parentOperatorRequiresLValue = operatorRequiresLValue();
326 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
327 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300328 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300329 ASSERT(!isLValueRequiredHere());
330 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300331 }
332
Olli Etuaho27446bd2015-08-10 14:59:53 +0300333 if (node->getLeft())
334 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335
Olli Etuaho27446bd2015-08-10 14:59:53 +0300336 if (inVisit)
337 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338
Olli Etuaho27446bd2015-08-10 14:59:53 +0300339 if (node->isAssignment())
340 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300341
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300342 // Index is not required to be an l-value even when the surrounding expression is required
343 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300344 TOperator op = node->getOp();
345 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
346 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300347 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300348 setOperatorRequiresLValue(false);
349 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300350 }
351
Olli Etuaho27446bd2015-08-10 14:59:53 +0300352 if (visit && node->getRight())
353 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700354
Olli Etuaho27446bd2015-08-10 14:59:53 +0300355 setOperatorRequiresLValue(parentOperatorRequiresLValue);
356 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300357
Olli Etuaho27446bd2015-08-10 14:59:53 +0300358 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700359 }
360
361 //
362 // Visit the node after the children, if requested and the traversal
363 // hasn't been cancelled yet.
364 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300365 if (visit && postVisit)
366 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367}
368
369//
370// Traverse a unary node. Same comments in binary node apply here.
371//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300372void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700374 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375
Olli Etuaho27446bd2015-08-10 14:59:53 +0300376 if (preVisit)
377 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378
Olli Etuahoa26ad582015-08-04 13:51:47 +0300379 if (visit)
380 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300381 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300382
Olli Etuaho3fc93372015-08-11 14:50:59 +0300383 node->getOperand()->traverse(this);
384
385 decrementDepth();
386 }
387
388 if (visit && postVisit)
389 visitUnary(PostVisit, node);
390}
391
392void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
393{
394 bool visit = true;
395
396 if (preVisit)
397 visit = visitUnary(PreVisit, node);
398
399 if (visit)
400 {
401 incrementDepth(node);
402
Olli Etuaho27446bd2015-08-10 14:59:53 +0300403 ASSERT(!operatorRequiresLValue());
404 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300405 {
406 case EOpPostIncrement:
407 case EOpPostDecrement:
408 case EOpPreIncrement:
409 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300410 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300411 break;
412 default:
413 break;
414 }
415
Olli Etuaho27446bd2015-08-10 14:59:53 +0300416 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300417
Olli Etuaho27446bd2015-08-10 14:59:53 +0300418 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300419
Olli Etuaho27446bd2015-08-10 14:59:53 +0300420 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700421 }
422
Olli Etuaho27446bd2015-08-10 14:59:53 +0300423 if (visit && postVisit)
424 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425}
426
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100427// Traverse a block node.
428void TIntermTraverser::traverseBlock(TIntermBlock *node)
429{
430 bool visit = true;
431
432 TIntermSequence *sequence = node->getSequence();
433
434 if (preVisit)
435 visit = visitBlock(PreVisit, node);
436
437 if (visit)
438 {
439 incrementDepth(node);
440 pushParentBlock(node);
441
442 for (auto *child : *sequence)
443 {
444 child->traverse(this);
445 if (visit && inVisit)
446 {
447 if (child != sequence->back())
448 visit = visitBlock(InVisit, node);
449 }
450
451 incrementParentBlockPos();
452 }
453
454 popParentBlock();
455 decrementDepth();
456 }
457
458 if (visit && postVisit)
459 visitBlock(PostVisit, node);
460}
461
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300463void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000464{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700465 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466
Olli Etuaho27446bd2015-08-10 14:59:53 +0300467 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300468
469 if (preVisit)
470 visit = visitAggregate(PreVisit, node);
471
472 if (visit)
473 {
474 incrementDepth(node);
475
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100476 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300477 mInGlobalScope = false;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300478
479 for (auto *child : *sequence)
480 {
481 child->traverse(this);
482 if (visit && inVisit)
483 {
484 if (child != sequence->back())
485 visit = visitAggregate(InVisit, node);
486 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300487 }
488
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100489 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300490 mInGlobalScope = true;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300491
492 decrementDepth();
493 }
494
495 if (visit && postVisit)
496 visitAggregate(PostVisit, node);
497}
498
499void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
500{
501 bool visit = true;
502
503 TIntermSequence *sequence = node->getSequence();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300504 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300505 {
506 case EOpFunction:
507 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300508 TIntermAggregate *params = sequence->front()->getAsAggregate();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300509 ASSERT(params != nullptr);
510 ASSERT(params->getOp() == EOpParameters);
Olli Etuahobd674552016-10-06 13:28:42 +0100511 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300512 break;
513 }
514 case EOpPrototype:
Olli Etuahobd674552016-10-06 13:28:42 +0100515 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300516 break;
517 default:
518 break;
519 }
520
Olli Etuaho27446bd2015-08-10 14:59:53 +0300521 if (preVisit)
522 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700524 if (visit)
525 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300526 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300527 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700528 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300529 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300530 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300531 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300532 // The function is not user-defined - it is likely built-in texture function.
533 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300534 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700535 }
536 }
537
Olli Etuaho27446bd2015-08-10 14:59:53 +0300538 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300539
Olli Etuahoa26ad582015-08-04 13:51:47 +0300540 if (inFunctionMap)
541 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300542 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300543 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300544 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300545 {
546 ASSERT(paramIter != params->end());
547 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300548 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300549
Olli Etuaho27446bd2015-08-10 14:59:53 +0300550 child->traverse(this);
551 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300552 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300553 if (child != sequence->back())
554 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300555 }
556
557 ++paramIter;
558 }
559
Olli Etuaho27446bd2015-08-10 14:59:53 +0300560 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300561 }
562 else
563 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100564 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300565 mInGlobalScope = false;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300566
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300567 // Find the built-in function corresponding to this op so that we can determine the
568 // in/out qualifiers of its parameters.
569 TFunction *builtInFunc = nullptr;
570 TString opString = GetOperatorString(node->getOp());
571 if (!node->isConstructor() && !opString.empty())
572 {
573 // The return type doesn't affect the mangled name of the function, which is used
574 // to look it up from the symbol table.
575 TType dummyReturnType;
576 TFunction call(&opString, &dummyReturnType, node->getOp());
577 for (auto *child : *sequence)
578 {
579 TType *paramType = child->getAsTyped()->getTypePointer();
580 TConstParameter p(paramType);
581 call.addParameter(p);
582 }
583
584 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
585 if (sym != nullptr && sym->isFunction())
586 {
587 builtInFunc = static_cast<TFunction *>(sym);
588 ASSERT(builtInFunc->getParamCount() == sequence->size());
589 }
590 }
591
592 size_t paramIndex = 0;
593
Olli Etuaho27446bd2015-08-10 14:59:53 +0300594 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300595 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300596 TQualifier qualifier = EvqIn;
597 if (builtInFunc != nullptr)
598 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
599 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300600 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300601
Olli Etuaho27446bd2015-08-10 14:59:53 +0300602 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300603 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300604 if (child != sequence->back())
605 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300606 }
607
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300608 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300609 }
610
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300611 setInFunctionCallOutParameter(false);
612
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100613 if (node->getOp() == EOpFunction)
Olli Etuahod4f4c112016-04-15 15:11:24 +0300614 mInGlobalScope = true;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300615 }
616
Olli Etuaho27446bd2015-08-10 14:59:53 +0300617 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700618 }
619
Olli Etuaho27446bd2015-08-10 14:59:53 +0300620 if (visit && postVisit)
621 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000622}
623
624//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300625// Traverse a ternary node. Same comments in binary node apply here.
626//
627void TIntermTraverser::traverseTernary(TIntermTernary *node)
628{
629 bool visit = true;
630
631 if (preVisit)
632 visit = visitTernary(PreVisit, node);
633
634 if (visit)
635 {
636 incrementDepth(node);
637 node->getCondition()->traverse(this);
638 if (node->getTrueExpression())
639 node->getTrueExpression()->traverse(this);
640 if (node->getFalseExpression())
641 node->getFalseExpression()->traverse(this);
642 decrementDepth();
643 }
644
645 if (visit && postVisit)
646 visitTernary(PostVisit, node);
647}
648
Olli Etuaho57961272016-09-14 13:57:46 +0300649// Traverse an if-else node. Same comments in binary node apply here.
650void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700652 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653
Olli Etuaho27446bd2015-08-10 14:59:53 +0300654 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300655 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700657 if (visit)
658 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300659 incrementDepth(node);
660 node->getCondition()->traverse(this);
661 if (node->getTrueBlock())
662 node->getTrueBlock()->traverse(this);
663 if (node->getFalseBlock())
664 node->getFalseBlock()->traverse(this);
665 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700666 }
667
Olli Etuaho27446bd2015-08-10 14:59:53 +0300668 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300669 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670}
671
672//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200673// Traverse a switch node. Same comments in binary node apply here.
674//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300675void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200676{
677 bool visit = true;
678
Olli Etuaho27446bd2015-08-10 14:59:53 +0300679 if (preVisit)
680 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200681
682 if (visit)
683 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300684 incrementDepth(node);
685 node->getInit()->traverse(this);
686 if (inVisit)
687 visit = visitSwitch(InVisit, node);
688 if (visit && node->getStatementList())
689 node->getStatementList()->traverse(this);
690 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200691 }
692
Olli Etuaho27446bd2015-08-10 14:59:53 +0300693 if (visit && postVisit)
694 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200695}
696
697//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300698// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200699//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300700void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200701{
702 bool visit = true;
703
Olli Etuaho27446bd2015-08-10 14:59:53 +0300704 if (preVisit)
705 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200706
Olli Etuaho27446bd2015-08-10 14:59:53 +0300707 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100708 {
709 incrementDepth(node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300710 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100711 decrementDepth();
712 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200713
Olli Etuaho27446bd2015-08-10 14:59:53 +0300714 if (visit && postVisit)
715 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200716}
717
718//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000719// Traverse a loop node. Same comments in binary node apply here.
720//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300721void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000722{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700723 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000724
Olli Etuaho27446bd2015-08-10 14:59:53 +0300725 if (preVisit)
726 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000727
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700728 if (visit)
729 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300730 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000731
Olli Etuaho27446bd2015-08-10 14:59:53 +0300732 if (node->getInit())
733 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000734
Olli Etuaho27446bd2015-08-10 14:59:53 +0300735 if (node->getCondition())
736 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737
Olli Etuaho27446bd2015-08-10 14:59:53 +0300738 if (node->getBody())
739 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700740
Olli Etuaho27446bd2015-08-10 14:59:53 +0300741 if (node->getExpression())
742 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000743
Olli Etuaho27446bd2015-08-10 14:59:53 +0300744 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700745 }
746
Olli Etuaho27446bd2015-08-10 14:59:53 +0300747 if (visit && postVisit)
748 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000749}
750
751//
752// Traverse a branch node. Same comments in binary node apply here.
753//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300754void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000755{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700756 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757
Olli Etuaho27446bd2015-08-10 14:59:53 +0300758 if (preVisit)
759 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760
Olli Etuaho27446bd2015-08-10 14:59:53 +0300761 if (visit && node->getExpression())
762 {
763 incrementDepth(node);
764 node->getExpression()->traverse(this);
765 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700766 }
767
Olli Etuaho27446bd2015-08-10 14:59:53 +0300768 if (visit && postVisit)
769 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770}
771
Olli Etuaho27446bd2015-08-10 14:59:53 +0300772void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400773{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300774 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400775}