blob: d46c13ecaeae912fb604c93ea5f25b31be47b362 [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{
Olli Etuaho64f0be92015-06-03 17:38:34 +030012 mParentBlockStack.push_back(ParentBlock(node, 0));
Olli Etuaho56eea882015-05-18 12:41:03 +030013}
14
15void TIntermTraverser::incrementParentBlockPos()
16{
Olli Etuaho64f0be92015-06-03 17:38:34 +030017 ++mParentBlockStack.back().pos;
Olli Etuaho56eea882015-05-18 12:41:03 +030018}
19
20void TIntermTraverser::popParentBlock()
21{
22 ASSERT(!mParentBlockStack.empty());
23 mParentBlockStack.pop_back();
24}
25
26void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
27{
28 ASSERT(!mParentBlockStack.empty());
29 NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos, insertions);
30 mInsertions.push_back(insert);
31}
32
Olli Etuahod4f303e2015-05-20 17:09:06 +030033TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
34{
35 // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
36 TInfoSinkBase symbolNameOut;
37 ASSERT(mTemporaryIndex != nullptr);
38 symbolNameOut << "s" << (*mTemporaryIndex);
39 TString symbolName = symbolNameOut.c_str();
40
41 TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
42 node->setInternal(true);
43 node->getTypePointer()->setQualifier(EvqTemporary);
44 return node;
45}
46
Olli Etuaho4f1af782015-05-25 11:55:07 +030047TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
48{
49 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
50 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
51 return tempDeclaration;
52}
Olli Etuahod4f303e2015-05-20 17:09:06 +030053
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//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
100//
101// Traversal functions for terminals are straighforward....
102//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700103void TIntermSymbol::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700105 it->visitSymbol(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106}
107
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700108void TIntermConstantUnion::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700110 it->visitConstantUnion(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111}
112
113//
114// Traverse a binary node.
115//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700116void TIntermBinary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700118 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700120 //
121 // visit the node before children if pre-visiting.
122 //
123 if (it->preVisit)
124 visit = it->visitBinary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700126 //
127 // Visit the children, in the right order.
128 //
129 if (visit)
130 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700131 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132
Olli Etuaho64f0be92015-06-03 17:38:34 +0300133 if (mLeft)
134 mLeft->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
Olli Etuaho64f0be92015-06-03 17:38:34 +0300136 if (it->inVisit)
137 visit = it->visitBinary(InVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138
Olli Etuaho64f0be92015-06-03 17:38:34 +0300139 if (visit && mRight)
140 mRight->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700141
142 it->decrementDepth();
143 }
144
145 //
146 // Visit the node after the children, if requested and the traversal
147 // hasn't been cancelled yet.
148 //
149 if (visit && it->postVisit)
150 it->visitBinary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151}
152
153//
154// Traverse a unary node. Same comments in binary node apply here.
155//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700156void TIntermUnary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700158 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700160 if (it->preVisit)
161 visit = it->visitUnary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700163 if (visit) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700164 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700165 mOperand->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700166 it->decrementDepth();
167 }
168
169 if (visit && it->postVisit)
170 it->visitUnary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171}
172
173//
174// Traverse an aggregate node. Same comments in binary node apply here.
175//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700176void TIntermAggregate::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000177{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700178 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700180 if (it->preVisit)
181 visit = it->visitAggregate(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700183 if (visit)
184 {
Olli Etuaho56eea882015-05-18 12:41:03 +0300185 if (mOp == EOpSequence)
186 it->pushParentBlock(this);
187
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700188 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189
Olli Etuaho64f0be92015-06-03 17:38:34 +0300190 for (TIntermSequence::iterator sit = mSequence.begin();
191 sit != mSequence.end(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700192 {
Olli Etuaho64f0be92015-06-03 17:38:34 +0300193 (*sit)->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194
Olli Etuaho64f0be92015-06-03 17:38:34 +0300195 if (visit && it->inVisit)
196 {
197 if (*sit != mSequence.back())
198 visit = it->visitAggregate(InVisit, this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700199 }
Olli Etuaho64f0be92015-06-03 17:38:34 +0300200 if (mOp == EOpSequence)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700201 {
Olli Etuaho64f0be92015-06-03 17:38:34 +0300202 it->incrementParentBlockPos();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700203 }
204 }
205
206 it->decrementDepth();
Olli Etuaho56eea882015-05-18 12:41:03 +0300207
208 if (mOp == EOpSequence)
209 it->popParentBlock();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700210 }
211
212 if (visit && it->postVisit)
213 it->visitAggregate(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214}
215
216//
217// Traverse a selection node. Same comments in binary node apply here.
218//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700219void TIntermSelection::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000220{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700221 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700223 if (it->preVisit)
224 visit = it->visitSelection(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700226 if (visit)
227 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700228 it->incrementDepth(this);
Olli Etuaho64f0be92015-06-03 17:38:34 +0300229 mCondition->traverse(it);
230 if (mTrueBlock)
231 mTrueBlock->traverse(it);
232 if (mFalseBlock)
233 mFalseBlock->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700234 it->decrementDepth();
235 }
236
237 if (visit && it->postVisit)
238 it->visitSelection(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239}
240
241//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200242// Traverse a switch node. Same comments in binary node apply here.
243//
244void TIntermSwitch::traverse(TIntermTraverser *it)
245{
246 bool visit = true;
247
248 if (it->preVisit)
249 visit = it->visitSwitch(PreVisit, this);
250
251 if (visit)
252 {
253 it->incrementDepth(this);
Olli Etuaho64f0be92015-06-03 17:38:34 +0300254 mInit->traverse(it);
255 if (it->inVisit)
256 visit = it->visitSwitch(InVisit, this);
257 if (visit && mStatementList)
258 mStatementList->traverse(it);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200259 it->decrementDepth();
260 }
261
262 if (visit && it->postVisit)
263 it->visitSwitch(PostVisit, this);
264}
265
266//
267// Traverse a switch node. Same comments in binary node apply here.
268//
269void TIntermCase::traverse(TIntermTraverser *it)
270{
271 bool visit = true;
272
273 if (it->preVisit)
274 visit = it->visitCase(PreVisit, this);
275
276 if (visit && mCondition)
277 mCondition->traverse(it);
278
279 if (visit && it->postVisit)
280 it->visitCase(PostVisit, this);
281}
282
283//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284// Traverse a loop node. Same comments in binary node apply here.
285//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700286void TIntermLoop::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700288 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700290 if (it->preVisit)
291 visit = it->visitLoop(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700293 if (visit)
294 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700295 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296
Olli Etuaho64f0be92015-06-03 17:38:34 +0300297 if (mInit)
298 mInit->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
Olli Etuaho64f0be92015-06-03 17:38:34 +0300300 if (mCond)
301 mCond->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
Olli Etuaho64f0be92015-06-03 17:38:34 +0300303 if (mBody)
304 mBody->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700305
Olli Etuaho64f0be92015-06-03 17:38:34 +0300306 if (mExpr)
307 mExpr->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700309 it->decrementDepth();
310 }
311
312 if (visit && it->postVisit)
313 it->visitLoop(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314}
315
316//
317// Traverse a branch node. Same comments in binary node apply here.
318//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700319void TIntermBranch::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700321 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000322
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700323 if (it->preVisit)
324 visit = it->visitBranch(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700326 if (visit && mExpression) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700327 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700328 mExpression->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700329 it->decrementDepth();
330 }
331
332 if (visit && it->postVisit)
333 it->visitBranch(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334}
335
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400336void TIntermRaw::traverse(TIntermTraverser *it)
337{
338 it->visitRaw(this);
339}