blob: c6a199ec407d3e64fee5d67a3f127e61b873c25d [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 Etuaho13389b62016-10-16 11:48:18 +010071void TIntermDeclaration::traverse(TIntermTraverser *it)
72{
73 it->traverseDeclaration(this);
74}
75
Olli Etuaho27446bd2015-08-10 14:59:53 +030076void TIntermAggregate::traverse(TIntermTraverser *it)
77{
78 it->traverseAggregate(this);
79}
80
81void TIntermLoop::traverse(TIntermTraverser *it)
82{
83 it->traverseLoop(this);
84}
85
86void TIntermBranch::traverse(TIntermTraverser *it)
87{
88 it->traverseBranch(this);
89}
90
Jamie Madill03d863c2016-07-27 18:15:53 -040091TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
92 : preVisit(preVisit),
93 inVisit(inVisit),
94 postVisit(postVisit),
95 mDepth(0),
96 mMaxDepth(0),
97 mInGlobalScope(true),
98 mTemporaryIndex(nullptr)
99{
100}
101
102TIntermTraverser::~TIntermTraverser()
103{
104}
105
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100106void TIntermTraverser::pushParentBlock(TIntermBlock *node)
Olli Etuaho56eea882015-05-18 12:41:03 +0300107{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300108 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +0300109}
110
111void TIntermTraverser::incrementParentBlockPos()
112{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300113 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +0300114}
115
116void TIntermTraverser::popParentBlock()
117{
118 ASSERT(!mParentBlockStack.empty());
119 mParentBlockStack.pop_back();
120}
121
122void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
123{
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300124 TIntermSequence emptyInsertionsAfter;
125 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
126}
127
128void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
129 const TIntermSequence &insertionsAfter)
130{
Olli Etuaho56eea882015-05-18 12:41:03 +0300131 ASSERT(!mParentBlockStack.empty());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300132 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
133 insertionsBefore, insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300134 mInsertions.push_back(insert);
135}
136
Jamie Madill1048e432016-07-23 18:51:28 -0400137void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
138{
139 TIntermSequence insertions;
140 insertions.push_back(statement);
141 insertStatementsInParentBlock(insertions);
142}
143
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300144TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300145{
146 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
147 TInfoSinkBase symbolNameOut;
148 ASSERT(mTemporaryIndex != nullptr);
149 symbolNameOut << "s" << (*mTemporaryIndex);
150 TString symbolName = symbolNameOut.c_str();
151
152 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
153 node->setInternal(true);
Olli Etuahob990b552016-10-27 12:29:17 +0100154
155 ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300156 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahob990b552016-10-27 12:29:17 +0100157 // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
158 // symbol. This might need to be done in other places as well.
Olli Etuahod4f303e2015-05-20 17:09:06 +0300159 return node;
160}
161
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300162TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
163{
164 return createTempSymbol(type, EvqTemporary);
165}
166
Olli Etuaho13389b62016-10-16 11:48:18 +0100167TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
Olli Etuaho4f1af782015-05-25 11:55:07 +0300168{
Olli Etuaho13389b62016-10-16 11:48:18 +0100169 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
170 tempDeclaration->appendDeclarator(createTempSymbol(type));
Olli Etuaho4f1af782015-05-25 11:55:07 +0300171 return tempDeclaration;
172}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300173
Olli Etuaho13389b62016-10-16 11:48:18 +0100174TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
175 TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300176{
177 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300178 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuaho13389b62016-10-16 11:48:18 +0100179 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300180 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
Olli Etuaho13389b62016-10-16 11:48:18 +0100181 tempDeclaration->appendDeclarator(tempInit);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300182 return tempDeclaration;
183}
184
Olli Etuaho13389b62016-10-16 11:48:18 +0100185TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300186{
187 return createTempInitDeclaration(initializer, EvqTemporary);
188}
189
Olli Etuahod4f303e2015-05-20 17:09:06 +0300190TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
191{
192 ASSERT(rightNode != nullptr);
193 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300194 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300195 return assignment;
196}
197
198void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
199{
200 mTemporaryIndex = temporaryIndex;
201}
202
203void TIntermTraverser::nextTemporaryIndex()
204{
205 ASSERT(mTemporaryIndex != nullptr);
206 ++(*mTemporaryIndex);
207}
208
Olli Etuaho5f579b12015-08-14 17:44:43 +0300209void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300210{
211 mFunctionMap[name] = paramSequence;
212}
213
Olli Etuaho3fc93372015-08-11 14:50:59 +0300214bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300215{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300216 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuahobd674552016-10-06 13:28:42 +0100217 return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
218 mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300219}
220
Olli Etuaho3fc93372015-08-11 14:50:59 +0300221TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300222{
223 ASSERT(isInFunctionMap(callNode));
Olli Etuahobd674552016-10-06 13:28:42 +0100224 return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300225}
226
Olli Etuaho3fc93372015-08-11 14:50:59 +0300227void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300228{
229 mInFunctionCallOutParameter = inOutParameter;
230}
231
Olli Etuaho3fc93372015-08-11 14:50:59 +0300232bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300233{
234 return mInFunctionCallOutParameter;
235}
236
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237//
238// Traverse the intermediate representation tree, and
239// call a node type specific function for each node.
240// Done recursively through the member function Traverse().
241// Node types can be skipped if their function to call is 0,
242// but their subtree will still be traversed.
243// Nodes with children can have their whole subtree skipped
244// if preVisit is turned on and the type specific function
245// returns false.
246//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247
248//
249// Traversal functions for terminals are straighforward....
250//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300251void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300253 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254}
255
Olli Etuaho27446bd2015-08-10 14:59:53 +0300256void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300258 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259}
260
Olli Etuahob6fa0432016-09-28 16:28:05 +0100261void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
262{
263 bool visit = true;
264
265 if (preVisit)
266 visit = visitSwizzle(PreVisit, node);
267
268 if (visit)
269 {
270 incrementDepth(node);
271
272 node->getOperand()->traverse(this);
273
274 decrementDepth();
275 }
276
277 if (visit && postVisit)
278 visitSwizzle(PostVisit, node);
279}
280
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281//
282// Traverse a binary node.
283//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300284void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700286 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700288 //
289 // visit the node before children if pre-visiting.
290 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300291 if (preVisit)
292 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700294 //
295 // Visit the children, in the right order.
296 //
297 if (visit)
298 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300299 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300
Olli Etuaho3fc93372015-08-11 14:50:59 +0300301 if (node->getLeft())
302 node->getLeft()->traverse(this);
303
304 if (inVisit)
305 visit = visitBinary(InVisit, node);
306
307 if (visit && node->getRight())
308 node->getRight()->traverse(this);
309
310 decrementDepth();
311 }
312
313 //
314 // Visit the node after the children, if requested and the traversal
315 // hasn't been cancelled yet.
316 //
317 if (visit && postVisit)
318 visitBinary(PostVisit, node);
319}
320
321void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
322{
323 bool visit = true;
324
325 //
326 // visit the node before children if pre-visiting.
327 //
328 if (preVisit)
329 visit = visitBinary(PreVisit, node);
330
331 //
332 // Visit the children, in the right order.
333 //
334 if (visit)
335 {
336 incrementDepth(node);
337
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300338 // Some binary operations like indexing can be inside an expression which must be an
339 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300340 bool parentOperatorRequiresLValue = operatorRequiresLValue();
341 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
342 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300343 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300344 ASSERT(!isLValueRequiredHere());
345 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300346 }
347
Olli Etuaho27446bd2015-08-10 14:59:53 +0300348 if (node->getLeft())
349 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350
Olli Etuaho27446bd2015-08-10 14:59:53 +0300351 if (inVisit)
352 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353
Olli Etuaho27446bd2015-08-10 14:59:53 +0300354 if (node->isAssignment())
355 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300356
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300357 // Index is not required to be an l-value even when the surrounding expression is required
358 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300359 TOperator op = node->getOp();
360 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
361 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300362 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300363 setOperatorRequiresLValue(false);
364 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300365 }
366
Olli Etuaho27446bd2015-08-10 14:59:53 +0300367 if (visit && node->getRight())
368 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700369
Olli Etuaho27446bd2015-08-10 14:59:53 +0300370 setOperatorRequiresLValue(parentOperatorRequiresLValue);
371 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300372
Olli Etuaho27446bd2015-08-10 14:59:53 +0300373 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700374 }
375
376 //
377 // Visit the node after the children, if requested and the traversal
378 // hasn't been cancelled yet.
379 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300380 if (visit && postVisit)
381 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382}
383
384//
385// Traverse a unary node. Same comments in binary node apply here.
386//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300387void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700389 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390
Olli Etuaho27446bd2015-08-10 14:59:53 +0300391 if (preVisit)
392 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
Olli Etuahoa26ad582015-08-04 13:51:47 +0300394 if (visit)
395 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300396 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300397
Olli Etuaho3fc93372015-08-11 14:50:59 +0300398 node->getOperand()->traverse(this);
399
400 decrementDepth();
401 }
402
403 if (visit && postVisit)
404 visitUnary(PostVisit, node);
405}
406
407void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
408{
409 bool visit = true;
410
411 if (preVisit)
412 visit = visitUnary(PreVisit, node);
413
414 if (visit)
415 {
416 incrementDepth(node);
417
Olli Etuaho27446bd2015-08-10 14:59:53 +0300418 ASSERT(!operatorRequiresLValue());
419 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300420 {
421 case EOpPostIncrement:
422 case EOpPostDecrement:
423 case EOpPreIncrement:
424 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300425 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300426 break;
427 default:
428 break;
429 }
430
Olli Etuaho27446bd2015-08-10 14:59:53 +0300431 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300432
Olli Etuaho27446bd2015-08-10 14:59:53 +0300433 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300434
Olli Etuaho27446bd2015-08-10 14:59:53 +0300435 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700436 }
437
Olli Etuaho27446bd2015-08-10 14:59:53 +0300438 if (visit && postVisit)
439 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000440}
441
Olli Etuaho336b1472016-10-05 16:37:55 +0100442// Traverse a function definition node.
443void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
444{
445 bool visit = true;
446
447 if (preVisit)
448 visit = visitFunctionDefinition(PreVisit, node);
449
450 if (visit)
451 {
452 incrementDepth(node);
453 mInGlobalScope = false;
454
455 node->getFunctionParameters()->traverse(this);
456 if (inVisit)
457 visit = visitFunctionDefinition(InVisit, node);
458 node->getBody()->traverse(this);
459
460 mInGlobalScope = true;
461 decrementDepth();
462 }
463
464 if (visit && postVisit)
465 visitFunctionDefinition(PostVisit, node);
466}
467
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100468// Traverse a block node.
469void TIntermTraverser::traverseBlock(TIntermBlock *node)
470{
471 bool visit = true;
472
473 TIntermSequence *sequence = node->getSequence();
474
475 if (preVisit)
476 visit = visitBlock(PreVisit, node);
477
478 if (visit)
479 {
480 incrementDepth(node);
481 pushParentBlock(node);
482
483 for (auto *child : *sequence)
484 {
485 child->traverse(this);
486 if (visit && inVisit)
487 {
488 if (child != sequence->back())
489 visit = visitBlock(InVisit, node);
490 }
491
492 incrementParentBlockPos();
493 }
494
495 popParentBlock();
496 decrementDepth();
497 }
498
499 if (visit && postVisit)
500 visitBlock(PostVisit, node);
501}
502
Olli Etuaho13389b62016-10-16 11:48:18 +0100503// Traverse a declaration node.
504void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
505{
506 bool visit = true;
507
508 TIntermSequence *sequence = node->getSequence();
509
510 if (preVisit)
511 visit = visitDeclaration(PreVisit, node);
512
513 if (visit)
514 {
515 incrementDepth(node);
516
517 for (auto *child : *sequence)
518 {
519 child->traverse(this);
520 if (visit && inVisit)
521 {
522 if (child != sequence->back())
523 visit = visitDeclaration(InVisit, node);
524 }
525 }
526
527 decrementDepth();
528 }
529
530 if (visit && postVisit)
531 visitDeclaration(PostVisit, node);
532}
533
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000534// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300535void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700537 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000538
Olli Etuaho27446bd2015-08-10 14:59:53 +0300539 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300540
541 if (preVisit)
542 visit = visitAggregate(PreVisit, node);
543
544 if (visit)
545 {
546 incrementDepth(node);
547
Olli Etuaho3fc93372015-08-11 14:50:59 +0300548 for (auto *child : *sequence)
549 {
550 child->traverse(this);
551 if (visit && inVisit)
552 {
553 if (child != sequence->back())
554 visit = visitAggregate(InVisit, node);
555 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300556 }
557
Olli Etuaho3fc93372015-08-11 14:50:59 +0300558 decrementDepth();
559 }
560
561 if (visit && postVisit)
562 visitAggregate(PostVisit, node);
563}
564
Olli Etuaho336b1472016-10-05 16:37:55 +0100565void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
566{
567 TIntermAggregate *params = node->getFunctionParameters();
568 ASSERT(params != nullptr);
569 ASSERT(params->getOp() == EOpParameters);
570 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
571
572 TIntermTraverser::traverseFunctionDefinition(node);
573}
574
Olli Etuaho3fc93372015-08-11 14:50:59 +0300575void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
576{
577 bool visit = true;
578
579 TIntermSequence *sequence = node->getSequence();
Olli Etuaho336b1472016-10-05 16:37:55 +0100580 if (node->getOp() == EOpPrototype)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300581 {
Olli Etuaho336b1472016-10-05 16:37:55 +0100582 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300583 }
584
Olli Etuaho27446bd2015-08-10 14:59:53 +0300585 if (preVisit)
586 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700588 if (visit)
589 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300590 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300591 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700592 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300593 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300594 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300595 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300596 // The function is not user-defined - it is likely built-in texture function.
597 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300598 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700599 }
600 }
601
Olli Etuaho27446bd2015-08-10 14:59:53 +0300602 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300603
Olli Etuahoa26ad582015-08-04 13:51:47 +0300604 if (inFunctionMap)
605 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300606 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300607 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300608 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300609 {
610 ASSERT(paramIter != params->end());
611 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300612 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300613
Olli Etuaho27446bd2015-08-10 14:59:53 +0300614 child->traverse(this);
615 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300616 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300617 if (child != sequence->back())
618 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300619 }
620
621 ++paramIter;
622 }
623
Olli Etuaho27446bd2015-08-10 14:59:53 +0300624 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300625 }
626 else
627 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300628 // Find the built-in function corresponding to this op so that we can determine the
629 // in/out qualifiers of its parameters.
630 TFunction *builtInFunc = nullptr;
631 TString opString = GetOperatorString(node->getOp());
632 if (!node->isConstructor() && !opString.empty())
633 {
634 // The return type doesn't affect the mangled name of the function, which is used
635 // to look it up from the symbol table.
636 TType dummyReturnType;
637 TFunction call(&opString, &dummyReturnType, node->getOp());
638 for (auto *child : *sequence)
639 {
640 TType *paramType = child->getAsTyped()->getTypePointer();
641 TConstParameter p(paramType);
642 call.addParameter(p);
643 }
644
645 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
646 if (sym != nullptr && sym->isFunction())
647 {
648 builtInFunc = static_cast<TFunction *>(sym);
649 ASSERT(builtInFunc->getParamCount() == sequence->size());
650 }
651 }
652
653 size_t paramIndex = 0;
654
Olli Etuaho27446bd2015-08-10 14:59:53 +0300655 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300656 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300657 TQualifier qualifier = EvqIn;
658 if (builtInFunc != nullptr)
659 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
660 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300661 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300662
Olli Etuaho27446bd2015-08-10 14:59:53 +0300663 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300664 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300665 if (child != sequence->back())
666 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300667 }
668
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300669 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300670 }
671
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300672 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300673 }
674
Olli Etuaho27446bd2015-08-10 14:59:53 +0300675 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700676 }
677
Olli Etuaho27446bd2015-08-10 14:59:53 +0300678 if (visit && postVisit)
679 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000680}
681
682//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300683// Traverse a ternary node. Same comments in binary node apply here.
684//
685void TIntermTraverser::traverseTernary(TIntermTernary *node)
686{
687 bool visit = true;
688
689 if (preVisit)
690 visit = visitTernary(PreVisit, node);
691
692 if (visit)
693 {
694 incrementDepth(node);
695 node->getCondition()->traverse(this);
696 if (node->getTrueExpression())
697 node->getTrueExpression()->traverse(this);
698 if (node->getFalseExpression())
699 node->getFalseExpression()->traverse(this);
700 decrementDepth();
701 }
702
703 if (visit && postVisit)
704 visitTernary(PostVisit, node);
705}
706
Olli Etuaho57961272016-09-14 13:57:46 +0300707// Traverse an if-else node. Same comments in binary node apply here.
708void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000709{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700710 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000711
Olli Etuaho27446bd2015-08-10 14:59:53 +0300712 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300713 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000714
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700715 if (visit)
716 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300717 incrementDepth(node);
718 node->getCondition()->traverse(this);
719 if (node->getTrueBlock())
720 node->getTrueBlock()->traverse(this);
721 if (node->getFalseBlock())
722 node->getFalseBlock()->traverse(this);
723 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700724 }
725
Olli Etuaho27446bd2015-08-10 14:59:53 +0300726 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300727 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728}
729
730//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200731// Traverse a switch node. Same comments in binary node apply here.
732//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300733void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200734{
735 bool visit = true;
736
Olli Etuaho27446bd2015-08-10 14:59:53 +0300737 if (preVisit)
738 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200739
740 if (visit)
741 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300742 incrementDepth(node);
743 node->getInit()->traverse(this);
744 if (inVisit)
745 visit = visitSwitch(InVisit, node);
746 if (visit && node->getStatementList())
747 node->getStatementList()->traverse(this);
748 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200749 }
750
Olli Etuaho27446bd2015-08-10 14:59:53 +0300751 if (visit && postVisit)
752 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200753}
754
755//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300756// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200757//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300758void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200759{
760 bool visit = true;
761
Olli Etuaho27446bd2015-08-10 14:59:53 +0300762 if (preVisit)
763 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200764
Olli Etuaho27446bd2015-08-10 14:59:53 +0300765 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100766 {
767 incrementDepth(node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300768 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100769 decrementDepth();
770 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200771
Olli Etuaho27446bd2015-08-10 14:59:53 +0300772 if (visit && postVisit)
773 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200774}
775
776//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777// Traverse a loop node. Same comments in binary node apply here.
778//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300779void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000780{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700781 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000782
Olli Etuaho27446bd2015-08-10 14:59:53 +0300783 if (preVisit)
784 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000785
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700786 if (visit)
787 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300788 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789
Olli Etuaho27446bd2015-08-10 14:59:53 +0300790 if (node->getInit())
791 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792
Olli Etuaho27446bd2015-08-10 14:59:53 +0300793 if (node->getCondition())
794 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000795
Olli Etuaho27446bd2015-08-10 14:59:53 +0300796 if (node->getBody())
797 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700798
Olli Etuaho27446bd2015-08-10 14:59:53 +0300799 if (node->getExpression())
800 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000801
Olli Etuaho27446bd2015-08-10 14:59:53 +0300802 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700803 }
804
Olli Etuaho27446bd2015-08-10 14:59:53 +0300805 if (visit && postVisit)
806 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000807}
808
809//
810// Traverse a branch node. Same comments in binary node apply here.
811//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300812void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000813{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700814 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815
Olli Etuaho27446bd2015-08-10 14:59:53 +0300816 if (preVisit)
817 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818
Olli Etuaho27446bd2015-08-10 14:59:53 +0300819 if (visit && node->getExpression())
820 {
821 incrementDepth(node);
822 node->getExpression()->traverse(this);
823 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700824 }
825
Olli Etuaho27446bd2015-08-10 14:59:53 +0300826 if (visit && postVisit)
827 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828}
829
Olli Etuaho27446bd2015-08-10 14:59:53 +0300830void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400831{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300832 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400833}