blob: 2ccf5aa4380bb094f82b15cedcf6b643948d2e85 [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 Etuahobf4e1b72016-12-09 11:30:15 +000074void TIntermInvariantDeclaration::traverse(TIntermTraverser *it)
75{
76 it->traverseInvariantDeclaration(this);
77}
78
Olli Etuaho13389b62016-10-16 11:48:18 +010079void TIntermDeclaration::traverse(TIntermTraverser *it)
80{
81 it->traverseDeclaration(this);
82}
83
Olli Etuaho16c745a2017-01-16 17:02:27 +000084void TIntermFunctionPrototype::traverse(TIntermTraverser *it)
85{
86 it->traverseFunctionPrototype(this);
87}
88
Olli Etuaho27446bd2015-08-10 14:59:53 +030089void TIntermAggregate::traverse(TIntermTraverser *it)
90{
91 it->traverseAggregate(this);
92}
93
94void TIntermLoop::traverse(TIntermTraverser *it)
95{
96 it->traverseLoop(this);
97}
98
99void TIntermBranch::traverse(TIntermTraverser *it)
100{
101 it->traverseBranch(this);
102}
103
Jamie Madill03d863c2016-07-27 18:15:53 -0400104TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
105 : preVisit(preVisit),
106 inVisit(inVisit),
107 postVisit(postVisit),
108 mDepth(0),
109 mMaxDepth(0),
110 mInGlobalScope(true),
111 mTemporaryIndex(nullptr)
112{
113}
114
115TIntermTraverser::~TIntermTraverser()
116{
117}
118
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100119void TIntermTraverser::pushParentBlock(TIntermBlock *node)
Olli Etuaho56eea882015-05-18 12:41:03 +0300120{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300121 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +0300122}
123
124void TIntermTraverser::incrementParentBlockPos()
125{
Olli Etuaho64f0be92015-06-03 17:38:34 +0300126 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +0300127}
128
129void TIntermTraverser::popParentBlock()
130{
131 ASSERT(!mParentBlockStack.empty());
132 mParentBlockStack.pop_back();
133}
134
135void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
136{
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300137 TIntermSequence emptyInsertionsAfter;
138 insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
139}
140
141void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
142 const TIntermSequence &insertionsAfter)
143{
Olli Etuaho56eea882015-05-18 12:41:03 +0300144 ASSERT(!mParentBlockStack.empty());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300145 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
146 insertionsBefore, insertionsAfter);
Olli Etuaho56eea882015-05-18 12:41:03 +0300147 mInsertions.push_back(insert);
148}
149
Jamie Madill1048e432016-07-23 18:51:28 -0400150void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
151{
152 TIntermSequence insertions;
153 insertions.push_back(statement);
154 insertStatementsInParentBlock(insertions);
155}
156
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300157TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300158{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500159 // Each traversal uses at most one temporary variable, so the index stays the same within a
160 // single traversal.
Olli Etuahod4f303e2015-05-20 17:09:06 +0300161 TInfoSinkBase symbolNameOut;
162 ASSERT(mTemporaryIndex != nullptr);
163 symbolNameOut << "s" << (*mTemporaryIndex);
164 TString symbolName = symbolNameOut.c_str();
165
166 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
167 node->setInternal(true);
Olli Etuahob990b552016-10-27 12:29:17 +0100168
169 ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300170 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahob990b552016-10-27 12:29:17 +0100171 // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
172 // symbol. This might need to be done in other places as well.
Olli Etuahod4f303e2015-05-20 17:09:06 +0300173 return node;
174}
175
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300176TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
177{
178 return createTempSymbol(type, EvqTemporary);
179}
180
Olli Etuaho13389b62016-10-16 11:48:18 +0100181TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
Olli Etuaho4f1af782015-05-25 11:55:07 +0300182{
Olli Etuaho13389b62016-10-16 11:48:18 +0100183 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
184 tempDeclaration->appendDeclarator(createTempSymbol(type));
Olli Etuaho4f1af782015-05-25 11:55:07 +0300185 return tempDeclaration;
186}
Olli Etuahod4f303e2015-05-20 17:09:06 +0300187
Olli Etuaho13389b62016-10-16 11:48:18 +0100188TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
189 TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +0300190{
191 ASSERT(initializer != nullptr);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500192 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuaho13389b62016-10-16 11:48:18 +0100193 TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500194 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
Olli Etuaho13389b62016-10-16 11:48:18 +0100195 tempDeclaration->appendDeclarator(tempInit);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300196 return tempDeclaration;
197}
198
Olli Etuaho13389b62016-10-16 11:48:18 +0100199TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300200{
201 return createTempInitDeclaration(initializer, EvqTemporary);
202}
203
Olli Etuahod4f303e2015-05-20 17:09:06 +0300204TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
205{
206 ASSERT(rightNode != nullptr);
207 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300208 TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
Olli Etuahod4f303e2015-05-20 17:09:06 +0300209 return assignment;
210}
211
212void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
213{
214 mTemporaryIndex = temporaryIndex;
215}
216
217void TIntermTraverser::nextTemporaryIndex()
218{
219 ASSERT(mTemporaryIndex != nullptr);
220 ++(*mTemporaryIndex);
221}
222
Olli Etuaho5f579b12015-08-14 17:44:43 +0300223void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300224{
225 mFunctionMap[name] = paramSequence;
226}
227
Olli Etuaho3fc93372015-08-11 14:50:59 +0300228bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
Olli Etuahoa26ad582015-08-04 13:51:47 +0300229{
Olli Etuaho59f9a642015-08-06 20:38:26 +0300230 ASSERT(callNode->getOp() == EOpFunctionCall);
Olli Etuahobd674552016-10-06 13:28:42 +0100231 return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
232 mFunctionMap.end());
Olli Etuahoa26ad582015-08-04 13:51:47 +0300233}
234
Olli Etuaho3fc93372015-08-11 14:50:59 +0300235TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300236{
237 ASSERT(isInFunctionMap(callNode));
Olli Etuahobd674552016-10-06 13:28:42 +0100238 return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()];
Olli Etuahoa26ad582015-08-04 13:51:47 +0300239}
240
Olli Etuaho3fc93372015-08-11 14:50:59 +0300241void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300242{
243 mInFunctionCallOutParameter = inOutParameter;
244}
245
Olli Etuaho3fc93372015-08-11 14:50:59 +0300246bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300247{
248 return mInFunctionCallOutParameter;
249}
250
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251//
252// Traverse the intermediate representation tree, and
253// call a node type specific function for each node.
254// Done recursively through the member function Traverse().
255// Node types can be skipped if their function to call is 0,
256// but their subtree will still be traversed.
257// Nodes with children can have their whole subtree skipped
258// if preVisit is turned on and the type specific function
259// returns false.
260//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261
262//
263// Traversal functions for terminals are straighforward....
264//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300265void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300267 visitSymbol(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268}
269
Olli Etuaho27446bd2015-08-10 14:59:53 +0300270void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300272 visitConstantUnion(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273}
274
Olli Etuahob6fa0432016-09-28 16:28:05 +0100275void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
276{
277 bool visit = true;
278
279 if (preVisit)
280 visit = visitSwizzle(PreVisit, node);
281
282 if (visit)
283 {
284 incrementDepth(node);
285
286 node->getOperand()->traverse(this);
287
288 decrementDepth();
289 }
290
291 if (visit && postVisit)
292 visitSwizzle(PostVisit, node);
293}
294
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295//
296// Traverse a binary node.
297//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300298void TIntermTraverser::traverseBinary(TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700300 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700302 //
303 // visit the node before children if pre-visiting.
304 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300305 if (preVisit)
306 visit = visitBinary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700308 //
309 // Visit the children, in the right order.
310 //
311 if (visit)
312 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300313 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314
Olli Etuaho3fc93372015-08-11 14:50:59 +0300315 if (node->getLeft())
316 node->getLeft()->traverse(this);
317
318 if (inVisit)
319 visit = visitBinary(InVisit, node);
320
321 if (visit && node->getRight())
322 node->getRight()->traverse(this);
323
324 decrementDepth();
325 }
326
327 //
328 // Visit the node after the children, if requested and the traversal
329 // hasn't been cancelled yet.
330 //
331 if (visit && postVisit)
332 visitBinary(PostVisit, node);
333}
334
335void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
336{
337 bool visit = true;
338
339 //
340 // visit the node before children if pre-visiting.
341 //
342 if (preVisit)
343 visit = visitBinary(PreVisit, node);
344
345 //
346 // Visit the children, in the right order.
347 //
348 if (visit)
349 {
350 incrementDepth(node);
351
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300352 // Some binary operations like indexing can be inside an expression which must be an
353 // l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300354 bool parentOperatorRequiresLValue = operatorRequiresLValue();
355 bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
356 if (node->isAssignment())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300357 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300358 ASSERT(!isLValueRequiredHere());
359 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300360 }
361
Olli Etuaho27446bd2015-08-10 14:59:53 +0300362 if (node->getLeft())
363 node->getLeft()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000364
Olli Etuaho27446bd2015-08-10 14:59:53 +0300365 if (inVisit)
366 visit = visitBinary(InVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367
Olli Etuaho27446bd2015-08-10 14:59:53 +0300368 if (node->isAssignment())
369 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300370
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300371 // Index is not required to be an l-value even when the surrounding expression is required
372 // to be an l-value.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300373 TOperator op = node->getOp();
374 if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
375 op == EOpIndexDirectStruct || op == EOpIndexIndirect)
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300376 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300377 setOperatorRequiresLValue(false);
378 setInFunctionCallOutParameter(false);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300379 }
380
Olli Etuaho27446bd2015-08-10 14:59:53 +0300381 if (visit && node->getRight())
382 node->getRight()->traverse(this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700383
Olli Etuaho27446bd2015-08-10 14:59:53 +0300384 setOperatorRequiresLValue(parentOperatorRequiresLValue);
385 setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
Olli Etuaho8afe1e12015-08-05 18:00:01 +0300386
Olli Etuaho27446bd2015-08-10 14:59:53 +0300387 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700388 }
389
390 //
391 // Visit the node after the children, if requested and the traversal
392 // hasn't been cancelled yet.
393 //
Olli Etuaho27446bd2015-08-10 14:59:53 +0300394 if (visit && postVisit)
395 visitBinary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396}
397
398//
399// Traverse a unary node. Same comments in binary node apply here.
400//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300401void TIntermTraverser::traverseUnary(TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000402{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700403 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404
Olli Etuaho27446bd2015-08-10 14:59:53 +0300405 if (preVisit)
406 visit = visitUnary(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407
Olli Etuahoa26ad582015-08-04 13:51:47 +0300408 if (visit)
409 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300410 incrementDepth(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300411
Olli Etuaho3fc93372015-08-11 14:50:59 +0300412 node->getOperand()->traverse(this);
413
414 decrementDepth();
415 }
416
417 if (visit && postVisit)
418 visitUnary(PostVisit, node);
419}
420
421void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
422{
423 bool visit = true;
424
425 if (preVisit)
426 visit = visitUnary(PreVisit, node);
427
428 if (visit)
429 {
430 incrementDepth(node);
431
Olli Etuaho27446bd2015-08-10 14:59:53 +0300432 ASSERT(!operatorRequiresLValue());
433 switch (node->getOp())
Olli Etuahoa26ad582015-08-04 13:51:47 +0300434 {
435 case EOpPostIncrement:
436 case EOpPostDecrement:
437 case EOpPreIncrement:
438 case EOpPreDecrement:
Olli Etuaho27446bd2015-08-10 14:59:53 +0300439 setOperatorRequiresLValue(true);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300440 break;
441 default:
442 break;
443 }
444
Olli Etuaho27446bd2015-08-10 14:59:53 +0300445 node->getOperand()->traverse(this);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300446
Olli Etuaho27446bd2015-08-10 14:59:53 +0300447 setOperatorRequiresLValue(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300448
Olli Etuaho27446bd2015-08-10 14:59:53 +0300449 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700450 }
451
Olli Etuaho27446bd2015-08-10 14:59:53 +0300452 if (visit && postVisit)
453 visitUnary(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454}
455
Olli Etuaho336b1472016-10-05 16:37:55 +0100456// Traverse a function definition node.
457void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
458{
459 bool visit = true;
460
461 if (preVisit)
462 visit = visitFunctionDefinition(PreVisit, node);
463
464 if (visit)
465 {
466 incrementDepth(node);
467 mInGlobalScope = false;
468
469 node->getFunctionParameters()->traverse(this);
470 if (inVisit)
471 visit = visitFunctionDefinition(InVisit, node);
472 node->getBody()->traverse(this);
473
474 mInGlobalScope = true;
475 decrementDepth();
476 }
477
478 if (visit && postVisit)
479 visitFunctionDefinition(PostVisit, node);
480}
481
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100482// Traverse a block node.
483void TIntermTraverser::traverseBlock(TIntermBlock *node)
484{
485 bool visit = true;
486
487 TIntermSequence *sequence = node->getSequence();
488
489 if (preVisit)
490 visit = visitBlock(PreVisit, node);
491
492 if (visit)
493 {
494 incrementDepth(node);
495 pushParentBlock(node);
496
497 for (auto *child : *sequence)
498 {
499 child->traverse(this);
500 if (visit && inVisit)
501 {
502 if (child != sequence->back())
503 visit = visitBlock(InVisit, node);
504 }
505
506 incrementParentBlockPos();
507 }
508
509 popParentBlock();
510 decrementDepth();
511 }
512
513 if (visit && postVisit)
514 visitBlock(PostVisit, node);
515}
516
Olli Etuahobf4e1b72016-12-09 11:30:15 +0000517void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node)
518{
519 bool visit = true;
520
521 if (preVisit)
522 {
523 visit = visitInvariantDeclaration(PreVisit, node);
524 }
525
526 if (visit)
527 {
528 node->getSymbol()->traverse(this);
529 if (postVisit)
530 {
531 visitInvariantDeclaration(PostVisit, node);
532 }
533 }
534}
535
Olli Etuaho13389b62016-10-16 11:48:18 +0100536// Traverse a declaration node.
537void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
538{
539 bool visit = true;
540
541 TIntermSequence *sequence = node->getSequence();
542
543 if (preVisit)
544 visit = visitDeclaration(PreVisit, node);
545
546 if (visit)
547 {
548 incrementDepth(node);
549
550 for (auto *child : *sequence)
551 {
552 child->traverse(this);
553 if (visit && inVisit)
554 {
555 if (child != sequence->back())
556 visit = visitDeclaration(InVisit, node);
557 }
558 }
559
560 decrementDepth();
561 }
562
563 if (visit && postVisit)
564 visitDeclaration(PostVisit, node);
565}
566
Olli Etuaho16c745a2017-01-16 17:02:27 +0000567void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
568{
569 bool visit = true;
570
571 TIntermSequence *sequence = node->getSequence();
572
573 if (preVisit)
574 visit = visitFunctionPrototype(PreVisit, node);
575
576 if (visit)
577 {
578 incrementDepth(node);
579
580 for (auto *child : *sequence)
581 {
582 child->traverse(this);
583 if (visit && inVisit)
584 {
585 if (child != sequence->back())
586 visit = visitFunctionPrototype(InVisit, node);
587 }
588 }
589
590 decrementDepth();
591 }
592
593 if (visit && postVisit)
594 visitFunctionPrototype(PostVisit, node);
595}
596
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000597// Traverse an aggregate node. Same comments in binary node apply here.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300598void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000599{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700600 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601
Olli Etuaho27446bd2015-08-10 14:59:53 +0300602 TIntermSequence *sequence = node->getSequence();
Olli Etuaho3fc93372015-08-11 14:50:59 +0300603
604 if (preVisit)
605 visit = visitAggregate(PreVisit, node);
606
607 if (visit)
608 {
609 incrementDepth(node);
610
Olli Etuaho3fc93372015-08-11 14:50:59 +0300611 for (auto *child : *sequence)
612 {
613 child->traverse(this);
614 if (visit && inVisit)
615 {
616 if (child != sequence->back())
617 visit = visitAggregate(InVisit, node);
618 }
Olli Etuaho3fc93372015-08-11 14:50:59 +0300619 }
620
Olli Etuaho3fc93372015-08-11 14:50:59 +0300621 decrementDepth();
622 }
623
624 if (visit && postVisit)
625 visitAggregate(PostVisit, node);
626}
627
Olli Etuaho336b1472016-10-05 16:37:55 +0100628void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
629{
630 TIntermAggregate *params = node->getFunctionParameters();
631 ASSERT(params != nullptr);
632 ASSERT(params->getOp() == EOpParameters);
633 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
634
635 TIntermTraverser::traverseFunctionDefinition(node);
636}
637
Olli Etuaho16c745a2017-01-16 17:02:27 +0000638void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
639{
640 TIntermSequence *sequence = node->getSequence();
641 addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
642
643 TIntermTraverser::traverseFunctionPrototype(node);
644}
645
Olli Etuaho3fc93372015-08-11 14:50:59 +0300646void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
647{
648 bool visit = true;
649
650 TIntermSequence *sequence = node->getSequence();
Olli Etuahoa26ad582015-08-04 13:51:47 +0300651
Olli Etuaho27446bd2015-08-10 14:59:53 +0300652 if (preVisit)
653 visit = visitAggregate(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700655 if (visit)
656 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300657 bool inFunctionMap = false;
Olli Etuaho27446bd2015-08-10 14:59:53 +0300658 if (node->getOp() == EOpFunctionCall)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700659 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300660 inFunctionMap = isInFunctionMap(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300661 if (!inFunctionMap)
Olli Etuaho64f0be92015-06-03 17:38:34 +0300662 {
Olli Etuahoa26ad582015-08-04 13:51:47 +0300663 // The function is not user-defined - it is likely built-in texture function.
664 // Assume that those do not have out parameters.
Olli Etuaho27446bd2015-08-10 14:59:53 +0300665 setInFunctionCallOutParameter(false);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700666 }
667 }
668
Olli Etuaho27446bd2015-08-10 14:59:53 +0300669 incrementDepth(node);
Olli Etuaho56eea882015-05-18 12:41:03 +0300670
Olli Etuahoa26ad582015-08-04 13:51:47 +0300671 if (inFunctionMap)
672 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300673 TIntermSequence *params = getFunctionParameters(node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300674 TIntermSequence::iterator paramIter = params->begin();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300675 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300676 {
677 ASSERT(paramIter != params->end());
678 TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
Olli Etuaho27446bd2015-08-10 14:59:53 +0300679 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300680
Olli Etuaho27446bd2015-08-10 14:59:53 +0300681 child->traverse(this);
682 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300683 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300684 if (child != sequence->back())
685 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300686 }
687
688 ++paramIter;
689 }
690
Olli Etuaho27446bd2015-08-10 14:59:53 +0300691 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300692 }
693 else
694 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300695 // Find the built-in function corresponding to this op so that we can determine the
696 // in/out qualifiers of its parameters.
697 TFunction *builtInFunc = nullptr;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500698 TString opString = GetOperatorString(node->getOp());
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300699 if (!node->isConstructor() && !opString.empty())
700 {
701 // The return type doesn't affect the mangled name of the function, which is used
702 // to look it up from the symbol table.
703 TType dummyReturnType;
704 TFunction call(&opString, &dummyReturnType, node->getOp());
705 for (auto *child : *sequence)
706 {
707 TType *paramType = child->getAsTyped()->getTypePointer();
708 TConstParameter p(paramType);
709 call.addParameter(p);
710 }
711
712 TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
713 if (sym != nullptr && sym->isFunction())
714 {
715 builtInFunc = static_cast<TFunction *>(sym);
716 ASSERT(builtInFunc->getParamCount() == sequence->size());
717 }
718 }
719
720 size_t paramIndex = 0;
721
Olli Etuaho27446bd2015-08-10 14:59:53 +0300722 for (auto *child : *sequence)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300723 {
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300724 TQualifier qualifier = EvqIn;
725 if (builtInFunc != nullptr)
726 qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
727 setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300728 child->traverse(this);
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300729
Olli Etuaho27446bd2015-08-10 14:59:53 +0300730 if (visit && inVisit)
Olli Etuahoa26ad582015-08-04 13:51:47 +0300731 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300732 if (child != sequence->back())
733 visit = visitAggregate(InVisit, node);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300734 }
735
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300736 ++paramIndex;
Olli Etuahoa26ad582015-08-04 13:51:47 +0300737 }
738
Olli Etuaho217fe6e2015-08-05 13:25:08 +0300739 setInFunctionCallOutParameter(false);
Olli Etuahoa26ad582015-08-04 13:51:47 +0300740 }
741
Olli Etuaho27446bd2015-08-10 14:59:53 +0300742 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700743 }
744
Olli Etuaho27446bd2015-08-10 14:59:53 +0300745 if (visit && postVisit)
746 visitAggregate(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000747}
748
749//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300750// Traverse a ternary node. Same comments in binary node apply here.
751//
752void TIntermTraverser::traverseTernary(TIntermTernary *node)
753{
754 bool visit = true;
755
756 if (preVisit)
757 visit = visitTernary(PreVisit, node);
758
759 if (visit)
760 {
761 incrementDepth(node);
762 node->getCondition()->traverse(this);
763 if (node->getTrueExpression())
764 node->getTrueExpression()->traverse(this);
765 if (node->getFalseExpression())
766 node->getFalseExpression()->traverse(this);
767 decrementDepth();
768 }
769
770 if (visit && postVisit)
771 visitTernary(PostVisit, node);
772}
773
Olli Etuaho57961272016-09-14 13:57:46 +0300774// Traverse an if-else node. Same comments in binary node apply here.
775void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000776{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700777 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000778
Olli Etuaho27446bd2015-08-10 14:59:53 +0300779 if (preVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300780 visit = visitIfElse(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000781
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700782 if (visit)
783 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300784 incrementDepth(node);
785 node->getCondition()->traverse(this);
786 if (node->getTrueBlock())
787 node->getTrueBlock()->traverse(this);
788 if (node->getFalseBlock())
789 node->getFalseBlock()->traverse(this);
790 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700791 }
792
Olli Etuaho27446bd2015-08-10 14:59:53 +0300793 if (visit && postVisit)
Olli Etuaho57961272016-09-14 13:57:46 +0300794 visitIfElse(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000795}
796
797//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200798// Traverse a switch node. Same comments in binary node apply here.
799//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300800void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200801{
802 bool visit = true;
803
Olli Etuaho27446bd2015-08-10 14:59:53 +0300804 if (preVisit)
805 visit = visitSwitch(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200806
807 if (visit)
808 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300809 incrementDepth(node);
810 node->getInit()->traverse(this);
811 if (inVisit)
812 visit = visitSwitch(InVisit, node);
813 if (visit && node->getStatementList())
814 node->getStatementList()->traverse(this);
815 decrementDepth();
Olli Etuahoa3a36662015-02-17 13:46:51 +0200816 }
817
Olli Etuaho27446bd2015-08-10 14:59:53 +0300818 if (visit && postVisit)
819 visitSwitch(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200820}
821
822//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300823// Traverse a case node. Same comments in binary node apply here.
Olli Etuahoa3a36662015-02-17 13:46:51 +0200824//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300825void TIntermTraverser::traverseCase(TIntermCase *node)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200826{
827 bool visit = true;
828
Olli Etuaho27446bd2015-08-10 14:59:53 +0300829 if (preVisit)
830 visit = visitCase(PreVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200831
Olli Etuaho27446bd2015-08-10 14:59:53 +0300832 if (visit && node->getCondition())
Olli Etuaho65c79db2016-10-06 17:11:28 +0100833 {
834 incrementDepth(node);
Olli Etuaho27446bd2015-08-10 14:59:53 +0300835 node->getCondition()->traverse(this);
Olli Etuaho65c79db2016-10-06 17:11:28 +0100836 decrementDepth();
837 }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200838
Olli Etuaho27446bd2015-08-10 14:59:53 +0300839 if (visit && postVisit)
840 visitCase(PostVisit, node);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200841}
842
843//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000844// Traverse a loop node. Same comments in binary node apply here.
845//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300846void TIntermTraverser::traverseLoop(TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700848 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000849
Olli Etuaho27446bd2015-08-10 14:59:53 +0300850 if (preVisit)
851 visit = visitLoop(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000852
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700853 if (visit)
854 {
Olli Etuaho27446bd2015-08-10 14:59:53 +0300855 incrementDepth(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000856
Olli Etuaho27446bd2015-08-10 14:59:53 +0300857 if (node->getInit())
858 node->getInit()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000859
Olli Etuaho27446bd2015-08-10 14:59:53 +0300860 if (node->getCondition())
861 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000862
Olli Etuaho27446bd2015-08-10 14:59:53 +0300863 if (node->getBody())
864 node->getBody()->traverse(this);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700865
Olli Etuaho27446bd2015-08-10 14:59:53 +0300866 if (node->getExpression())
867 node->getExpression()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000868
Olli Etuaho27446bd2015-08-10 14:59:53 +0300869 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700870 }
871
Olli Etuaho27446bd2015-08-10 14:59:53 +0300872 if (visit && postVisit)
873 visitLoop(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000874}
875
876//
877// Traverse a branch node. Same comments in binary node apply here.
878//
Olli Etuaho27446bd2015-08-10 14:59:53 +0300879void TIntermTraverser::traverseBranch(TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000880{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700881 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882
Olli Etuaho27446bd2015-08-10 14:59:53 +0300883 if (preVisit)
884 visit = visitBranch(PreVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885
Olli Etuaho27446bd2015-08-10 14:59:53 +0300886 if (visit && node->getExpression())
887 {
888 incrementDepth(node);
889 node->getExpression()->traverse(this);
890 decrementDepth();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700891 }
892
Olli Etuaho27446bd2015-08-10 14:59:53 +0300893 if (visit && postVisit)
894 visitBranch(PostVisit, node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000895}
896
Olli Etuaho27446bd2015-08-10 14:59:53 +0300897void TIntermTraverser::traverseRaw(TIntermRaw *node)
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400898{
Olli Etuaho27446bd2015-08-10 14:59:53 +0300899 visitRaw(node);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400900}
Jamie Madill45bcc782016-11-07 13:58:48 -0500901
902} // namespace sh