blob: 9d5d870cf6bb6d4db40f8f883dff2f9c085f7f22 [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"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009
Olli Etuaho56eea882015-05-18 12:41:03 +030010void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
11{
12 if (rightToLeft)
13 mParentBlockStack.push_back(ParentBlock(node, node->getSequence()->size() - 1));
14 else
15 mParentBlockStack.push_back(ParentBlock(node, 0));
16}
17
18void TIntermTraverser::incrementParentBlockPos()
19{
20 if (rightToLeft)
21 --mParentBlockStack.back().pos;
22 else
23 ++mParentBlockStack.back().pos;
24}
25
26void TIntermTraverser::popParentBlock()
27{
28 ASSERT(!mParentBlockStack.empty());
29 mParentBlockStack.pop_back();
30}
31
32void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
33{
34 ASSERT(!mParentBlockStack.empty());
35 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos, insertions);
36 mInsertions.push_back(insert);
37}
38
Olli Etuahod4f303e2015-05-20 17:09:06 +030039TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
40{
41 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
42 TInfoSinkBase symbolNameOut;
43 ASSERT(mTemporaryIndex != nullptr);
44 symbolNameOut << "s" << (*mTemporaryIndex);
45 TString symbolName = symbolNameOut.c_str();
46
47 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
48 node->setInternal(true);
49 node->getTypePointer()->setQualifier(EvqTemporary);
50 return node;
51}
52
53
54TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
55{
56 ASSERT(initializer != nullptr);
57 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType());
58 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
59 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
60 tempInit->setLeft(tempSymbol);
61 tempInit->setRight(initializer);
62 tempInit->setType(tempSymbol->getType());
63 tempDeclaration->getSequence()->push_back(tempInit);
64 return tempDeclaration;
65}
66
67TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
68{
69 ASSERT(rightNode != nullptr);
70 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
71 TIntermBinary *assignment = new TIntermBinary(EOpAssign);
72 assignment->setLeft(tempSymbol);
73 assignment->setRight(rightNode);
74 assignment->setType(tempSymbol->getType());
75 return assignment;
76}
77
78void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
79{
80 mTemporaryIndex = temporaryIndex;
81}
82
83void TIntermTraverser::nextTemporaryIndex()
84{
85 ASSERT(mTemporaryIndex != nullptr);
86 ++(*mTemporaryIndex);
87}
88
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089//
90// Traverse the intermediate representation tree, and
91// call a node type specific function for each node.
92// Done recursively through the member function Traverse().
93// Node types can be skipped if their function to call is 0,
94// but their subtree will still be traversed.
95// Nodes with children can have their whole subtree skipped
96// if preVisit is turned on and the type specific function
97// returns false.
98//
99// preVisit, postVisit, and rightToLeft control what order
100// nodes are visited in.
101//
102
103//
104// Traversal functions for terminals are straighforward....
105//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700106void TIntermSymbol::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700108 it->visitSymbol(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109}
110
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700111void TIntermConstantUnion::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700113 it->visitConstantUnion(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114}
115
116//
117// Traverse a binary node.
118//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700119void TIntermBinary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700121 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700123 //
124 // visit the node before children if pre-visiting.
125 //
126 if (it->preVisit)
127 visit = it->visitBinary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700129 //
130 // Visit the children, in the right order.
131 //
132 if (visit)
133 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700134 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700136 if (it->rightToLeft)
137 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700138 if (mRight)
139 mRight->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700141 if (it->inVisit)
142 visit = it->visitBinary(InVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700144 if (visit && mLeft)
145 mLeft->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700146 }
147 else
148 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700149 if (mLeft)
150 mLeft->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700152 if (it->inVisit)
153 visit = it->visitBinary(InVisit, this);
154
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700155 if (visit && mRight)
156 mRight->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700157 }
158
159 it->decrementDepth();
160 }
161
162 //
163 // Visit the node after the children, if requested and the traversal
164 // hasn't been cancelled yet.
165 //
166 if (visit && it->postVisit)
167 it->visitBinary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168}
169
170//
171// Traverse a unary node. Same comments in binary node apply here.
172//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700173void TIntermUnary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700175 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700177 if (it->preVisit)
178 visit = it->visitUnary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700180 if (visit) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700181 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700182 mOperand->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700183 it->decrementDepth();
184 }
185
186 if (visit && it->postVisit)
187 it->visitUnary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188}
189
190//
191// Traverse an aggregate node. Same comments in binary node apply here.
192//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700193void TIntermAggregate::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700195 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000196
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700197 if (it->preVisit)
198 visit = it->visitAggregate(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700200 if (visit)
201 {
Olli Etuaho56eea882015-05-18 12:41:03 +0300202 if (mOp == EOpSequence)
203 it->pushParentBlock(this);
204
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700205 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700207 if (it->rightToLeft)
208 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700209 for (TIntermSequence::reverse_iterator sit = mSequence.rbegin();
210 sit != mSequence.rend(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700211 {
212 (*sit)->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700214 if (visit && it->inVisit)
215 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700216 if (*sit != mSequence.front())
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700217 visit = it->visitAggregate(InVisit, this);
218 }
Olli Etuaho56eea882015-05-18 12:41:03 +0300219 if (mOp == EOpSequence)
220 {
221 it->incrementParentBlockPos();
222 }
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700223 }
224 }
225 else
226 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700227 for (TIntermSequence::iterator sit = mSequence.begin();
228 sit != mSequence.end(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700229 {
230 (*sit)->traverse(it);
231
232 if (visit && it->inVisit)
233 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700234 if (*sit != mSequence.back())
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700235 visit = it->visitAggregate(InVisit, this);
236 }
Olli Etuaho56eea882015-05-18 12:41:03 +0300237 if (mOp == EOpSequence)
238 {
239 it->incrementParentBlockPos();
240 }
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700241 }
242 }
243
244 it->decrementDepth();
Olli Etuaho56eea882015-05-18 12:41:03 +0300245
246 if (mOp == EOpSequence)
247 it->popParentBlock();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700248 }
249
250 if (visit && it->postVisit)
251 it->visitAggregate(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252}
253
254//
255// Traverse a selection node. Same comments in binary node apply here.
256//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700257void TIntermSelection::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700259 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700261 if (it->preVisit)
262 visit = it->visitSelection(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700264 if (visit)
265 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700266 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700267 if (it->rightToLeft)
268 {
269 if (mFalseBlock)
270 mFalseBlock->traverse(it);
271 if (mTrueBlock)
272 mTrueBlock->traverse(it);
273 mCondition->traverse(it);
274 }
275 else
276 {
277 mCondition->traverse(it);
278 if (mTrueBlock)
279 mTrueBlock->traverse(it);
280 if (mFalseBlock)
281 mFalseBlock->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700282 }
283 it->decrementDepth();
284 }
285
286 if (visit && it->postVisit)
287 it->visitSelection(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288}
289
290//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200291// Traverse a switch node. Same comments in binary node apply here.
292//
293void TIntermSwitch::traverse(TIntermTraverser *it)
294{
295 bool visit = true;
296
297 if (it->preVisit)
298 visit = it->visitSwitch(PreVisit, this);
299
300 if (visit)
301 {
302 it->incrementDepth(this);
303 if (it->rightToLeft)
304 {
305 if (mStatementList)
306 mStatementList->traverse(it);
307 if (it->inVisit)
308 visit = it->visitSwitch(InVisit, this);
309 if (visit)
310 mInit->traverse(it);
311 }
312 else
313 {
314 mInit->traverse(it);
315 if (it->inVisit)
316 visit = it->visitSwitch(InVisit, this);
317 if (visit && mStatementList)
318 mStatementList->traverse(it);
319 }
320 it->decrementDepth();
321 }
322
323 if (visit && it->postVisit)
324 it->visitSwitch(PostVisit, this);
325}
326
327//
328// Traverse a switch node. Same comments in binary node apply here.
329//
330void TIntermCase::traverse(TIntermTraverser *it)
331{
332 bool visit = true;
333
334 if (it->preVisit)
335 visit = it->visitCase(PreVisit, this);
336
337 if (visit && mCondition)
338 mCondition->traverse(it);
339
340 if (visit && it->postVisit)
341 it->visitCase(PostVisit, this);
342}
343
344//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345// Traverse a loop node. Same comments in binary node apply here.
346//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700347void TIntermLoop::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700349 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700351 if (it->preVisit)
352 visit = it->visitLoop(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700354 if (visit)
355 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700356 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700358 if (it->rightToLeft)
359 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700360 if (mExpr)
361 mExpr->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700363 if (mBody)
364 mBody->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700366 if (mCond)
367 mCond->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700368
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700369 if (mInit)
370 mInit->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700371 }
372 else
373 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700374 if (mInit)
375 mInit->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700376
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700377 if (mCond)
378 mCond->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000379
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700380 if (mBody)
381 mBody->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700383 if (mExpr)
384 mExpr->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700385 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700387 it->decrementDepth();
388 }
389
390 if (visit && it->postVisit)
391 it->visitLoop(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392}
393
394//
395// Traverse a branch node. Same comments in binary node apply here.
396//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700397void TIntermBranch::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700399 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700401 if (it->preVisit)
402 visit = it->visitBranch(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700404 if (visit && mExpression) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700405 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700406 mExpression->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700407 it->decrementDepth();
408 }
409
410 if (visit && it->postVisit)
411 it->visitBranch(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412}
413
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400414void TIntermRaw::traverse(TIntermTraverser *it)
415{
416 it->visitRaw(this);
417}