blob: 79cb86dec8c43b621e824a5f2a8568720ae0274a [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
26void TIntermBinary::traverse(TIntermTraverser *it)
27{
28 it->traverseBinary(this);
29}
30
31void TIntermUnary::traverse(TIntermTraverser *it)
32{
33 it->traverseUnary(this);
34}
35
36void TIntermSelection::traverse(TIntermTraverser *it)
37{
38 it->traverseSelection(this);
39}
40
41void TIntermSwitch::traverse(TIntermTraverser *it)
42{
43 it->traverseSwitch(this);
44}
45
46void TIntermCase::traverse(TIntermTraverser *it)
47{
48 it->traverseCase(this);
49}
50
51void TIntermAggregate::traverse(TIntermTraverser *it)
52{
53 it->traverseAggregate(this);
54}
55
56void TIntermLoop::traverse(TIntermTraverser *it)
57{
58 it->traverseLoop(this);
59}
60
61void TIntermBranch::traverse(TIntermTraverser *it)
62{
63 it->traverseBranch(this);
64}
65
Jamie Madill03d863c2016-07-27 18:15:53 -040066TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
67 : preVisit(preVisit),
68 inVisit(inVisit),
69 postVisit(postVisit),
70 mDepth(0),
71 mMaxDepth(0),
72 mInGlobalScope(true),
73 mTemporaryIndex(nullptr)
74{
75}
76
77TIntermTraverser::~TIntermTraverser()
78{
79}
80
Olli Etuaho56eea882015-05-18 12:41:03 +030081void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
82{
Olli Etuaho64f0be92015-06-03 17:38:34 +030083 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +030084}
85
86void TIntermTraverser::incrementParentBlockPos()
87{
Olli Etuaho64f0be92015-06-03 17:38:34 +030088 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +030089}
90
91void TIntermTraverser::popParentBlock()
92{
93 ASSERT(!mParentBlockStack.empty());
94 mParentBlockStack.pop_back();
95}
96
97void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
98{
Olli Etuaho5d91dda2015-06-18 15:47:46 +030099 TIntermSequence emptyInsertionsAfter;
100 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
101}
102
103void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
104 const TIntermSequence &insertionsAfter)
105{
Olli Etuaho56eea882015-05-18 12:41:03 +0300106 ASSERT(!mParentBlockStack.empty());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300107 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
108 insertionsBefore, insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300109 mInsertions.push_back(insert);
110}
111
Jamie Madill1048e432016-07-23 18:51:28 -0400112void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
113{
114 TIntermSequence insertions;
115 insertions.push_back(statement);
116 insertStatementsInParentBlock(insertions);
117}
118
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300119TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300120{
121 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
122 TInfoSinkBase symbolNameOut;
123 ASSERT(mTemporaryIndex != nullptr);
124 symbolNameOut << "s" << (*mTemporaryIndex);
125 TString symbolName = symbolNameOut.c_str();
126
127 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
128 node->setInternal(true);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300129 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300130 return node;
131}
132
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300133TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
134{
135 return createTempSymbol(type, EvqTemporary);
136}
137
Olli Etuaho4f1af782015-05-25 11:55:07 +0300138TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
139{
140 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
141 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
142 return tempDeclaration;
143}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300144
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300145TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300146{
147 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300148 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300149 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300150 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300151 tempDeclaration->getSequence()->push_back(tempInit);
152 return tempDeclaration;
153}
154
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300155TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
156{
157 return createTempInitDeclaration(initializer, EvqTemporary);
158}
159
Olli Etuahod4f303e2015-05-20 17:09:06 +0300160TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
161{
162 ASSERT(rightNode != nullptr);
163 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300164 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300165 return assignment;
166}
167
168void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
169{
170 mTemporaryIndex = temporaryIndex;
171}
172
173void TIntermTraverser::nextTemporaryIndex()
174{
175 ASSERT(mTemporaryIndex != nullptr);
176 ++(*mTemporaryIndex);
177}
178
Olli Etuaho5f579b12015-08-14 17:44:43 +0300179void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300180{
181 mFunctionMap[name] = paramSequence;
182}
183
Olli Etuaho3fc93372015-08-11 14:50:59 +0300184bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300185{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300186 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuaho5f579b12015-08-14 17:44:43 +0300187 return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300188}
189
Olli Etuaho3fc93372015-08-11 14:50:59 +0300190TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300191{
192 ASSERT(isInFunctionMap(callNode));
Olli Etuaho5f579b12015-08-14 17:44:43 +0300193 return mFunctionMap[callNode->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300194}
195
Olli Etuaho3fc93372015-08-11 14:50:59 +0300196void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300197{
198 mInFunctionCallOutParameter = inOutParameter;
199}
200
Olli Etuaho3fc93372015-08-11 14:50:59 +0300201bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300202{
203 return mInFunctionCallOutParameter;
204}
205
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206//
207// Traverse the intermediate representation tree, and
208// call a node type specific function for each node.
209// Done recursively through the member function Traverse().
210// Node types can be skipped if their function to call is 0,
211// but their subtree will still be traversed.
212// Nodes with children can have their whole subtree skipped
213// if preVisit is turned on and the type specific function
214// returns false.
215//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216
217//
218// Traversal functions for terminals are straighforward....
219//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300220void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300222 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223}
224
Olli Etuaho27446bd2015-08-10 14:59:53 +0300225void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300227 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228}
229
230//
231// Traverse a binary node.
232//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300233void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700235 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700237 //
238 // visit the node before children if pre-visiting.
239 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300240 if (preVisit)
241 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700243 //
244 // Visit the children, in the right order.
245 //
246 if (visit)
247 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300248 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
Olli Etuaho3fc93372015-08-11 14:50:59 +0300250 if (node->getLeft())
251 node->getLeft()->traverse(this);
252
253 if (inVisit)
254 visit = visitBinary(InVisit, node);
255
256 if (visit && node->getRight())
257 node->getRight()->traverse(this);
258
259 decrementDepth();
260 }
261
262 //
263 // Visit the node after the children, if requested and the traversal
264 // hasn't been cancelled yet.
265 //
266 if (visit && postVisit)
267 visitBinary(PostVisit, node);
268}
269
270void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
271{
272 bool visit = true;
273
274 //
275 // visit the node before children if pre-visiting.
276 //
277 if (preVisit)
278 visit = visitBinary(PreVisit, node);
279
280 //
281 // Visit the children, in the right order.
282 //
283 if (visit)
284 {
285 incrementDepth(node);
286
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300287 // Some binary operations like indexing can be inside an expression which must be an
288 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300289 bool parentOperatorRequiresLValue = operatorRequiresLValue();
290 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
291 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300292 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300293 ASSERT(!isLValueRequiredHere());
294 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300295 }
296
Olli Etuaho27446bd2015-08-10 14:59:53 +0300297 if (node->getLeft())
298 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
Olli Etuaho27446bd2015-08-10 14:59:53 +0300300 if (inVisit)
301 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
Olli Etuaho27446bd2015-08-10 14:59:53 +0300303 if (node->isAssignment())
304 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300305
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300306 // Index is not required to be an l-value even when the surrounding expression is required
307 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300308 TOperator op = node->getOp();
309 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
310 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300311 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300312 setOperatorRequiresLValue(false);
313 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300314 }
315
Olli Etuaho27446bd2015-08-10 14:59:53 +0300316 if (visit && node->getRight())
317 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700318
Olli Etuaho27446bd2015-08-10 14:59:53 +0300319 setOperatorRequiresLValue(parentOperatorRequiresLValue);
320 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300321
Olli Etuaho27446bd2015-08-10 14:59:53 +0300322 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700323 }
324
325 //
326 // Visit the node after the children, if requested and the traversal
327 // hasn't been cancelled yet.
328 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300329 if (visit && postVisit)
330 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000331}
332
333//
334// Traverse a unary node. Same comments in binary node apply here.
335//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300336void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700338 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339
Olli Etuaho27446bd2015-08-10 14:59:53 +0300340 if (preVisit)
341 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000342
Olli Etuahoa26ad582015-08-04 13:51:47 +0300343 if (visit)
344 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300345 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300346
Olli Etuaho3fc93372015-08-11 14:50:59 +0300347 node->getOperand()->traverse(this);
348
349 decrementDepth();
350 }
351
352 if (visit && postVisit)
353 visitUnary(PostVisit, node);
354}
355
356void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
357{
358 bool visit = true;
359
360 if (preVisit)
361 visit = visitUnary(PreVisit, node);
362
363 if (visit)
364 {
365 incrementDepth(node);
366
Olli Etuaho27446bd2015-08-10 14:59:53 +0300367 ASSERT(!operatorRequiresLValue());
368 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300369 {
370 case EOpPostIncrement:
371 case EOpPostDecrement:
372 case EOpPreIncrement:
373 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300374 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300375 break;
376 default:
377 break;
378 }
379
Olli Etuaho27446bd2015-08-10 14:59:53 +0300380 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300381
Olli Etuaho27446bd2015-08-10 14:59:53 +0300382 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300383
Olli Etuaho27446bd2015-08-10 14:59:53 +0300384 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700385 }
386
Olli Etuaho27446bd2015-08-10 14:59:53 +0300387 if (visit && postVisit)
388 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389}
390
391//
392// Traverse an aggregate node. Same comments in binary node apply here.
393//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300394void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700396 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397
Olli Etuaho27446bd2015-08-10 14:59:53 +0300398 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300399
400 if (preVisit)
401 visit = visitAggregate(PreVisit, node);
402
403 if (visit)
404 {
405 incrementDepth(node);
406
407 if (node->getOp() == EOpSequence)
408 pushParentBlock(node);
Olli Etuahod4f4c112016-04-15 15:11:24 +0300409 else if (node->getOp() == EOpFunction)
410 mInGlobalScope = false;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300411
412 for (auto *child : *sequence)
413 {
414 child->traverse(this);
415 if (visit && inVisit)
416 {
417 if (child != sequence->back())
418 visit = visitAggregate(InVisit, node);
419 }
420
421 if (node->getOp() == EOpSequence)
422 incrementParentBlockPos();
423 }
424
425 if (node->getOp() == EOpSequence)
426 popParentBlock();
Olli Etuahod4f4c112016-04-15 15:11:24 +0300427 else if (node->getOp() == EOpFunction)
428 mInGlobalScope = true;
Olli Etuaho3fc93372015-08-11 14:50:59 +0300429
430 decrementDepth();
431 }
432
433 if (visit && postVisit)
434 visitAggregate(PostVisit, node);
435}
436
437void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
438{
439 bool visit = true;
440
441 TIntermSequence *sequence = node->getSequence();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300442 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300443 {
444 case EOpFunction:
445 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300446 TIntermAggregate *params = sequence->front()->getAsAggregate();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300447 ASSERT(params != nullptr);
448 ASSERT(params->getOp() == EOpParameters);
Olli Etuaho5f579b12015-08-14 17:44:43 +0300449 addToFunctionMap(node->getNameObj(), params->getSequence());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300450 break;
451 }
452 case EOpPrototype:
Olli Etuaho5f579b12015-08-14 17:44:43 +0300453 addToFunctionMap(node->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300454 break;
455 default:
456 break;
457 }
458
Olli Etuaho27446bd2015-08-10 14:59:53 +0300459 if (preVisit)
460 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000461
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700462 if (visit)
463 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300464 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300465 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700466 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300467 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300468 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300469 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300470 // The function is not user-defined - it is likely built-in texture function.
471 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300472 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700473 }
474 }
475
Olli Etuaho27446bd2015-08-10 14:59:53 +0300476 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300477
Olli Etuahoa26ad582015-08-04 13:51:47 +0300478 if (inFunctionMap)
479 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300480 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300481 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300482 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300483 {
484 ASSERT(paramIter != params->end());
485 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300486 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300487
Olli Etuaho27446bd2015-08-10 14:59:53 +0300488 child->traverse(this);
489 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300490 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300491 if (child != sequence->back())
492 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300493 }
494
495 ++paramIter;
496 }
497
Olli Etuaho27446bd2015-08-10 14:59:53 +0300498 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300499 }
500 else
501 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300502 if (node->getOp() == EOpSequence)
503 pushParentBlock(node);
Olli Etuahod4f4c112016-04-15 15:11:24 +0300504 else if (node->getOp() == EOpFunction)
505 mInGlobalScope = false;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300506
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300507 // Find the built-in function corresponding to this op so that we can determine the
508 // in/out qualifiers of its parameters.
509 TFunction *builtInFunc = nullptr;
510 TString opString = GetOperatorString(node->getOp());
511 if (!node->isConstructor() && !opString.empty())
512 {
513 // The return type doesn't affect the mangled name of the function, which is used
514 // to look it up from the symbol table.
515 TType dummyReturnType;
516 TFunction call(&opString, &dummyReturnType, node->getOp());
517 for (auto *child : *sequence)
518 {
519 TType *paramType = child->getAsTyped()->getTypePointer();
520 TConstParameter p(paramType);
521 call.addParameter(p);
522 }
523
524 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
525 if (sym != nullptr && sym->isFunction())
526 {
527 builtInFunc = static_cast<TFunction *>(sym);
528 ASSERT(builtInFunc->getParamCount() == sequence->size());
529 }
530 }
531
532 size_t paramIndex = 0;
533
Olli Etuaho27446bd2015-08-10 14:59:53 +0300534 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300535 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300536 TQualifier qualifier = EvqIn;
537 if (builtInFunc != nullptr)
538 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
539 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300540 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300541
Olli Etuaho27446bd2015-08-10 14:59:53 +0300542 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300543 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300544 if (child != sequence->back())
545 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300546 }
547
Olli Etuaho27446bd2015-08-10 14:59:53 +0300548 if (node->getOp() == EOpSequence)
549 incrementParentBlockPos();
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300550
551 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300552 }
553
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300554 setInFunctionCallOutParameter(false);
555
Olli Etuaho27446bd2015-08-10 14:59:53 +0300556 if (node->getOp() == EOpSequence)
557 popParentBlock();
Olli Etuahod4f4c112016-04-15 15:11:24 +0300558 else if (node->getOp() == EOpFunction)
559 mInGlobalScope = true;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300560 }
561
Olli Etuaho27446bd2015-08-10 14:59:53 +0300562 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700563 }
564
Olli Etuaho27446bd2015-08-10 14:59:53 +0300565 if (visit && postVisit)
566 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000567}
568
569//
570// Traverse a selection node. Same comments in binary node apply here.
571//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300572void TIntermTraverser::traverseSelection(TIntermSelection *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000573{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700574 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000575
Olli Etuaho27446bd2015-08-10 14:59:53 +0300576 if (preVisit)
577 visit = visitSelection(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000578
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700579 if (visit)
580 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300581 incrementDepth(node);
582 node->getCondition()->traverse(this);
583 if (node->getTrueBlock())
584 node->getTrueBlock()->traverse(this);
585 if (node->getFalseBlock())
586 node->getFalseBlock()->traverse(this);
587 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700588 }
589
Olli Etuaho27446bd2015-08-10 14:59:53 +0300590 if (visit && postVisit)
591 visitSelection(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000592}
593
594//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200595// Traverse a switch node. Same comments in binary node apply here.
596//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300597void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200598{
599 bool visit = true;
600
Olli Etuaho27446bd2015-08-10 14:59:53 +0300601 if (preVisit)
602 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200603
604 if (visit)
605 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300606 incrementDepth(node);
607 node->getInit()->traverse(this);
608 if (inVisit)
609 visit = visitSwitch(InVisit, node);
610 if (visit && node->getStatementList())
611 node->getStatementList()->traverse(this);
612 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200613 }
614
Olli Etuaho27446bd2015-08-10 14:59:53 +0300615 if (visit && postVisit)
616 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200617}
618
619//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300620// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200621//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300622void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200623{
624 bool visit = true;
625
Olli Etuaho27446bd2015-08-10 14:59:53 +0300626 if (preVisit)
627 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200628
Olli Etuaho27446bd2015-08-10 14:59:53 +0300629 if (visit && node->getCondition())
630 node->getCondition()->traverse(this);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200631
Olli Etuaho27446bd2015-08-10 14:59:53 +0300632 if (visit && postVisit)
633 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200634}
635
636//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637// Traverse a loop node. Same comments in binary node apply here.
638//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300639void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000640{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700641 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642
Olli Etuaho27446bd2015-08-10 14:59:53 +0300643 if (preVisit)
644 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700646 if (visit)
647 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300648 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649
Olli Etuaho27446bd2015-08-10 14:59:53 +0300650 if (node->getInit())
651 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652
Olli Etuaho27446bd2015-08-10 14:59:53 +0300653 if (node->getCondition())
654 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655
Olli Etuaho27446bd2015-08-10 14:59:53 +0300656 if (node->getBody())
657 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700658
Olli Etuaho27446bd2015-08-10 14:59:53 +0300659 if (node->getExpression())
660 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661
Olli Etuaho27446bd2015-08-10 14:59:53 +0300662 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700663 }
664
Olli Etuaho27446bd2015-08-10 14:59:53 +0300665 if (visit && postVisit)
666 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000667}
668
669//
670// Traverse a branch node. Same comments in binary node apply here.
671//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300672void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000673{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700674 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675
Olli Etuaho27446bd2015-08-10 14:59:53 +0300676 if (preVisit)
677 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000678
Olli Etuaho27446bd2015-08-10 14:59:53 +0300679 if (visit && node->getExpression())
680 {
681 incrementDepth(node);
682 node->getExpression()->traverse(this);
683 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700684 }
685
Olli Etuaho27446bd2015-08-10 14:59:53 +0300686 if (visit && postVisit)
687 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000688}
689
Olli Etuaho27446bd2015-08-10 14:59:53 +0300690void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400691{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300692 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400693}