blob: e6be777a419038906d3ed71f12d3b8f420cf8f15 [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
Jamie Madill45bcc782016-11-07 13:58:48 -050011namespace sh
12{
13
Olli Etuaho27446bd2015-08-10 14:59:53 +030014void TIntermSymbol::traverse(TIntermTraverser *it)
15{
16 it->traverseSymbol(this);
17}
18
19void TIntermRaw::traverse(TIntermTraverser *it)
20{
21 it->traverseRaw(this);
22}
23
24void TIntermConstantUnion::traverse(TIntermTraverser *it)
25{
26 it->traverseConstantUnion(this);
27}
28
Olli Etuahob6fa0432016-09-28 16:28:05 +010029void TIntermSwizzle::traverse(TIntermTraverser *it)
30{
31 it->traverseSwizzle(this);
32}
33
Olli Etuaho27446bd2015-08-10 14:59:53 +030034void TIntermBinary::traverse(TIntermTraverser *it)
35{
36 it->traverseBinary(this);
37}
38
39void TIntermUnary::traverse(TIntermTraverser *it)
40{
41 it->traverseUnary(this);
42}
43
Olli Etuahod0bad2c2016-09-09 18:01:16 +030044void TIntermTernary::traverse(TIntermTraverser *it)
45{
46 it->traverseTernary(this);
47}
48
Olli Etuaho57961272016-09-14 13:57:46 +030049void TIntermIfElse::traverse(TIntermTraverser *it)
Olli Etuaho27446bd2015-08-10 14:59:53 +030050{
Olli Etuaho57961272016-09-14 13:57:46 +030051 it->traverseIfElse(this);
Olli Etuaho27446bd2015-08-10 14:59:53 +030052}
53
54void TIntermSwitch::traverse(TIntermTraverser *it)
55{
56 it->traverseSwitch(this);
57}
58
59void TIntermCase::traverse(TIntermTraverser *it)
60{
61 it->traverseCase(this);
62}
63
Olli Etuaho336b1472016-10-05 16:37:55 +010064void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
65{
66 it->traverseFunctionDefinition(this);
67}
68
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010069void TIntermBlock::traverse(TIntermTraverser *it)
70{
71 it->traverseBlock(this);
72}
73
Olli Etuaho13389b62016-10-16 11:48:18 +010074void TIntermDeclaration::traverse(TIntermTraverser *it)
75{
76 it->traverseDeclaration(this);
77}
78
Olli Etuaho27446bd2015-08-10 14:59:53 +030079void TIntermAggregate::traverse(TIntermTraverser *it)
80{
81 it->traverseAggregate(this);
82}
83
84void TIntermLoop::traverse(TIntermTraverser *it)
85{
86 it->traverseLoop(this);
87}
88
89void TIntermBranch::traverse(TIntermTraverser *it)
90{
91 it->traverseBranch(this);
92}
93
Jamie Madill03d863c2016-07-27 18:15:53 -040094TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
95 : preVisit(preVisit),
96 inVisit(inVisit),
97 postVisit(postVisit),
98 mDepth(0),
99 mMaxDepth(0),
100 mInGlobalScope(true),
101 mTemporaryIndex(nullptr)
102{
103}
104
105TIntermTraverser::~TIntermTraverser()
106{
107}
108
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100109void TIntermTraverser::pushParentBlock(TIntermBlock *node)
Olli Etuaho56eea882015-05-18 12:41:03 +0300110{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300111 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +0300112}
113
114void TIntermTraverser::incrementParentBlockPos()
115{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300116 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +0300117}
118
119void TIntermTraverser::popParentBlock()
120{
121 ASSERT(!mParentBlockStack.empty());
122 mParentBlockStack.pop_back();
123}
124
125void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
126{
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300127 TIntermSequence emptyInsertionsAfter;
128 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
129}
130
131void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
132 const TIntermSequence &insertionsAfter)
133{
Olli Etuaho56eea882015-05-18 12:41:03 +0300134 ASSERT(!mParentBlockStack.empty());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300135 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
136 insertionsBefore, insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300137 mInsertions.push_back(insert);
138}
139
Jamie Madill1048e432016-07-23 18:51:28 -0400140void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
141{
142 TIntermSequence insertions;
143 insertions.push_back(statement);
144 insertStatementsInParentBlock(insertions);
145}
146
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300147TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300148{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500149 // Each traversal uses at most one temporary variable, so the index stays the same within a
150 // single traversal.
Olli Etuahod4f303e2015-05-20 17:09:06 +0300151 TInfoSinkBase symbolNameOut;
152 ASSERT(mTemporaryIndex != nullptr);
153 symbolNameOut << "s" << (*mTemporaryIndex);
154 TString symbolName = symbolNameOut.c_str();
155
156 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
157 node->setInternal(true);
Olli Etuahob990b552016-10-27 12:29:17 +0100158
159 ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300160 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahob990b552016-10-27 12:29:17 +0100161 // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
162 // symbol. This might need to be done in other places as well.
Olli Etuahod4f303e2015-05-20 17:09:06 +0300163 return node;
164}
165
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300166TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
167{
168 return createTempSymbol(type, EvqTemporary);
169}
170
Olli Etuaho13389b62016-10-16 11:48:18 +0100171TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
Olli Etuaho4f1af782015-05-25 11:55:07 +0300172{
Olli Etuaho13389b62016-10-16 11:48:18 +0100173 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
174 tempDeclaration->appendDeclarator(createTempSymbol(type));
Olli Etuaho4f1af782015-05-25 11:55:07 +0300175 return tempDeclaration;
176}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300177
Olli Etuaho13389b62016-10-16 11:48:18 +0100178TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
179 TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300180{
181 ASSERT(initializer != nullptr);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500182 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuaho13389b62016-10-16 11:48:18 +0100183 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500184 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
Olli Etuaho13389b62016-10-16 11:48:18 +0100185 tempDeclaration->appendDeclarator(tempInit);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300186 return tempDeclaration;
187}
188
Olli Etuaho13389b62016-10-16 11:48:18 +0100189TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300190{
191 return createTempInitDeclaration(initializer, EvqTemporary);
192}
193
Olli Etuahod4f303e2015-05-20 17:09:06 +0300194TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
195{
196 ASSERT(rightNode != nullptr);
197 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300198 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300199 return assignment;
200}
201
202void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
203{
204 mTemporaryIndex = temporaryIndex;
205}
206
207void TIntermTraverser::nextTemporaryIndex()
208{
209 ASSERT(mTemporaryIndex != nullptr);
210 ++(*mTemporaryIndex);
211}
212
Olli Etuaho5f579b12015-08-14 17:44:43 +0300213void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300214{
215 mFunctionMap[name] = paramSequence;
216}
217
Olli Etuaho3fc93372015-08-11 14:50:59 +0300218bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300219{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300220 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuahobd674552016-10-06 13:28:42 +0100221 return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
222 mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300223}
224
Olli Etuaho3fc93372015-08-11 14:50:59 +0300225TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300226{
227 ASSERT(isInFunctionMap(callNode));
Olli Etuahobd674552016-10-06 13:28:42 +0100228 return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300229}
230
Olli Etuaho3fc93372015-08-11 14:50:59 +0300231void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300232{
233 mInFunctionCallOutParameter = inOutParameter;
234}
235
Olli Etuaho3fc93372015-08-11 14:50:59 +0300236bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300237{
238 return mInFunctionCallOutParameter;
239}
240
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241//
242// Traverse the intermediate representation tree, and
243// call a node type specific function for each node.
244// Done recursively through the member function Traverse().
245// Node types can be skipped if their function to call is 0,
246// but their subtree will still be traversed.
247// Nodes with children can have their whole subtree skipped
248// if preVisit is turned on and the type specific function
249// returns false.
250//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251
252//
253// Traversal functions for terminals are straighforward....
254//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300255void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300257 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258}
259
Olli Etuaho27446bd2015-08-10 14:59:53 +0300260void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300262 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263}
264
Olli Etuahob6fa0432016-09-28 16:28:05 +0100265void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
266{
267 bool visit = true;
268
269 if (preVisit)
270 visit = visitSwizzle(PreVisit, node);
271
272 if (visit)
273 {
274 incrementDepth(node);
275
276 node->getOperand()->traverse(this);
277
278 decrementDepth();
279 }
280
281 if (visit && postVisit)
282 visitSwizzle(PostVisit, node);
283}
284
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285//
286// Traverse a binary node.
287//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300288void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700290 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700292 //
293 // visit the node before children if pre-visiting.
294 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300295 if (preVisit)
296 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700298 //
299 // Visit the children, in the right order.
300 //
301 if (visit)
302 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300303 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304
Olli Etuaho3fc93372015-08-11 14:50:59 +0300305 if (node->getLeft())
306 node->getLeft()->traverse(this);
307
308 if (inVisit)
309 visit = visitBinary(InVisit, node);
310
311 if (visit && node->getRight())
312 node->getRight()->traverse(this);
313
314 decrementDepth();
315 }
316
317 //
318 // Visit the node after the children, if requested and the traversal
319 // hasn't been cancelled yet.
320 //
321 if (visit && postVisit)
322 visitBinary(PostVisit, node);
323}
324
325void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
326{
327 bool visit = true;
328
329 //
330 // visit the node before children if pre-visiting.
331 //
332 if (preVisit)
333 visit = visitBinary(PreVisit, node);
334
335 //
336 // Visit the children, in the right order.
337 //
338 if (visit)
339 {
340 incrementDepth(node);
341
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300342 // Some binary operations like indexing can be inside an expression which must be an
343 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300344 bool parentOperatorRequiresLValue = operatorRequiresLValue();
345 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
346 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300347 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300348 ASSERT(!isLValueRequiredHere());
349 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300350 }
351
Olli Etuaho27446bd2015-08-10 14:59:53 +0300352 if (node->getLeft())
353 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354
Olli Etuaho27446bd2015-08-10 14:59:53 +0300355 if (inVisit)
356 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357
Olli Etuaho27446bd2015-08-10 14:59:53 +0300358 if (node->isAssignment())
359 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300360
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300361 // Index is not required to be an l-value even when the surrounding expression is required
362 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300363 TOperator op = node->getOp();
364 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
365 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300366 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300367 setOperatorRequiresLValue(false);
368 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300369 }
370
Olli Etuaho27446bd2015-08-10 14:59:53 +0300371 if (visit && node->getRight())
372 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700373
Olli Etuaho27446bd2015-08-10 14:59:53 +0300374 setOperatorRequiresLValue(parentOperatorRequiresLValue);
375 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300376
Olli Etuaho27446bd2015-08-10 14:59:53 +0300377 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700378 }
379
380 //
381 // Visit the node after the children, if requested and the traversal
382 // hasn't been cancelled yet.
383 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300384 if (visit && postVisit)
385 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386}
387
388//
389// Traverse a unary node. Same comments in binary node apply here.
390//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300391void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700393 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394
Olli Etuaho27446bd2015-08-10 14:59:53 +0300395 if (preVisit)
396 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397
Olli Etuahoa26ad582015-08-04 13:51:47 +0300398 if (visit)
399 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300400 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300401
Olli Etuaho3fc93372015-08-11 14:50:59 +0300402 node->getOperand()->traverse(this);
403
404 decrementDepth();
405 }
406
407 if (visit && postVisit)
408 visitUnary(PostVisit, node);
409}
410
411void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
412{
413 bool visit = true;
414
415 if (preVisit)
416 visit = visitUnary(PreVisit, node);
417
418 if (visit)
419 {
420 incrementDepth(node);
421
Olli Etuaho27446bd2015-08-10 14:59:53 +0300422 ASSERT(!operatorRequiresLValue());
423 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300424 {
425 case EOpPostIncrement:
426 case EOpPostDecrement:
427 case EOpPreIncrement:
428 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300429 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300430 break;
431 default:
432 break;
433 }
434
Olli Etuaho27446bd2015-08-10 14:59:53 +0300435 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300436
Olli Etuaho27446bd2015-08-10 14:59:53 +0300437 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300438
Olli Etuaho27446bd2015-08-10 14:59:53 +0300439 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700440 }
441
Olli Etuaho27446bd2015-08-10 14:59:53 +0300442 if (visit && postVisit)
443 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000444}
445
Olli Etuaho336b1472016-10-05 16:37:55 +0100446// Traverse a function definition node.
447void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
448{
449 bool visit = true;
450
451 if (preVisit)
452 visit = visitFunctionDefinition(PreVisit, node);
453
454 if (visit)
455 {
456 incrementDepth(node);
457 mInGlobalScope = false;
458
459 node->getFunctionParameters()->traverse(this);
460 if (inVisit)
461 visit = visitFunctionDefinition(InVisit, node);
462 node->getBody()->traverse(this);
463
464 mInGlobalScope = true;
465 decrementDepth();
466 }
467
468 if (visit && postVisit)
469 visitFunctionDefinition(PostVisit, node);
470}
471
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100472// Traverse a block node.
473void TIntermTraverser::traverseBlock(TIntermBlock *node)
474{
475 bool visit = true;
476
477 TIntermSequence *sequence = node->getSequence();
478
479 if (preVisit)
480 visit = visitBlock(PreVisit, node);
481
482 if (visit)
483 {
484 incrementDepth(node);
485 pushParentBlock(node);
486
487 for (auto *child : *sequence)
488 {
489 child->traverse(this);
490 if (visit && inVisit)
491 {
492 if (child != sequence->back())
493 visit = visitBlock(InVisit, node);
494 }
495
496 incrementParentBlockPos();
497 }
498
499 popParentBlock();
500 decrementDepth();
501 }
502
503 if (visit && postVisit)
504 visitBlock(PostVisit, node);
505}
506
Olli Etuaho13389b62016-10-16 11:48:18 +0100507// Traverse a declaration node.
508void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
509{
510 bool visit = true;
511
512 TIntermSequence *sequence = node->getSequence();
513
514 if (preVisit)
515 visit = visitDeclaration(PreVisit, node);
516
517 if (visit)
518 {
519 incrementDepth(node);
520
521 for (auto *child : *sequence)
522 {
523 child->traverse(this);
524 if (visit && inVisit)
525 {
526 if (child != sequence->back())
527 visit = visitDeclaration(InVisit, node);
528 }
529 }
530
531 decrementDepth();
532 }
533
534 if (visit && postVisit)
535 visitDeclaration(PostVisit, node);
536}
537
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000538// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300539void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000540{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700541 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542
Olli Etuaho27446bd2015-08-10 14:59:53 +0300543 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300544
545 if (preVisit)
546 visit = visitAggregate(PreVisit, node);
547
548 if (visit)
549 {
550 incrementDepth(node);
551
Olli Etuaho3fc93372015-08-11 14:50:59 +0300552 for (auto *child : *sequence)
553 {
554 child->traverse(this);
555 if (visit && inVisit)
556 {
557 if (child != sequence->back())
558 visit = visitAggregate(InVisit, node);
559 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300560 }
561
Olli Etuaho3fc93372015-08-11 14:50:59 +0300562 decrementDepth();
563 }
564
565 if (visit && postVisit)
566 visitAggregate(PostVisit, node);
567}
568
Olli Etuaho336b1472016-10-05 16:37:55 +0100569void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
570{
571 TIntermAggregate *params = node->getFunctionParameters();
572 ASSERT(params != nullptr);
573 ASSERT(params->getOp() == EOpParameters);
574 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
575
576 TIntermTraverser::traverseFunctionDefinition(node);
577}
578
Olli Etuaho3fc93372015-08-11 14:50:59 +0300579void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
580{
581 bool visit = true;
582
583 TIntermSequence *sequence = node->getSequence();
Olli Etuaho336b1472016-10-05 16:37:55 +0100584 if (node->getOp() == EOpPrototype)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300585 {
Olli Etuaho336b1472016-10-05 16:37:55 +0100586 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300587 }
588
Olli Etuaho27446bd2015-08-10 14:59:53 +0300589 if (preVisit)
590 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700592 if (visit)
593 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300594 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300595 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700596 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300597 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300598 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300599 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300600 // The function is not user-defined - it is likely built-in texture function.
601 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300602 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700603 }
604 }
605
Olli Etuaho27446bd2015-08-10 14:59:53 +0300606 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300607
Olli Etuahoa26ad582015-08-04 13:51:47 +0300608 if (inFunctionMap)
609 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300610 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300611 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300612 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300613 {
614 ASSERT(paramIter != params->end());
615 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300616 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300617
Olli Etuaho27446bd2015-08-10 14:59:53 +0300618 child->traverse(this);
619 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300620 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300621 if (child != sequence->back())
622 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300623 }
624
625 ++paramIter;
626 }
627
Olli Etuaho27446bd2015-08-10 14:59:53 +0300628 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300629 }
630 else
631 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300632 // Find the built-in function corresponding to this op so that we can determine the
633 // in/out qualifiers of its parameters.
634 TFunction *builtInFunc = nullptr;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500635 TString opString = GetOperatorString(node->getOp());
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300636 if (!node->isConstructor() && !opString.empty())
637 {
638 // The return type doesn't affect the mangled name of the function, which is used
639 // to look it up from the symbol table.
640 TType dummyReturnType;
641 TFunction call(&opString, &dummyReturnType, node->getOp());
642 for (auto *child : *sequence)
643 {
644 TType *paramType = child->getAsTyped()->getTypePointer();
645 TConstParameter p(paramType);
646 call.addParameter(p);
647 }
648
649 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
650 if (sym != nullptr && sym->isFunction())
651 {
652 builtInFunc = static_cast<TFunction *>(sym);
653 ASSERT(builtInFunc->getParamCount() == sequence->size());
654 }
655 }
656
657 size_t paramIndex = 0;
658
Olli Etuaho27446bd2015-08-10 14:59:53 +0300659 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300660 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300661 TQualifier qualifier = EvqIn;
662 if (builtInFunc != nullptr)
663 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
664 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300665 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300666
Olli Etuaho27446bd2015-08-10 14:59:53 +0300667 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300668 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300669 if (child != sequence->back())
670 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300671 }
672
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300673 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300674 }
675
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300676 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300677 }
678
Olli Etuaho27446bd2015-08-10 14:59:53 +0300679 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700680 }
681
Olli Etuaho27446bd2015-08-10 14:59:53 +0300682 if (visit && postVisit)
683 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684}
685
686//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300687// Traverse a ternary node. Same comments in binary node apply here.
688//
689void TIntermTraverser::traverseTernary(TIntermTernary *node)
690{
691 bool visit = true;
692
693 if (preVisit)
694 visit = visitTernary(PreVisit, node);
695
696 if (visit)
697 {
698 incrementDepth(node);
699 node->getCondition()->traverse(this);
700 if (node->getTrueExpression())
701 node->getTrueExpression()->traverse(this);
702 if (node->getFalseExpression())
703 node->getFalseExpression()->traverse(this);
704 decrementDepth();
705 }
706
707 if (visit && postVisit)
708 visitTernary(PostVisit, node);
709}
710
Olli Etuaho57961272016-09-14 13:57:46 +0300711// Traverse an if-else node. Same comments in binary node apply here.
712void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000713{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700714 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000715
Olli Etuaho27446bd2015-08-10 14:59:53 +0300716 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300717 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000718
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700719 if (visit)
720 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300721 incrementDepth(node);
722 node->getCondition()->traverse(this);
723 if (node->getTrueBlock())
724 node->getTrueBlock()->traverse(this);
725 if (node->getFalseBlock())
726 node->getFalseBlock()->traverse(this);
727 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700728 }
729
Olli Etuaho27446bd2015-08-10 14:59:53 +0300730 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300731 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732}
733
734//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200735// Traverse a switch node. Same comments in binary node apply here.
736//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300737void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200738{
739 bool visit = true;
740
Olli Etuaho27446bd2015-08-10 14:59:53 +0300741 if (preVisit)
742 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200743
744 if (visit)
745 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300746 incrementDepth(node);
747 node->getInit()->traverse(this);
748 if (inVisit)
749 visit = visitSwitch(InVisit, node);
750 if (visit && node->getStatementList())
751 node->getStatementList()->traverse(this);
752 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200753 }
754
Olli Etuaho27446bd2015-08-10 14:59:53 +0300755 if (visit && postVisit)
756 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200757}
758
759//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300760// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200761//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300762void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200763{
764 bool visit = true;
765
Olli Etuaho27446bd2015-08-10 14:59:53 +0300766 if (preVisit)
767 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200768
Olli Etuaho27446bd2015-08-10 14:59:53 +0300769 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100770 {
771 incrementDepth(node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300772 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100773 decrementDepth();
774 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200775
Olli Etuaho27446bd2015-08-10 14:59:53 +0300776 if (visit && postVisit)
777 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200778}
779
780//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000781// Traverse a loop node. Same comments in binary node apply here.
782//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300783void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000784{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700785 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000786
Olli Etuaho27446bd2015-08-10 14:59:53 +0300787 if (preVisit)
788 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700790 if (visit)
791 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300792 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793
Olli Etuaho27446bd2015-08-10 14:59:53 +0300794 if (node->getInit())
795 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796
Olli Etuaho27446bd2015-08-10 14:59:53 +0300797 if (node->getCondition())
798 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000799
Olli Etuaho27446bd2015-08-10 14:59:53 +0300800 if (node->getBody())
801 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700802
Olli Etuaho27446bd2015-08-10 14:59:53 +0300803 if (node->getExpression())
804 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000805
Olli Etuaho27446bd2015-08-10 14:59:53 +0300806 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700807 }
808
Olli Etuaho27446bd2015-08-10 14:59:53 +0300809 if (visit && postVisit)
810 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811}
812
813//
814// Traverse a branch node. Same comments in binary node apply here.
815//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300816void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700818 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000819
Olli Etuaho27446bd2015-08-10 14:59:53 +0300820 if (preVisit)
821 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000822
Olli Etuaho27446bd2015-08-10 14:59:53 +0300823 if (visit && node->getExpression())
824 {
825 incrementDepth(node);
826 node->getExpression()->traverse(this);
827 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700828 }
829
Olli Etuaho27446bd2015-08-10 14:59:53 +0300830 if (visit && postVisit)
831 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000832}
833
Olli Etuaho27446bd2015-08-10 14:59:53 +0300834void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400835{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300836 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400837}
Jamie Madill45bcc782016-11-07 13:58:48 -0500838
839} // namespace sh