blob: aeaf7de5609cac976f5abacd47e18983d2d9ea1b [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 Etuahoa4aa4e32015-06-04 15:54:30 +030033TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +030034{
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);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +030043 node->getTypePointer()->setQualifier(qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +030044 return node;
45}
46
Olli Etuahoa4aa4e32015-06-04 15:54:30 +030047TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
48{
49 return createTempSymbol(type, EvqTemporary);
50}
51
Olli Etuaho4f1af782015-05-25 11:55:07 +030052TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
53{
54 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
55 tempDeclaration->getSequence()->push_back(createTempSymbol(type));
56 return tempDeclaration;
57}
Olli Etuahod4f303e2015-05-20 17:09:06 +030058
Olli Etuahoa4aa4e32015-06-04 15:54:30 +030059TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
Olli Etuahod4f303e2015-05-20 17:09:06 +030060{
61 ASSERT(initializer != nullptr);
Olli Etuahoa4aa4e32015-06-04 15:54:30 +030062 TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
Olli Etuahod4f303e2015-05-20 17:09:06 +030063 TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
64 TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
65 tempInit->setLeft(tempSymbol);
66 tempInit->setRight(initializer);
67 tempInit->setType(tempSymbol->getType());
68 tempDeclaration->getSequence()->push_back(tempInit);
69 return tempDeclaration;
70}
71
Olli Etuahoa4aa4e32015-06-04 15:54:30 +030072TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
73{
74 return createTempInitDeclaration(initializer, EvqTemporary);
75}
76
Olli Etuahod4f303e2015-05-20 17:09:06 +030077TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
78{
79 ASSERT(rightNode != nullptr);
80 TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
81 TIntermBinary *assignment = new TIntermBinary(EOpAssign);
82 assignment->setLeft(tempSymbol);
83 assignment->setRight(rightNode);
84 assignment->setType(tempSymbol->getType());
85 return assignment;
86}
87
88void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
89{
90 mTemporaryIndex = temporaryIndex;
91}
92
93void TIntermTraverser::nextTemporaryIndex()
94{
95 ASSERT(mTemporaryIndex != nullptr);
96 ++(*mTemporaryIndex);
97}
98
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099//
100// Traverse the intermediate representation tree, and
101// call a node type specific function for each node.
102// Done recursively through the member function Traverse().
103// Node types can be skipped if their function to call is 0,
104// but their subtree will still be traversed.
105// Nodes with children can have their whole subtree skipped
106// if preVisit is turned on and the type specific function
107// returns false.
108//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109
110//
111// Traversal functions for terminals are straighforward....
112//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700113void TIntermSymbol::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700115 it->visitSymbol(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116}
117
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700118void TIntermConstantUnion::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700120 it->visitConstantUnion(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121}
122
123//
124// Traverse a binary node.
125//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700126void TIntermBinary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700128 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700130 //
131 // visit the node before children if pre-visiting.
132 //
133 if (it->preVisit)
134 visit = it->visitBinary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700136 //
137 // Visit the children, in the right order.
138 //
139 if (visit)
140 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700141 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142
Olli Etuaho64f0be92015-06-03 17:38:34 +0300143 if (mLeft)
144 mLeft->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145
Olli Etuaho64f0be92015-06-03 17:38:34 +0300146 if (it->inVisit)
147 visit = it->visitBinary(InVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148
Olli Etuaho64f0be92015-06-03 17:38:34 +0300149 if (visit && mRight)
150 mRight->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700151
152 it->decrementDepth();
153 }
154
155 //
156 // Visit the node after the children, if requested and the traversal
157 // hasn't been cancelled yet.
158 //
159 if (visit && it->postVisit)
160 it->visitBinary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161}
162
163//
164// Traverse a unary node. Same comments in binary node apply here.
165//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700166void TIntermUnary::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700168 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700170 if (it->preVisit)
171 visit = it->visitUnary(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700173 if (visit) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700174 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700175 mOperand->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700176 it->decrementDepth();
177 }
178
179 if (visit && it->postVisit)
180 it->visitUnary(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181}
182
183//
184// Traverse an aggregate node. Same comments in binary node apply here.
185//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700186void TIntermAggregate::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700188 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700190 if (it->preVisit)
191 visit = it->visitAggregate(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700193 if (visit)
194 {
Olli Etuaho56eea882015-05-18 12:41:03 +0300195 if (mOp == EOpSequence)
196 it->pushParentBlock(this);
197
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700198 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199
Olli Etuaho64f0be92015-06-03 17:38:34 +0300200 for (TIntermSequence::iterator sit = mSequence.begin();
201 sit != mSequence.end(); sit++)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700202 {
Olli Etuaho64f0be92015-06-03 17:38:34 +0300203 (*sit)->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204
Olli Etuaho64f0be92015-06-03 17:38:34 +0300205 if (visit && it->inVisit)
206 {
207 if (*sit != mSequence.back())
208 visit = it->visitAggregate(InVisit, this);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700209 }
Olli Etuaho64f0be92015-06-03 17:38:34 +0300210 if (mOp == EOpSequence)
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700211 {
Olli Etuaho64f0be92015-06-03 17:38:34 +0300212 it->incrementParentBlockPos();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700213 }
214 }
215
216 it->decrementDepth();
Olli Etuaho56eea882015-05-18 12:41:03 +0300217
218 if (mOp == EOpSequence)
219 it->popParentBlock();
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700220 }
221
222 if (visit && it->postVisit)
223 it->visitAggregate(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224}
225
226//
227// Traverse a selection node. Same comments in binary node apply here.
228//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700229void TIntermSelection::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700231 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700233 if (it->preVisit)
234 visit = it->visitSelection(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700236 if (visit)
237 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700238 it->incrementDepth(this);
Olli Etuaho64f0be92015-06-03 17:38:34 +0300239 mCondition->traverse(it);
240 if (mTrueBlock)
241 mTrueBlock->traverse(it);
242 if (mFalseBlock)
243 mFalseBlock->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700244 it->decrementDepth();
245 }
246
247 if (visit && it->postVisit)
248 it->visitSelection(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249}
250
251//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200252// Traverse a switch node. Same comments in binary node apply here.
253//
254void TIntermSwitch::traverse(TIntermTraverser *it)
255{
256 bool visit = true;
257
258 if (it->preVisit)
259 visit = it->visitSwitch(PreVisit, this);
260
261 if (visit)
262 {
263 it->incrementDepth(this);
Olli Etuaho64f0be92015-06-03 17:38:34 +0300264 mInit->traverse(it);
265 if (it->inVisit)
266 visit = it->visitSwitch(InVisit, this);
267 if (visit && mStatementList)
268 mStatementList->traverse(it);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200269 it->decrementDepth();
270 }
271
272 if (visit && it->postVisit)
273 it->visitSwitch(PostVisit, this);
274}
275
276//
277// Traverse a switch node. Same comments in binary node apply here.
278//
279void TIntermCase::traverse(TIntermTraverser *it)
280{
281 bool visit = true;
282
283 if (it->preVisit)
284 visit = it->visitCase(PreVisit, this);
285
286 if (visit && mCondition)
287 mCondition->traverse(it);
288
289 if (visit && it->postVisit)
290 it->visitCase(PostVisit, this);
291}
292
293//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294// Traverse a loop node. Same comments in binary node apply here.
295//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700296void TIntermLoop::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700298 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700300 if (it->preVisit)
301 visit = it->visitLoop(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700303 if (visit)
304 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700305 it->incrementDepth(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306
Olli Etuaho64f0be92015-06-03 17:38:34 +0300307 if (mInit)
308 mInit->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309
Olli Etuaho64f0be92015-06-03 17:38:34 +0300310 if (mCond)
311 mCond->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312
Olli Etuaho64f0be92015-06-03 17:38:34 +0300313 if (mBody)
314 mBody->traverse(it);
Zhenyao Mo6cb95f32013-10-03 17:01:52 -0700315
Olli Etuaho64f0be92015-06-03 17:38:34 +0300316 if (mExpr)
317 mExpr->traverse(it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700319 it->decrementDepth();
320 }
321
322 if (visit && it->postVisit)
323 it->visitLoop(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000324}
325
326//
327// Traverse a branch node. Same comments in binary node apply here.
328//
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700329void TIntermBranch::traverse(TIntermTraverser *it)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330{
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700331 bool visit = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700333 if (it->preVisit)
334 visit = it->visitBranch(PreVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700336 if (visit && mExpression) {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700337 it->incrementDepth(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700338 mExpression->traverse(it);
Zhenyao Moe88dcaf2013-10-03 16:55:19 -0700339 it->decrementDepth();
340 }
341
342 if (visit && it->postVisit)
343 it->visitBranch(PostVisit, this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000344}
345
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400346void TIntermRaw::traverse(TIntermTraverser *it)
347{
348 it->visitRaw(this);
349}