blob: 7f91595d411cecf1212102894567fe9ad6c5037f [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{
149 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
150 TInfoSinkBase symbolNameOut;
151 ASSERT(mTemporaryIndex != nullptr);
152 symbolNameOut << "s" << (*mTemporaryIndex);
153 TString symbolName = symbolNameOut.c_str();
154
155 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
156 node->setInternal(true);
Olli Etuahob990b552016-10-27 12:29:17 +0100157
158 ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300159 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahob990b552016-10-27 12:29:17 +0100160 // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
161 // symbol. This might need to be done in other places as well.
Olli Etuahod4f303e2015-05-20 17:09:06 +0300162 return node;
163}
164
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300165TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
166{
167 return createTempSymbol(type, EvqTemporary);
168}
169
Olli Etuaho13389b62016-10-16 11:48:18 +0100170TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
Olli Etuaho4f1af782015-05-25 11:55:07 +0300171{
Olli Etuaho13389b62016-10-16 11:48:18 +0100172 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
173 tempDeclaration->appendDeclarator(createTempSymbol(type));
Olli Etuaho4f1af782015-05-25 11:55:07 +0300174 return tempDeclaration;
175}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300176
Olli Etuaho13389b62016-10-16 11:48:18 +0100177TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
178 TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300179{
180 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300181 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuaho13389b62016-10-16 11:48:18 +0100182 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300183 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
Olli Etuaho13389b62016-10-16 11:48:18 +0100184 tempDeclaration->appendDeclarator(tempInit);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300185 return tempDeclaration;
186}
187
Olli Etuaho13389b62016-10-16 11:48:18 +0100188TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300189{
190 return createTempInitDeclaration(initializer, EvqTemporary);
191}
192
Olli Etuahod4f303e2015-05-20 17:09:06 +0300193TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
194{
195 ASSERT(rightNode != nullptr);
196 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300197 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300198 return assignment;
199}
200
201void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
202{
203 mTemporaryIndex = temporaryIndex;
204}
205
206void TIntermTraverser::nextTemporaryIndex()
207{
208 ASSERT(mTemporaryIndex != nullptr);
209 ++(*mTemporaryIndex);
210}
211
Olli Etuaho5f579b12015-08-14 17:44:43 +0300212void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300213{
214 mFunctionMap[name] = paramSequence;
215}
216
Olli Etuaho3fc93372015-08-11 14:50:59 +0300217bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300218{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300219 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuahobd674552016-10-06 13:28:42 +0100220 return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
221 mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300222}
223
Olli Etuaho3fc93372015-08-11 14:50:59 +0300224TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300225{
226 ASSERT(isInFunctionMap(callNode));
Olli Etuahobd674552016-10-06 13:28:42 +0100227 return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300228}
229
Olli Etuaho3fc93372015-08-11 14:50:59 +0300230void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300231{
232 mInFunctionCallOutParameter = inOutParameter;
233}
234
Olli Etuaho3fc93372015-08-11 14:50:59 +0300235bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300236{
237 return mInFunctionCallOutParameter;
238}
239
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240//
241// Traverse the intermediate representation tree, and
242// call a node type specific function for each node.
243// Done recursively through the member function Traverse().
244// Node types can be skipped if their function to call is 0,
245// but their subtree will still be traversed.
246// Nodes with children can have their whole subtree skipped
247// if preVisit is turned on and the type specific function
248// returns false.
249//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250
251//
252// Traversal functions for terminals are straighforward....
253//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300254void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300256 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257}
258
Olli Etuaho27446bd2015-08-10 14:59:53 +0300259void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300261 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262}
263
Olli Etuahob6fa0432016-09-28 16:28:05 +0100264void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
265{
266 bool visit = true;
267
268 if (preVisit)
269 visit = visitSwizzle(PreVisit, node);
270
271 if (visit)
272 {
273 incrementDepth(node);
274
275 node->getOperand()->traverse(this);
276
277 decrementDepth();
278 }
279
280 if (visit && postVisit)
281 visitSwizzle(PostVisit, node);
282}
283
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284//
285// Traverse a binary node.
286//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300287void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700289 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700291 //
292 // visit the node before children if pre-visiting.
293 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300294 if (preVisit)
295 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700297 //
298 // Visit the children, in the right order.
299 //
300 if (visit)
301 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300302 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303
Olli Etuaho3fc93372015-08-11 14:50:59 +0300304 if (node->getLeft())
305 node->getLeft()->traverse(this);
306
307 if (inVisit)
308 visit = visitBinary(InVisit, node);
309
310 if (visit && node->getRight())
311 node->getRight()->traverse(this);
312
313 decrementDepth();
314 }
315
316 //
317 // Visit the node after the children, if requested and the traversal
318 // hasn't been cancelled yet.
319 //
320 if (visit && postVisit)
321 visitBinary(PostVisit, node);
322}
323
324void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
325{
326 bool visit = true;
327
328 //
329 // visit the node before children if pre-visiting.
330 //
331 if (preVisit)
332 visit = visitBinary(PreVisit, node);
333
334 //
335 // Visit the children, in the right order.
336 //
337 if (visit)
338 {
339 incrementDepth(node);
340
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300341 // Some binary operations like indexing can be inside an expression which must be an
342 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300343 bool parentOperatorRequiresLValue = operatorRequiresLValue();
344 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
345 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300346 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300347 ASSERT(!isLValueRequiredHere());
348 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300349 }
350
Olli Etuaho27446bd2015-08-10 14:59:53 +0300351 if (node->getLeft())
352 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353
Olli Etuaho27446bd2015-08-10 14:59:53 +0300354 if (inVisit)
355 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
Olli Etuaho27446bd2015-08-10 14:59:53 +0300357 if (node->isAssignment())
358 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300359
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300360 // Index is not required to be an l-value even when the surrounding expression is required
361 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300362 TOperator op = node->getOp();
363 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
364 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300365 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300366 setOperatorRequiresLValue(false);
367 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300368 }
369
Olli Etuaho27446bd2015-08-10 14:59:53 +0300370 if (visit && node->getRight())
371 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700372
Olli Etuaho27446bd2015-08-10 14:59:53 +0300373 setOperatorRequiresLValue(parentOperatorRequiresLValue);
374 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300375
Olli Etuaho27446bd2015-08-10 14:59:53 +0300376 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700377 }
378
379 //
380 // Visit the node after the children, if requested and the traversal
381 // hasn't been cancelled yet.
382 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300383 if (visit && postVisit)
384 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385}
386
387//
388// Traverse a unary node. Same comments in binary node apply here.
389//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300390void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700392 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
Olli Etuaho27446bd2015-08-10 14:59:53 +0300394 if (preVisit)
395 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396
Olli Etuahoa26ad582015-08-04 13:51:47 +0300397 if (visit)
398 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300399 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300400
Olli Etuaho3fc93372015-08-11 14:50:59 +0300401 node->getOperand()->traverse(this);
402
403 decrementDepth();
404 }
405
406 if (visit && postVisit)
407 visitUnary(PostVisit, node);
408}
409
410void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
411{
412 bool visit = true;
413
414 if (preVisit)
415 visit = visitUnary(PreVisit, node);
416
417 if (visit)
418 {
419 incrementDepth(node);
420
Olli Etuaho27446bd2015-08-10 14:59:53 +0300421 ASSERT(!operatorRequiresLValue());
422 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300423 {
424 case EOpPostIncrement:
425 case EOpPostDecrement:
426 case EOpPreIncrement:
427 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300428 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300429 break;
430 default:
431 break;
432 }
433
Olli Etuaho27446bd2015-08-10 14:59:53 +0300434 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300435
Olli Etuaho27446bd2015-08-10 14:59:53 +0300436 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300437
Olli Etuaho27446bd2015-08-10 14:59:53 +0300438 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700439 }
440
Olli Etuaho27446bd2015-08-10 14:59:53 +0300441 if (visit && postVisit)
442 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443}
444
Olli Etuaho336b1472016-10-05 16:37:55 +0100445// Traverse a function definition node.
446void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
447{
448 bool visit = true;
449
450 if (preVisit)
451 visit = visitFunctionDefinition(PreVisit, node);
452
453 if (visit)
454 {
455 incrementDepth(node);
456 mInGlobalScope = false;
457
458 node->getFunctionParameters()->traverse(this);
459 if (inVisit)
460 visit = visitFunctionDefinition(InVisit, node);
461 node->getBody()->traverse(this);
462
463 mInGlobalScope = true;
464 decrementDepth();
465 }
466
467 if (visit && postVisit)
468 visitFunctionDefinition(PostVisit, node);
469}
470
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100471// Traverse a block node.
472void TIntermTraverser::traverseBlock(TIntermBlock *node)
473{
474 bool visit = true;
475
476 TIntermSequence *sequence = node->getSequence();
477
478 if (preVisit)
479 visit = visitBlock(PreVisit, node);
480
481 if (visit)
482 {
483 incrementDepth(node);
484 pushParentBlock(node);
485
486 for (auto *child : *sequence)
487 {
488 child->traverse(this);
489 if (visit && inVisit)
490 {
491 if (child != sequence->back())
492 visit = visitBlock(InVisit, node);
493 }
494
495 incrementParentBlockPos();
496 }
497
498 popParentBlock();
499 decrementDepth();
500 }
501
502 if (visit && postVisit)
503 visitBlock(PostVisit, node);
504}
505
Olli Etuaho13389b62016-10-16 11:48:18 +0100506// Traverse a declaration node.
507void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
508{
509 bool visit = true;
510
511 TIntermSequence *sequence = node->getSequence();
512
513 if (preVisit)
514 visit = visitDeclaration(PreVisit, node);
515
516 if (visit)
517 {
518 incrementDepth(node);
519
520 for (auto *child : *sequence)
521 {
522 child->traverse(this);
523 if (visit && inVisit)
524 {
525 if (child != sequence->back())
526 visit = visitDeclaration(InVisit, node);
527 }
528 }
529
530 decrementDepth();
531 }
532
533 if (visit && postVisit)
534 visitDeclaration(PostVisit, node);
535}
536
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000537// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300538void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700540 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000541
Olli Etuaho27446bd2015-08-10 14:59:53 +0300542 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300543
544 if (preVisit)
545 visit = visitAggregate(PreVisit, node);
546
547 if (visit)
548 {
549 incrementDepth(node);
550
Olli Etuaho3fc93372015-08-11 14:50:59 +0300551 for (auto *child : *sequence)
552 {
553 child->traverse(this);
554 if (visit && inVisit)
555 {
556 if (child != sequence->back())
557 visit = visitAggregate(InVisit, node);
558 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300559 }
560
Olli Etuaho3fc93372015-08-11 14:50:59 +0300561 decrementDepth();
562 }
563
564 if (visit && postVisit)
565 visitAggregate(PostVisit, node);
566}
567
Olli Etuaho336b1472016-10-05 16:37:55 +0100568void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
569{
570 TIntermAggregate *params = node->getFunctionParameters();
571 ASSERT(params != nullptr);
572 ASSERT(params->getOp() == EOpParameters);
573 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
574
575 TIntermTraverser::traverseFunctionDefinition(node);
576}
577
Olli Etuaho3fc93372015-08-11 14:50:59 +0300578void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
579{
580 bool visit = true;
581
582 TIntermSequence *sequence = node->getSequence();
Olli Etuaho336b1472016-10-05 16:37:55 +0100583 if (node->getOp() == EOpPrototype)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300584 {
Olli Etuaho336b1472016-10-05 16:37:55 +0100585 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300586 }
587
Olli Etuaho27446bd2015-08-10 14:59:53 +0300588 if (preVisit)
589 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000590
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700591 if (visit)
592 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300593 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300594 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700595 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300596 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300597 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300598 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300599 // The function is not user-defined - it is likely built-in texture function.
600 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300601 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700602 }
603 }
604
Olli Etuaho27446bd2015-08-10 14:59:53 +0300605 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300606
Olli Etuahoa26ad582015-08-04 13:51:47 +0300607 if (inFunctionMap)
608 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300609 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300610 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300611 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300612 {
613 ASSERT(paramIter != params->end());
614 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300615 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300616
Olli Etuaho27446bd2015-08-10 14:59:53 +0300617 child->traverse(this);
618 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300619 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300620 if (child != sequence->back())
621 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300622 }
623
624 ++paramIter;
625 }
626
Olli Etuaho27446bd2015-08-10 14:59:53 +0300627 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300628 }
629 else
630 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300631 // Find the built-in function corresponding to this op so that we can determine the
632 // in/out qualifiers of its parameters.
633 TFunction *builtInFunc = nullptr;
634 TString opString = GetOperatorString(node->getOp());
635 if (!node->isConstructor() && !opString.empty())
636 {
637 // The return type doesn't affect the mangled name of the function, which is used
638 // to look it up from the symbol table.
639 TType dummyReturnType;
640 TFunction call(&opString, &dummyReturnType, node->getOp());
641 for (auto *child : *sequence)
642 {
643 TType *paramType = child->getAsTyped()->getTypePointer();
644 TConstParameter p(paramType);
645 call.addParameter(p);
646 }
647
648 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
649 if (sym != nullptr && sym->isFunction())
650 {
651 builtInFunc = static_cast<TFunction *>(sym);
652 ASSERT(builtInFunc->getParamCount() == sequence->size());
653 }
654 }
655
656 size_t paramIndex = 0;
657
Olli Etuaho27446bd2015-08-10 14:59:53 +0300658 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300659 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300660 TQualifier qualifier = EvqIn;
661 if (builtInFunc != nullptr)
662 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
663 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300664 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300665
Olli Etuaho27446bd2015-08-10 14:59:53 +0300666 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300667 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300668 if (child != sequence->back())
669 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300670 }
671
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300672 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300673 }
674
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300675 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300676 }
677
Olli Etuaho27446bd2015-08-10 14:59:53 +0300678 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700679 }
680
Olli Etuaho27446bd2015-08-10 14:59:53 +0300681 if (visit && postVisit)
682 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000683}
684
685//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300686// Traverse a ternary node. Same comments in binary node apply here.
687//
688void TIntermTraverser::traverseTernary(TIntermTernary *node)
689{
690 bool visit = true;
691
692 if (preVisit)
693 visit = visitTernary(PreVisit, node);
694
695 if (visit)
696 {
697 incrementDepth(node);
698 node->getCondition()->traverse(this);
699 if (node->getTrueExpression())
700 node->getTrueExpression()->traverse(this);
701 if (node->getFalseExpression())
702 node->getFalseExpression()->traverse(this);
703 decrementDepth();
704 }
705
706 if (visit && postVisit)
707 visitTernary(PostVisit, node);
708}
709
Olli Etuaho57961272016-09-14 13:57:46 +0300710// Traverse an if-else node. Same comments in binary node apply here.
711void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000712{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700713 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000714
Olli Etuaho27446bd2015-08-10 14:59:53 +0300715 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300716 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700718 if (visit)
719 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300720 incrementDepth(node);
721 node->getCondition()->traverse(this);
722 if (node->getTrueBlock())
723 node->getTrueBlock()->traverse(this);
724 if (node->getFalseBlock())
725 node->getFalseBlock()->traverse(this);
726 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700727 }
728
Olli Etuaho27446bd2015-08-10 14:59:53 +0300729 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300730 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000731}
732
733//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200734// Traverse a switch node. Same comments in binary node apply here.
735//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300736void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200737{
738 bool visit = true;
739
Olli Etuaho27446bd2015-08-10 14:59:53 +0300740 if (preVisit)
741 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200742
743 if (visit)
744 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300745 incrementDepth(node);
746 node->getInit()->traverse(this);
747 if (inVisit)
748 visit = visitSwitch(InVisit, node);
749 if (visit && node->getStatementList())
750 node->getStatementList()->traverse(this);
751 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200752 }
753
Olli Etuaho27446bd2015-08-10 14:59:53 +0300754 if (visit && postVisit)
755 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200756}
757
758//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300759// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200760//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300761void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200762{
763 bool visit = true;
764
Olli Etuaho27446bd2015-08-10 14:59:53 +0300765 if (preVisit)
766 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200767
Olli Etuaho27446bd2015-08-10 14:59:53 +0300768 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100769 {
770 incrementDepth(node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300771 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100772 decrementDepth();
773 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200774
Olli Etuaho27446bd2015-08-10 14:59:53 +0300775 if (visit && postVisit)
776 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200777}
778
779//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000780// Traverse a loop node. Same comments in binary node apply here.
781//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300782void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000783{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700784 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000785
Olli Etuaho27446bd2015-08-10 14:59:53 +0300786 if (preVisit)
787 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000788
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700789 if (visit)
790 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300791 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792
Olli Etuaho27446bd2015-08-10 14:59:53 +0300793 if (node->getInit())
794 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000795
Olli Etuaho27446bd2015-08-10 14:59:53 +0300796 if (node->getCondition())
797 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798
Olli Etuaho27446bd2015-08-10 14:59:53 +0300799 if (node->getBody())
800 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700801
Olli Etuaho27446bd2015-08-10 14:59:53 +0300802 if (node->getExpression())
803 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000804
Olli Etuaho27446bd2015-08-10 14:59:53 +0300805 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700806 }
807
Olli Etuaho27446bd2015-08-10 14:59:53 +0300808 if (visit && postVisit)
809 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810}
811
812//
813// Traverse a branch node. Same comments in binary node apply here.
814//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300815void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000816{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700817 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818
Olli Etuaho27446bd2015-08-10 14:59:53 +0300819 if (preVisit)
820 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000821
Olli Etuaho27446bd2015-08-10 14:59:53 +0300822 if (visit && node->getExpression())
823 {
824 incrementDepth(node);
825 node->getExpression()->traverse(this);
826 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700827 }
828
Olli Etuaho27446bd2015-08-10 14:59:53 +0300829 if (visit && postVisit)
830 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831}
832
Olli Etuaho27446bd2015-08-10 14:59:53 +0300833void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400834{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300835 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400836}
Jamie Madill45bcc782016-11-07 13:58:48 -0500837
838} // namespace sh