blob: 29f81f401fdc7875735de19d21e056b5f74cad5c [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 Etuaho336b1472016-10-05 16:37:55 +010061void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
62{
63 it->traverseFunctionDefinition(this);
64}
65
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010066void TIntermBlock::traverse(TIntermTraverser *it)
67{
68 it->traverseBlock(this);
69}
70
Olli Etuaho27446bd2015-08-10 14:59:53 +030071void TIntermAggregate::traverse(TIntermTraverser *it)
72{
73 it->traverseAggregate(this);
74}
75
76void TIntermLoop::traverse(TIntermTraverser *it)
77{
78 it->traverseLoop(this);
79}
80
81void TIntermBranch::traverse(TIntermTraverser *it)
82{
83 it->traverseBranch(this);
84}
85
Jamie Madill03d863c2016-07-27 18:15:53 -040086TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
87 : preVisit(preVisit),
88 inVisit(inVisit),
89 postVisit(postVisit),
90 mDepth(0),
91 mMaxDepth(0),
92 mInGlobalScope(true),
93 mTemporaryIndex(nullptr)
94{
95}
96
97TIntermTraverser::~TIntermTraverser()
98{
99}
100
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100101void TIntermTraverser::pushParentBlock(TIntermBlock *node)
Olli Etuaho56eea882015-05-18 12:41:03 +0300102{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300103 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +0300104}
105
106void TIntermTraverser::incrementParentBlockPos()
107{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300108 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +0300109}
110
111void TIntermTraverser::popParentBlock()
112{
113 ASSERT(!mParentBlockStack.empty());
114 mParentBlockStack.pop_back();
115}
116
117void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
118{
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300119 TIntermSequence emptyInsertionsAfter;
120 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
121}
122
123void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
124 const TIntermSequence &insertionsAfter)
125{
Olli Etuaho56eea882015-05-18 12:41:03 +0300126 ASSERT(!mParentBlockStack.empty());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300127 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
128 insertionsBefore, insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300129 mInsertions.push_back(insert);
130}
131
Jamie Madill1048e432016-07-23 18:51:28 -0400132void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
133{
134 TIntermSequence insertions;
135 insertions.push_back(statement);
136 insertStatementsInParentBlock(insertions);
137}
138
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300139TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300140{
141 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
142 TInfoSinkBase symbolNameOut;
143 ASSERT(mTemporaryIndex != nullptr);
144 symbolNameOut << "s" << (*mTemporaryIndex);
145 TString symbolName = symbolNameOut.c_str();
146
147 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
148 node->setInternal(true);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300149 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300150 return node;
151}
152
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300153TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
154{
155 return createTempSymbol(type, EvqTemporary);
156}
157
Olli Etuaho4f1af782015-05-25 11:55:07 +0300158TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
159{
160 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
161 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
162 return tempDeclaration;
163}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300164
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300165TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300166{
167 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300168 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300169 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300170 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300171 tempDeclaration->getSequence()->push_back(tempInit);
172 return tempDeclaration;
173}
174
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300175TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
176{
177 return createTempInitDeclaration(initializer, EvqTemporary);
178}
179
Olli Etuahod4f303e2015-05-20 17:09:06 +0300180TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
181{
182 ASSERT(rightNode != nullptr);
183 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300184 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300185 return assignment;
186}
187
188void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
189{
190 mTemporaryIndex = temporaryIndex;
191}
192
193void TIntermTraverser::nextTemporaryIndex()
194{
195 ASSERT(mTemporaryIndex != nullptr);
196 ++(*mTemporaryIndex);
197}
198
Olli Etuaho5f579b12015-08-14 17:44:43 +0300199void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300200{
201 mFunctionMap[name] = paramSequence;
202}
203
Olli Etuaho3fc93372015-08-11 14:50:59 +0300204bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300205{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300206 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuahobd674552016-10-06 13:28:42 +0100207 return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
208 mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300209}
210
Olli Etuaho3fc93372015-08-11 14:50:59 +0300211TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300212{
213 ASSERT(isInFunctionMap(callNode));
Olli Etuahobd674552016-10-06 13:28:42 +0100214 return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300215}
216
Olli Etuaho3fc93372015-08-11 14:50:59 +0300217void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300218{
219 mInFunctionCallOutParameter = inOutParameter;
220}
221
Olli Etuaho3fc93372015-08-11 14:50:59 +0300222bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300223{
224 return mInFunctionCallOutParameter;
225}
226
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227//
228// Traverse the intermediate representation tree, and
229// call a node type specific function for each node.
230// Done recursively through the member function Traverse().
231// Node types can be skipped if their function to call is 0,
232// but their subtree will still be traversed.
233// Nodes with children can have their whole subtree skipped
234// if preVisit is turned on and the type specific function
235// returns false.
236//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237
238//
239// Traversal functions for terminals are straighforward....
240//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300241void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300243 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244}
245
Olli Etuaho27446bd2015-08-10 14:59:53 +0300246void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300248 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249}
250
Olli Etuahob6fa0432016-09-28 16:28:05 +0100251void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
252{
253 bool visit = true;
254
255 if (preVisit)
256 visit = visitSwizzle(PreVisit, node);
257
258 if (visit)
259 {
260 incrementDepth(node);
261
262 node->getOperand()->traverse(this);
263
264 decrementDepth();
265 }
266
267 if (visit && postVisit)
268 visitSwizzle(PostVisit, node);
269}
270
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271//
272// Traverse a binary node.
273//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300274void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700276 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700278 //
279 // visit the node before children if pre-visiting.
280 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300281 if (preVisit)
282 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700284 //
285 // Visit the children, in the right order.
286 //
287 if (visit)
288 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300289 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290
Olli Etuaho3fc93372015-08-11 14:50:59 +0300291 if (node->getLeft())
292 node->getLeft()->traverse(this);
293
294 if (inVisit)
295 visit = visitBinary(InVisit, node);
296
297 if (visit && node->getRight())
298 node->getRight()->traverse(this);
299
300 decrementDepth();
301 }
302
303 //
304 // Visit the node after the children, if requested and the traversal
305 // hasn't been cancelled yet.
306 //
307 if (visit && postVisit)
308 visitBinary(PostVisit, node);
309}
310
311void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
312{
313 bool visit = true;
314
315 //
316 // visit the node before children if pre-visiting.
317 //
318 if (preVisit)
319 visit = visitBinary(PreVisit, node);
320
321 //
322 // Visit the children, in the right order.
323 //
324 if (visit)
325 {
326 incrementDepth(node);
327
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300328 // Some binary operations like indexing can be inside an expression which must be an
329 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300330 bool parentOperatorRequiresLValue = operatorRequiresLValue();
331 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
332 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300333 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300334 ASSERT(!isLValueRequiredHere());
335 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300336 }
337
Olli Etuaho27446bd2015-08-10 14:59:53 +0300338 if (node->getLeft())
339 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000340
Olli Etuaho27446bd2015-08-10 14:59:53 +0300341 if (inVisit)
342 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
Olli Etuaho27446bd2015-08-10 14:59:53 +0300344 if (node->isAssignment())
345 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300346
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300347 // Index is not required to be an l-value even when the surrounding expression is required
348 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300349 TOperator op = node->getOp();
350 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
351 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300352 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300353 setOperatorRequiresLValue(false);
354 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300355 }
356
Olli Etuaho27446bd2015-08-10 14:59:53 +0300357 if (visit && node->getRight())
358 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700359
Olli Etuaho27446bd2015-08-10 14:59:53 +0300360 setOperatorRequiresLValue(parentOperatorRequiresLValue);
361 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300362
Olli Etuaho27446bd2015-08-10 14:59:53 +0300363 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700364 }
365
366 //
367 // Visit the node after the children, if requested and the traversal
368 // hasn't been cancelled yet.
369 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300370 if (visit && postVisit)
371 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372}
373
374//
375// Traverse a unary node. Same comments in binary node apply here.
376//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300377void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700379 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380
Olli Etuaho27446bd2015-08-10 14:59:53 +0300381 if (preVisit)
382 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383
Olli Etuahoa26ad582015-08-04 13:51:47 +0300384 if (visit)
385 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300386 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300387
Olli Etuaho3fc93372015-08-11 14:50:59 +0300388 node->getOperand()->traverse(this);
389
390 decrementDepth();
391 }
392
393 if (visit && postVisit)
394 visitUnary(PostVisit, node);
395}
396
397void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
398{
399 bool visit = true;
400
401 if (preVisit)
402 visit = visitUnary(PreVisit, node);
403
404 if (visit)
405 {
406 incrementDepth(node);
407
Olli Etuaho27446bd2015-08-10 14:59:53 +0300408 ASSERT(!operatorRequiresLValue());
409 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300410 {
411 case EOpPostIncrement:
412 case EOpPostDecrement:
413 case EOpPreIncrement:
414 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300415 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300416 break;
417 default:
418 break;
419 }
420
Olli Etuaho27446bd2015-08-10 14:59:53 +0300421 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300422
Olli Etuaho27446bd2015-08-10 14:59:53 +0300423 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300424
Olli Etuaho27446bd2015-08-10 14:59:53 +0300425 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700426 }
427
Olli Etuaho27446bd2015-08-10 14:59:53 +0300428 if (visit && postVisit)
429 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000430}
431
Olli Etuaho336b1472016-10-05 16:37:55 +0100432// Traverse a function definition node.
433void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
434{
435 bool visit = true;
436
437 if (preVisit)
438 visit = visitFunctionDefinition(PreVisit, node);
439
440 if (visit)
441 {
442 incrementDepth(node);
443 mInGlobalScope = false;
444
445 node->getFunctionParameters()->traverse(this);
446 if (inVisit)
447 visit = visitFunctionDefinition(InVisit, node);
448 node->getBody()->traverse(this);
449
450 mInGlobalScope = true;
451 decrementDepth();
452 }
453
454 if (visit && postVisit)
455 visitFunctionDefinition(PostVisit, node);
456}
457
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100458// Traverse a block node.
459void TIntermTraverser::traverseBlock(TIntermBlock *node)
460{
461 bool visit = true;
462
463 TIntermSequence *sequence = node->getSequence();
464
465 if (preVisit)
466 visit = visitBlock(PreVisit, node);
467
468 if (visit)
469 {
470 incrementDepth(node);
471 pushParentBlock(node);
472
473 for (auto *child : *sequence)
474 {
475 child->traverse(this);
476 if (visit && inVisit)
477 {
478 if (child != sequence->back())
479 visit = visitBlock(InVisit, node);
480 }
481
482 incrementParentBlockPos();
483 }
484
485 popParentBlock();
486 decrementDepth();
487 }
488
489 if (visit && postVisit)
490 visitBlock(PostVisit, node);
491}
492
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300494void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000495{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700496 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000497
Olli Etuaho27446bd2015-08-10 14:59:53 +0300498 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300499
500 if (preVisit)
501 visit = visitAggregate(PreVisit, node);
502
503 if (visit)
504 {
505 incrementDepth(node);
506
Olli Etuaho3fc93372015-08-11 14:50:59 +0300507 for (auto *child : *sequence)
508 {
509 child->traverse(this);
510 if (visit && inVisit)
511 {
512 if (child != sequence->back())
513 visit = visitAggregate(InVisit, node);
514 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300515 }
516
Olli Etuaho3fc93372015-08-11 14:50:59 +0300517 decrementDepth();
518 }
519
520 if (visit && postVisit)
521 visitAggregate(PostVisit, node);
522}
523
Olli Etuaho336b1472016-10-05 16:37:55 +0100524void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
525{
526 TIntermAggregate *params = node->getFunctionParameters();
527 ASSERT(params != nullptr);
528 ASSERT(params->getOp() == EOpParameters);
529 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
530
531 TIntermTraverser::traverseFunctionDefinition(node);
532}
533
Olli Etuaho3fc93372015-08-11 14:50:59 +0300534void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
535{
536 bool visit = true;
537
538 TIntermSequence *sequence = node->getSequence();
Olli Etuaho336b1472016-10-05 16:37:55 +0100539 if (node->getOp() == EOpPrototype)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300540 {
Olli Etuaho336b1472016-10-05 16:37:55 +0100541 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300542 }
543
Olli Etuaho27446bd2015-08-10 14:59:53 +0300544 if (preVisit)
545 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000546
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700547 if (visit)
548 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300549 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300550 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700551 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300552 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300553 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300554 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300555 // The function is not user-defined - it is likely built-in texture function.
556 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300557 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700558 }
559 }
560
Olli Etuaho27446bd2015-08-10 14:59:53 +0300561 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300562
Olli Etuahoa26ad582015-08-04 13:51:47 +0300563 if (inFunctionMap)
564 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300565 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300566 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300567 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300568 {
569 ASSERT(paramIter != params->end());
570 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300571 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300572
Olli Etuaho27446bd2015-08-10 14:59:53 +0300573 child->traverse(this);
574 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300575 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300576 if (child != sequence->back())
577 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300578 }
579
580 ++paramIter;
581 }
582
Olli Etuaho27446bd2015-08-10 14:59:53 +0300583 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300584 }
585 else
586 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300587 // Find the built-in function corresponding to this op so that we can determine the
588 // in/out qualifiers of its parameters.
589 TFunction *builtInFunc = nullptr;
590 TString opString = GetOperatorString(node->getOp());
591 if (!node->isConstructor() && !opString.empty())
592 {
593 // The return type doesn't affect the mangled name of the function, which is used
594 // to look it up from the symbol table.
595 TType dummyReturnType;
596 TFunction call(&opString, &dummyReturnType, node->getOp());
597 for (auto *child : *sequence)
598 {
599 TType *paramType = child->getAsTyped()->getTypePointer();
600 TConstParameter p(paramType);
601 call.addParameter(p);
602 }
603
604 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
605 if (sym != nullptr && sym->isFunction())
606 {
607 builtInFunc = static_cast<TFunction *>(sym);
608 ASSERT(builtInFunc->getParamCount() == sequence->size());
609 }
610 }
611
612 size_t paramIndex = 0;
613
Olli Etuaho27446bd2015-08-10 14:59:53 +0300614 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300615 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300616 TQualifier qualifier = EvqIn;
617 if (builtInFunc != nullptr)
618 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
619 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300620 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300621
Olli Etuaho27446bd2015-08-10 14:59:53 +0300622 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300623 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300624 if (child != sequence->back())
625 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300626 }
627
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300628 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300629 }
630
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300631 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300632 }
633
Olli Etuaho27446bd2015-08-10 14:59:53 +0300634 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700635 }
636
Olli Etuaho27446bd2015-08-10 14:59:53 +0300637 if (visit && postVisit)
638 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000639}
640
641//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300642// Traverse a ternary node. Same comments in binary node apply here.
643//
644void TIntermTraverser::traverseTernary(TIntermTernary *node)
645{
646 bool visit = true;
647
648 if (preVisit)
649 visit = visitTernary(PreVisit, node);
650
651 if (visit)
652 {
653 incrementDepth(node);
654 node->getCondition()->traverse(this);
655 if (node->getTrueExpression())
656 node->getTrueExpression()->traverse(this);
657 if (node->getFalseExpression())
658 node->getFalseExpression()->traverse(this);
659 decrementDepth();
660 }
661
662 if (visit && postVisit)
663 visitTernary(PostVisit, node);
664}
665
Olli Etuaho57961272016-09-14 13:57:46 +0300666// Traverse an if-else node. Same comments in binary node apply here.
667void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700669 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670
Olli Etuaho27446bd2015-08-10 14:59:53 +0300671 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300672 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000673
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700674 if (visit)
675 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300676 incrementDepth(node);
677 node->getCondition()->traverse(this);
678 if (node->getTrueBlock())
679 node->getTrueBlock()->traverse(this);
680 if (node->getFalseBlock())
681 node->getFalseBlock()->traverse(this);
682 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700683 }
684
Olli Etuaho27446bd2015-08-10 14:59:53 +0300685 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300686 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000687}
688
689//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200690// Traverse a switch node. Same comments in binary node apply here.
691//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300692void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200693{
694 bool visit = true;
695
Olli Etuaho27446bd2015-08-10 14:59:53 +0300696 if (preVisit)
697 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200698
699 if (visit)
700 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300701 incrementDepth(node);
702 node->getInit()->traverse(this);
703 if (inVisit)
704 visit = visitSwitch(InVisit, node);
705 if (visit && node->getStatementList())
706 node->getStatementList()->traverse(this);
707 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200708 }
709
Olli Etuaho27446bd2015-08-10 14:59:53 +0300710 if (visit && postVisit)
711 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200712}
713
714//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300715// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200716//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300717void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200718{
719 bool visit = true;
720
Olli Etuaho27446bd2015-08-10 14:59:53 +0300721 if (preVisit)
722 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200723
Olli Etuaho27446bd2015-08-10 14:59:53 +0300724 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100725 {
726 incrementDepth(node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300727 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100728 decrementDepth();
729 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200730
Olli Etuaho27446bd2015-08-10 14:59:53 +0300731 if (visit && postVisit)
732 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200733}
734
735//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736// Traverse a loop node. Same comments in binary node apply here.
737//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300738void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700740 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000741
Olli Etuaho27446bd2015-08-10 14:59:53 +0300742 if (preVisit)
743 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000744
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700745 if (visit)
746 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300747 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748
Olli Etuaho27446bd2015-08-10 14:59:53 +0300749 if (node->getInit())
750 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000751
Olli Etuaho27446bd2015-08-10 14:59:53 +0300752 if (node->getCondition())
753 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000754
Olli Etuaho27446bd2015-08-10 14:59:53 +0300755 if (node->getBody())
756 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700757
Olli Etuaho27446bd2015-08-10 14:59:53 +0300758 if (node->getExpression())
759 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760
Olli Etuaho27446bd2015-08-10 14:59:53 +0300761 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700762 }
763
Olli Etuaho27446bd2015-08-10 14:59:53 +0300764 if (visit && postVisit)
765 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766}
767
768//
769// Traverse a branch node. Same comments in binary node apply here.
770//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300771void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000772{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700773 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000774
Olli Etuaho27446bd2015-08-10 14:59:53 +0300775 if (preVisit)
776 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777
Olli Etuaho27446bd2015-08-10 14:59:53 +0300778 if (visit && node->getExpression())
779 {
780 incrementDepth(node);
781 node->getExpression()->traverse(this);
782 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700783 }
784
Olli Etuaho27446bd2015-08-10 14:59:53 +0300785 if (visit && postVisit)
786 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000787}
788
Olli Etuaho27446bd2015-08-10 14:59:53 +0300789void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400790{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300791 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400792}