blob: add49976fbe663d78912d1952f75ba50a6a60433 [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
Olli Etuaho4f1af782015-05-25 11:55:07 +030053TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
54{
55 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
56 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
57 return tempDeclaration;
58}
Olli Etuahod4f303e2015-05-20 17:09:06 +030059
60TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
61{
62 ASSERT(initializer != nullptr);
63 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType());
64 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
65 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
66 tempInit->setLeft(tempSymbol);
67 tempInit->setRight(initializer);
68 tempInit->setType(tempSymbol->getType());
69 tempDeclaration->getSequence()->push_back(tempInit);
70 return tempDeclaration;
71}
72
73TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
74{
75 ASSERT(rightNode != nullptr);
76 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
77 TIntermBinary *assignment = new TIntermBinary(EOpAssign);
78 assignment->setLeft(tempSymbol);
79 assignment->setRight(rightNode);
80 assignment->setType(tempSymbol->getType());
81 return assignment;
82}
83
84void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
85{
86 mTemporaryIndex = temporaryIndex;
87}
88
89void TIntermTraverser::nextTemporaryIndex()
90{
91 ASSERT(mTemporaryIndex != nullptr);
92 ++(*mTemporaryIndex);
93}
94
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095//
96// Traverse the intermediate representation tree, and
97// call a node type specific function for each node.
98// Done recursively through the member function Traverse().
99// Node types can be skipped if their function to call is 0,
100// but their subtree will still be traversed.
101// Nodes with children can have their whole subtree skipped
102// if preVisit is turned on and the type specific function
103// returns false.
104//
105// preVisit, postVisit, and rightToLeft control what order
106// nodes are visited in.
107//
108
109//
110// Traversal functions for terminals are straighforward....
111//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700112void TIntermSymbol::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700114 it->visitSymbol(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115}
116
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700117void TIntermConstantUnion::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700119 it->visitConstantUnion(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120}
121
122//
123// Traverse a binary node.
124//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700125void TIntermBinary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700127 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700129 //
130 // visit the node before children if pre-visiting.
131 //
132 if (it->preVisit)
133 visit = it->visitBinary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700135 //
136 // Visit the children, in the right order.
137 //
138 if (visit)
139 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700140 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700142 if (it->rightToLeft)
143 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700144 if (mRight)
145 mRight->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700147 if (it->inVisit)
148 visit = it->visitBinary(InVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700150 if (visit && mLeft)
151 mLeft->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700152 }
153 else
154 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700155 if (mLeft)
156 mLeft->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700158 if (it->inVisit)
159 visit = it->visitBinary(InVisit, this);
160
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700161 if (visit && mRight)
162 mRight->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700163 }
164
165 it->decrementDepth();
166 }
167
168 //
169 // Visit the node after the children, if requested and the traversal
170 // hasn't been cancelled yet.
171 //
172 if (visit && it->postVisit)
173 it->visitBinary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174}
175
176//
177// Traverse a unary node. Same comments in binary node apply here.
178//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700179void TIntermUnary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700181 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700183 if (it->preVisit)
184 visit = it->visitUnary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700186 if (visit) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700187 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700188 mOperand->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700189 it->decrementDepth();
190 }
191
192 if (visit && it->postVisit)
193 it->visitUnary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194}
195
196//
197// Traverse an aggregate node. Same comments in binary node apply here.
198//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700199void TIntermAggregate::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700201 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700203 if (it->preVisit)
204 visit = it->visitAggregate(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700206 if (visit)
207 {
Olli Etuaho56eea882015-05-18 12:41:03 +0300208 if (mOp == EOpSequence)
209 it->pushParentBlock(this);
210
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700211 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700213 if (it->rightToLeft)
214 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700215 for (TIntermSequence::reverse_iterator sit = mSequence.rbegin();
216 sit != mSequence.rend(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700217 {
218 (*sit)->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700220 if (visit && it->inVisit)
221 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700222 if (*sit != mSequence.front())
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700223 visit = it->visitAggregate(InVisit, this);
224 }
Olli Etuaho56eea882015-05-18 12:41:03 +0300225 if (mOp == EOpSequence)
226 {
227 it->incrementParentBlockPos();
228 }
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700229 }
230 }
231 else
232 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700233 for (TIntermSequence::iterator sit = mSequence.begin();
234 sit != mSequence.end(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700235 {
236 (*sit)->traverse(it);
237
238 if (visit && it->inVisit)
239 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700240 if (*sit != mSequence.back())
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700241 visit = it->visitAggregate(InVisit, this);
242 }
Olli Etuaho56eea882015-05-18 12:41:03 +0300243 if (mOp == EOpSequence)
244 {
245 it->incrementParentBlockPos();
246 }
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700247 }
248 }
249
250 it->decrementDepth();
Olli Etuaho56eea882015-05-18 12:41:03 +0300251
252 if (mOp == EOpSequence)
253 it->popParentBlock();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700254 }
255
256 if (visit && it->postVisit)
257 it->visitAggregate(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258}
259
260//
261// Traverse a selection node. Same comments in binary node apply here.
262//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700263void TIntermSelection::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700265 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700267 if (it->preVisit)
268 visit = it->visitSelection(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700270 if (visit)
271 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700272 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700273 if (it->rightToLeft)
274 {
275 if (mFalseBlock)
276 mFalseBlock->traverse(it);
277 if (mTrueBlock)
278 mTrueBlock->traverse(it);
279 mCondition->traverse(it);
280 }
281 else
282 {
283 mCondition->traverse(it);
284 if (mTrueBlock)
285 mTrueBlock->traverse(it);
286 if (mFalseBlock)
287 mFalseBlock->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700288 }
289 it->decrementDepth();
290 }
291
292 if (visit && it->postVisit)
293 it->visitSelection(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294}
295
296//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200297// Traverse a switch node. Same comments in binary node apply here.
298//
299void TIntermSwitch::traverse(TIntermTraverser *it)
300{
301 bool visit = true;
302
303 if (it->preVisit)
304 visit = it->visitSwitch(PreVisit, this);
305
306 if (visit)
307 {
308 it->incrementDepth(this);
309 if (it->rightToLeft)
310 {
311 if (mStatementList)
312 mStatementList->traverse(it);
313 if (it->inVisit)
314 visit = it->visitSwitch(InVisit, this);
315 if (visit)
316 mInit->traverse(it);
317 }
318 else
319 {
320 mInit->traverse(it);
321 if (it->inVisit)
322 visit = it->visitSwitch(InVisit, this);
323 if (visit && mStatementList)
324 mStatementList->traverse(it);
325 }
326 it->decrementDepth();
327 }
328
329 if (visit && it->postVisit)
330 it->visitSwitch(PostVisit, this);
331}
332
333//
334// Traverse a switch node. Same comments in binary node apply here.
335//
336void TIntermCase::traverse(TIntermTraverser *it)
337{
338 bool visit = true;
339
340 if (it->preVisit)
341 visit = it->visitCase(PreVisit, this);
342
343 if (visit && mCondition)
344 mCondition->traverse(it);
345
346 if (visit && it->postVisit)
347 it->visitCase(PostVisit, this);
348}
349
350//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351// Traverse a loop node. Same comments in binary node apply here.
352//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700353void TIntermLoop::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700355 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700357 if (it->preVisit)
358 visit = it->visitLoop(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700360 if (visit)
361 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700362 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700364 if (it->rightToLeft)
365 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700366 if (mExpr)
367 mExpr->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700369 if (mBody)
370 mBody->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000371
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700372 if (mCond)
373 mCond->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700374
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700375 if (mInit)
376 mInit->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700377 }
378 else
379 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700380 if (mInit)
381 mInit->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700382
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700383 if (mCond)
384 mCond->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700386 if (mBody)
387 mBody->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700389 if (mExpr)
390 mExpr->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700391 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700393 it->decrementDepth();
394 }
395
396 if (visit && it->postVisit)
397 it->visitLoop(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398}
399
400//
401// Traverse a branch node. Same comments in binary node apply here.
402//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700403void TIntermBranch::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700405 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000406
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700407 if (it->preVisit)
408 visit = it->visitBranch(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700410 if (visit && mExpression) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700411 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700412 mExpression->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700413 it->decrementDepth();
414 }
415
416 if (visit && it->postVisit)
417 it->visitBranch(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000418}
419
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400420void TIntermRaw::traverse(TIntermTraverser *it)
421{
422 it->visitRaw(this);
423}