Line data Source code
1 : //
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 :
7 : #include "compiler/translator/IntermNode.h"
8 : #include "compiler/translator/InfoSink.h"
9 : #include "compiler/translator/SymbolTable.h"
10 :
11 : namespace sh
12 : {
13 :
14 0 : void TIntermSymbol::traverse(TIntermTraverser *it)
15 : {
16 0 : it->traverseSymbol(this);
17 0 : }
18 :
19 0 : void TIntermRaw::traverse(TIntermTraverser *it)
20 : {
21 0 : it->traverseRaw(this);
22 0 : }
23 :
24 0 : void TIntermConstantUnion::traverse(TIntermTraverser *it)
25 : {
26 0 : it->traverseConstantUnion(this);
27 0 : }
28 :
29 0 : void TIntermSwizzle::traverse(TIntermTraverser *it)
30 : {
31 0 : it->traverseSwizzle(this);
32 0 : }
33 :
34 0 : void TIntermBinary::traverse(TIntermTraverser *it)
35 : {
36 0 : it->traverseBinary(this);
37 0 : }
38 :
39 0 : void TIntermUnary::traverse(TIntermTraverser *it)
40 : {
41 0 : it->traverseUnary(this);
42 0 : }
43 :
44 0 : void TIntermTernary::traverse(TIntermTraverser *it)
45 : {
46 0 : it->traverseTernary(this);
47 0 : }
48 :
49 0 : void TIntermIfElse::traverse(TIntermTraverser *it)
50 : {
51 0 : it->traverseIfElse(this);
52 0 : }
53 :
54 0 : void TIntermSwitch::traverse(TIntermTraverser *it)
55 : {
56 0 : it->traverseSwitch(this);
57 0 : }
58 :
59 0 : void TIntermCase::traverse(TIntermTraverser *it)
60 : {
61 0 : it->traverseCase(this);
62 0 : }
63 :
64 0 : void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
65 : {
66 0 : it->traverseFunctionDefinition(this);
67 0 : }
68 :
69 0 : void TIntermBlock::traverse(TIntermTraverser *it)
70 : {
71 0 : it->traverseBlock(this);
72 0 : }
73 :
74 0 : void TIntermDeclaration::traverse(TIntermTraverser *it)
75 : {
76 0 : it->traverseDeclaration(this);
77 0 : }
78 :
79 0 : void TIntermAggregate::traverse(TIntermTraverser *it)
80 : {
81 0 : it->traverseAggregate(this);
82 0 : }
83 :
84 0 : void TIntermLoop::traverse(TIntermTraverser *it)
85 : {
86 0 : it->traverseLoop(this);
87 0 : }
88 :
89 0 : void TIntermBranch::traverse(TIntermTraverser *it)
90 : {
91 0 : it->traverseBranch(this);
92 0 : }
93 :
94 0 : TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
95 : : preVisit(preVisit),
96 : inVisit(inVisit),
97 : postVisit(postVisit),
98 : mDepth(0),
99 : mMaxDepth(0),
100 : mInGlobalScope(true),
101 0 : mTemporaryIndex(nullptr)
102 : {
103 0 : }
104 :
105 0 : TIntermTraverser::~TIntermTraverser()
106 : {
107 0 : }
108 :
109 0 : void TIntermTraverser::pushParentBlock(TIntermBlock *node)
110 : {
111 0 : mParentBlockStack.push_back(ParentBlock(node, 0));
112 0 : }
113 :
114 0 : void TIntermTraverser::incrementParentBlockPos()
115 : {
116 0 : ++mParentBlockStack.back().pos;
117 0 : }
118 :
119 0 : void TIntermTraverser::popParentBlock()
120 : {
121 0 : ASSERT(!mParentBlockStack.empty());
122 0 : mParentBlockStack.pop_back();
123 0 : }
124 :
125 0 : void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
126 : {
127 0 : TIntermSequence emptyInsertionsAfter;
128 0 : insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
129 0 : }
130 :
131 0 : void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
132 : const TIntermSequence &insertionsAfter)
133 : {
134 0 : ASSERT(!mParentBlockStack.empty());
135 0 : NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
136 0 : insertionsBefore, insertionsAfter);
137 0 : mInsertions.push_back(insert);
138 0 : }
139 :
140 0 : void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
141 : {
142 0 : TIntermSequence insertions;
143 0 : insertions.push_back(statement);
144 0 : insertStatementsInParentBlock(insertions);
145 0 : }
146 :
147 0 : TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
148 : {
149 : // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
150 0 : TInfoSinkBase symbolNameOut;
151 0 : ASSERT(mTemporaryIndex != nullptr);
152 0 : symbolNameOut << "s" << (*mTemporaryIndex);
153 0 : TString symbolName = symbolNameOut.c_str();
154 :
155 0 : TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
156 0 : node->setInternal(true);
157 :
158 0 : ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
159 0 : node->getTypePointer()->setQualifier(qualifier);
160 : // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
161 : // symbol. This might need to be done in other places as well.
162 0 : return node;
163 : }
164 :
165 0 : TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
166 : {
167 0 : return createTempSymbol(type, EvqTemporary);
168 : }
169 :
170 0 : TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
171 : {
172 0 : TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
173 0 : tempDeclaration->appendDeclarator(createTempSymbol(type));
174 0 : return tempDeclaration;
175 : }
176 :
177 0 : TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
178 : TQualifier qualifier)
179 : {
180 0 : ASSERT(initializer != nullptr);
181 0 : TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
182 0 : TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
183 0 : TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
184 0 : tempDeclaration->appendDeclarator(tempInit);
185 0 : return tempDeclaration;
186 : }
187 :
188 0 : TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
189 : {
190 0 : return createTempInitDeclaration(initializer, EvqTemporary);
191 : }
192 :
193 0 : TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
194 : {
195 0 : ASSERT(rightNode != nullptr);
196 0 : TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
197 0 : TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
198 0 : return assignment;
199 : }
200 :
201 0 : void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
202 : {
203 0 : mTemporaryIndex = temporaryIndex;
204 0 : }
205 :
206 0 : void TIntermTraverser::nextTemporaryIndex()
207 : {
208 0 : ASSERT(mTemporaryIndex != nullptr);
209 0 : ++(*mTemporaryIndex);
210 0 : }
211 :
212 0 : void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
213 : {
214 0 : mFunctionMap[name] = paramSequence;
215 0 : }
216 :
217 0 : bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
218 : {
219 0 : ASSERT(callNode->getOp() == EOpFunctionCall);
220 0 : return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
221 0 : mFunctionMap.end());
222 : }
223 :
224 0 : TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
225 : {
226 0 : ASSERT(isInFunctionMap(callNode));
227 0 : return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()];
228 : }
229 :
230 0 : void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
231 : {
232 0 : mInFunctionCallOutParameter = inOutParameter;
233 0 : }
234 :
235 0 : bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
236 : {
237 0 : return mInFunctionCallOutParameter;
238 : }
239 :
240 : //
241 : // Traverse the intermediate representation tree, and
242 : // call a node type specific function for each node.
243 : // Done recursively through the member function Traverse().
244 : // Node types can be skipped if their function to call is 0,
245 : // but their subtree will still be traversed.
246 : // Nodes with children can have their whole subtree skipped
247 : // if preVisit is turned on and the type specific function
248 : // returns false.
249 : //
250 :
251 : //
252 : // Traversal functions for terminals are straighforward....
253 : //
254 0 : void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
255 : {
256 0 : visitSymbol(node);
257 0 : }
258 :
259 0 : void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
260 : {
261 0 : visitConstantUnion(node);
262 0 : }
263 :
264 0 : void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
265 : {
266 0 : bool visit = true;
267 :
268 0 : if (preVisit)
269 0 : visit = visitSwizzle(PreVisit, node);
270 :
271 0 : if (visit)
272 : {
273 0 : incrementDepth(node);
274 :
275 0 : node->getOperand()->traverse(this);
276 :
277 0 : decrementDepth();
278 : }
279 :
280 0 : if (visit && postVisit)
281 0 : visitSwizzle(PostVisit, node);
282 0 : }
283 :
284 : //
285 : // Traverse a binary node.
286 : //
287 0 : void TIntermTraverser::traverseBinary(TIntermBinary *node)
288 : {
289 0 : bool visit = true;
290 :
291 : //
292 : // visit the node before children if pre-visiting.
293 : //
294 0 : if (preVisit)
295 0 : visit = visitBinary(PreVisit, node);
296 :
297 : //
298 : // Visit the children, in the right order.
299 : //
300 0 : if (visit)
301 : {
302 0 : incrementDepth(node);
303 :
304 0 : if (node->getLeft())
305 0 : node->getLeft()->traverse(this);
306 :
307 0 : if (inVisit)
308 0 : visit = visitBinary(InVisit, node);
309 :
310 0 : if (visit && node->getRight())
311 0 : node->getRight()->traverse(this);
312 :
313 0 : decrementDepth();
314 : }
315 :
316 : //
317 : // Visit the node after the children, if requested and the traversal
318 : // hasn't been cancelled yet.
319 : //
320 0 : if (visit && postVisit)
321 0 : visitBinary(PostVisit, node);
322 0 : }
323 :
324 0 : void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
325 : {
326 0 : bool visit = true;
327 :
328 : //
329 : // visit the node before children if pre-visiting.
330 : //
331 0 : if (preVisit)
332 0 : visit = visitBinary(PreVisit, node);
333 :
334 : //
335 : // Visit the children, in the right order.
336 : //
337 0 : if (visit)
338 : {
339 0 : incrementDepth(node);
340 :
341 : // Some binary operations like indexing can be inside an expression which must be an
342 : // l-value.
343 0 : bool parentOperatorRequiresLValue = operatorRequiresLValue();
344 0 : bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
345 0 : if (node->isAssignment())
346 : {
347 0 : ASSERT(!isLValueRequiredHere());
348 0 : setOperatorRequiresLValue(true);
349 : }
350 :
351 0 : if (node->getLeft())
352 0 : node->getLeft()->traverse(this);
353 :
354 0 : if (inVisit)
355 0 : visit = visitBinary(InVisit, node);
356 :
357 0 : if (node->isAssignment())
358 0 : setOperatorRequiresLValue(false);
359 :
360 : // Index is not required to be an l-value even when the surrounding expression is required
361 : // to be an l-value.
362 0 : TOperator op = node->getOp();
363 0 : if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
364 0 : op == EOpIndexDirectStruct || op == EOpIndexIndirect)
365 : {
366 0 : setOperatorRequiresLValue(false);
367 0 : setInFunctionCallOutParameter(false);
368 : }
369 :
370 0 : if (visit && node->getRight())
371 0 : node->getRight()->traverse(this);
372 :
373 0 : setOperatorRequiresLValue(parentOperatorRequiresLValue);
374 0 : setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
375 :
376 0 : decrementDepth();
377 : }
378 :
379 : //
380 : // Visit the node after the children, if requested and the traversal
381 : // hasn't been cancelled yet.
382 : //
383 0 : if (visit && postVisit)
384 0 : visitBinary(PostVisit, node);
385 0 : }
386 :
387 : //
388 : // Traverse a unary node. Same comments in binary node apply here.
389 : //
390 0 : void TIntermTraverser::traverseUnary(TIntermUnary *node)
391 : {
392 0 : bool visit = true;
393 :
394 0 : if (preVisit)
395 0 : visit = visitUnary(PreVisit, node);
396 :
397 0 : if (visit)
398 : {
399 0 : incrementDepth(node);
400 :
401 0 : node->getOperand()->traverse(this);
402 :
403 0 : decrementDepth();
404 : }
405 :
406 0 : if (visit && postVisit)
407 0 : visitUnary(PostVisit, node);
408 0 : }
409 :
410 0 : void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
411 : {
412 0 : bool visit = true;
413 :
414 0 : if (preVisit)
415 0 : visit = visitUnary(PreVisit, node);
416 :
417 0 : if (visit)
418 : {
419 0 : incrementDepth(node);
420 :
421 0 : ASSERT(!operatorRequiresLValue());
422 0 : switch (node->getOp())
423 : {
424 : case EOpPostIncrement:
425 : case EOpPostDecrement:
426 : case EOpPreIncrement:
427 : case EOpPreDecrement:
428 0 : setOperatorRequiresLValue(true);
429 0 : break;
430 : default:
431 0 : break;
432 : }
433 :
434 0 : node->getOperand()->traverse(this);
435 :
436 0 : setOperatorRequiresLValue(false);
437 :
438 0 : decrementDepth();
439 : }
440 :
441 0 : if (visit && postVisit)
442 0 : visitUnary(PostVisit, node);
443 0 : }
444 :
445 : // Traverse a function definition node.
446 0 : void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
447 : {
448 0 : bool visit = true;
449 :
450 0 : if (preVisit)
451 0 : visit = visitFunctionDefinition(PreVisit, node);
452 :
453 0 : if (visit)
454 : {
455 0 : incrementDepth(node);
456 0 : mInGlobalScope = false;
457 :
458 0 : node->getFunctionParameters()->traverse(this);
459 0 : if (inVisit)
460 0 : visit = visitFunctionDefinition(InVisit, node);
461 0 : node->getBody()->traverse(this);
462 :
463 0 : mInGlobalScope = true;
464 0 : decrementDepth();
465 : }
466 :
467 0 : if (visit && postVisit)
468 0 : visitFunctionDefinition(PostVisit, node);
469 0 : }
470 :
471 : // Traverse a block node.
472 0 : void TIntermTraverser::traverseBlock(TIntermBlock *node)
473 : {
474 0 : bool visit = true;
475 :
476 0 : TIntermSequence *sequence = node->getSequence();
477 :
478 0 : if (preVisit)
479 0 : visit = visitBlock(PreVisit, node);
480 :
481 0 : if (visit)
482 : {
483 0 : incrementDepth(node);
484 0 : pushParentBlock(node);
485 :
486 0 : for (auto *child : *sequence)
487 : {
488 0 : child->traverse(this);
489 0 : if (visit && inVisit)
490 : {
491 0 : if (child != sequence->back())
492 0 : visit = visitBlock(InVisit, node);
493 : }
494 :
495 0 : incrementParentBlockPos();
496 : }
497 :
498 0 : popParentBlock();
499 0 : decrementDepth();
500 : }
501 :
502 0 : if (visit && postVisit)
503 0 : visitBlock(PostVisit, node);
504 0 : }
505 :
506 : // Traverse a declaration node.
507 0 : void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
508 : {
509 0 : bool visit = true;
510 :
511 0 : TIntermSequence *sequence = node->getSequence();
512 :
513 0 : if (preVisit)
514 0 : visit = visitDeclaration(PreVisit, node);
515 :
516 0 : if (visit)
517 : {
518 0 : incrementDepth(node);
519 :
520 0 : for (auto *child : *sequence)
521 : {
522 0 : child->traverse(this);
523 0 : if (visit && inVisit)
524 : {
525 0 : if (child != sequence->back())
526 0 : visit = visitDeclaration(InVisit, node);
527 : }
528 : }
529 :
530 0 : decrementDepth();
531 : }
532 :
533 0 : if (visit && postVisit)
534 0 : visitDeclaration(PostVisit, node);
535 0 : }
536 :
537 : // Traverse an aggregate node. Same comments in binary node apply here.
538 0 : void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
539 : {
540 0 : bool visit = true;
541 :
542 0 : TIntermSequence *sequence = node->getSequence();
543 :
544 0 : if (preVisit)
545 0 : visit = visitAggregate(PreVisit, node);
546 :
547 0 : if (visit)
548 : {
549 0 : incrementDepth(node);
550 :
551 0 : for (auto *child : *sequence)
552 : {
553 0 : child->traverse(this);
554 0 : if (visit && inVisit)
555 : {
556 0 : if (child != sequence->back())
557 0 : visit = visitAggregate(InVisit, node);
558 : }
559 : }
560 :
561 0 : decrementDepth();
562 : }
563 :
564 0 : if (visit && postVisit)
565 0 : visitAggregate(PostVisit, node);
566 0 : }
567 :
568 0 : void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
569 : {
570 0 : TIntermAggregate *params = node->getFunctionParameters();
571 0 : ASSERT(params != nullptr);
572 0 : ASSERT(params->getOp() == EOpParameters);
573 0 : addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
574 :
575 0 : TIntermTraverser::traverseFunctionDefinition(node);
576 0 : }
577 :
578 0 : void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
579 : {
580 0 : bool visit = true;
581 :
582 0 : TIntermSequence *sequence = node->getSequence();
583 0 : if (node->getOp() == EOpPrototype)
584 : {
585 0 : addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
586 : }
587 :
588 0 : if (preVisit)
589 0 : visit = visitAggregate(PreVisit, node);
590 :
591 0 : if (visit)
592 : {
593 0 : bool inFunctionMap = false;
594 0 : if (node->getOp() == EOpFunctionCall)
595 : {
596 0 : inFunctionMap = isInFunctionMap(node);
597 0 : if (!inFunctionMap)
598 : {
599 : // The function is not user-defined - it is likely built-in texture function.
600 : // Assume that those do not have out parameters.
601 0 : setInFunctionCallOutParameter(false);
602 : }
603 : }
604 :
605 0 : incrementDepth(node);
606 :
607 0 : if (inFunctionMap)
608 : {
609 0 : TIntermSequence *params = getFunctionParameters(node);
610 0 : TIntermSequence::iterator paramIter = params->begin();
611 0 : for (auto *child : *sequence)
612 : {
613 0 : ASSERT(paramIter != params->end());
614 0 : TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
615 0 : setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
616 :
617 0 : child->traverse(this);
618 0 : if (visit && inVisit)
619 : {
620 0 : if (child != sequence->back())
621 0 : visit = visitAggregate(InVisit, node);
622 : }
623 :
624 0 : ++paramIter;
625 : }
626 :
627 0 : setInFunctionCallOutParameter(false);
628 : }
629 : else
630 : {
631 : // Find the built-in function corresponding to this op so that we can determine the
632 : // in/out qualifiers of its parameters.
633 0 : TFunction *builtInFunc = nullptr;
634 0 : TString opString = GetOperatorString(node->getOp());
635 0 : if (!node->isConstructor() && !opString.empty())
636 : {
637 : // The return type doesn't affect the mangled name of the function, which is used
638 : // to look it up from the symbol table.
639 0 : TType dummyReturnType;
640 0 : TFunction call(&opString, &dummyReturnType, node->getOp());
641 0 : for (auto *child : *sequence)
642 : {
643 0 : TType *paramType = child->getAsTyped()->getTypePointer();
644 0 : TConstParameter p(paramType);
645 0 : call.addParameter(p);
646 : }
647 :
648 0 : TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
649 0 : if (sym != nullptr && sym->isFunction())
650 : {
651 0 : builtInFunc = static_cast<TFunction *>(sym);
652 0 : ASSERT(builtInFunc->getParamCount() == sequence->size());
653 : }
654 : }
655 :
656 0 : size_t paramIndex = 0;
657 :
658 0 : for (auto *child : *sequence)
659 : {
660 0 : TQualifier qualifier = EvqIn;
661 0 : if (builtInFunc != nullptr)
662 0 : qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
663 0 : setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
664 0 : child->traverse(this);
665 :
666 0 : if (visit && inVisit)
667 : {
668 0 : if (child != sequence->back())
669 0 : visit = visitAggregate(InVisit, node);
670 : }
671 :
672 0 : ++paramIndex;
673 : }
674 :
675 0 : setInFunctionCallOutParameter(false);
676 : }
677 :
678 0 : decrementDepth();
679 : }
680 :
681 0 : if (visit && postVisit)
682 0 : visitAggregate(PostVisit, node);
683 0 : }
684 :
685 : //
686 : // Traverse a ternary node. Same comments in binary node apply here.
687 : //
688 0 : void TIntermTraverser::traverseTernary(TIntermTernary *node)
689 : {
690 0 : bool visit = true;
691 :
692 0 : if (preVisit)
693 0 : visit = visitTernary(PreVisit, node);
694 :
695 0 : if (visit)
696 : {
697 0 : incrementDepth(node);
698 0 : node->getCondition()->traverse(this);
699 0 : if (node->getTrueExpression())
700 0 : node->getTrueExpression()->traverse(this);
701 0 : if (node->getFalseExpression())
702 0 : node->getFalseExpression()->traverse(this);
703 0 : decrementDepth();
704 : }
705 :
706 0 : if (visit && postVisit)
707 0 : visitTernary(PostVisit, node);
708 0 : }
709 :
710 : // Traverse an if-else node. Same comments in binary node apply here.
711 0 : void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
712 : {
713 0 : bool visit = true;
714 :
715 0 : if (preVisit)
716 0 : visit = visitIfElse(PreVisit, node);
717 :
718 0 : if (visit)
719 : {
720 0 : incrementDepth(node);
721 0 : node->getCondition()->traverse(this);
722 0 : if (node->getTrueBlock())
723 0 : node->getTrueBlock()->traverse(this);
724 0 : if (node->getFalseBlock())
725 0 : node->getFalseBlock()->traverse(this);
726 0 : decrementDepth();
727 : }
728 :
729 0 : if (visit && postVisit)
730 0 : visitIfElse(PostVisit, node);
731 0 : }
732 :
733 : //
734 : // Traverse a switch node. Same comments in binary node apply here.
735 : //
736 0 : void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
737 : {
738 0 : bool visit = true;
739 :
740 0 : if (preVisit)
741 0 : visit = visitSwitch(PreVisit, node);
742 :
743 0 : if (visit)
744 : {
745 0 : incrementDepth(node);
746 0 : node->getInit()->traverse(this);
747 0 : if (inVisit)
748 0 : visit = visitSwitch(InVisit, node);
749 0 : if (visit && node->getStatementList())
750 0 : node->getStatementList()->traverse(this);
751 0 : decrementDepth();
752 : }
753 :
754 0 : if (visit && postVisit)
755 0 : visitSwitch(PostVisit, node);
756 0 : }
757 :
758 : //
759 : // Traverse a case node. Same comments in binary node apply here.
760 : //
761 0 : void TIntermTraverser::traverseCase(TIntermCase *node)
762 : {
763 0 : bool visit = true;
764 :
765 0 : if (preVisit)
766 0 : visit = visitCase(PreVisit, node);
767 :
768 0 : if (visit && node->getCondition())
769 : {
770 0 : incrementDepth(node);
771 0 : node->getCondition()->traverse(this);
772 0 : decrementDepth();
773 : }
774 :
775 0 : if (visit && postVisit)
776 0 : visitCase(PostVisit, node);
777 0 : }
778 :
779 : //
780 : // Traverse a loop node. Same comments in binary node apply here.
781 : //
782 0 : void TIntermTraverser::traverseLoop(TIntermLoop *node)
783 : {
784 0 : bool visit = true;
785 :
786 0 : if (preVisit)
787 0 : visit = visitLoop(PreVisit, node);
788 :
789 0 : if (visit)
790 : {
791 0 : incrementDepth(node);
792 :
793 0 : if (node->getInit())
794 0 : node->getInit()->traverse(this);
795 :
796 0 : if (node->getCondition())
797 0 : node->getCondition()->traverse(this);
798 :
799 0 : if (node->getBody())
800 0 : node->getBody()->traverse(this);
801 :
802 0 : if (node->getExpression())
803 0 : node->getExpression()->traverse(this);
804 :
805 0 : decrementDepth();
806 : }
807 :
808 0 : if (visit && postVisit)
809 0 : visitLoop(PostVisit, node);
810 0 : }
811 :
812 : //
813 : // Traverse a branch node. Same comments in binary node apply here.
814 : //
815 0 : void TIntermTraverser::traverseBranch(TIntermBranch *node)
816 : {
817 0 : bool visit = true;
818 :
819 0 : if (preVisit)
820 0 : visit = visitBranch(PreVisit, node);
821 :
822 0 : if (visit && node->getExpression())
823 : {
824 0 : incrementDepth(node);
825 0 : node->getExpression()->traverse(this);
826 0 : decrementDepth();
827 : }
828 :
829 0 : if (visit && postVisit)
830 0 : visitBranch(PostVisit, node);
831 0 : }
832 :
833 0 : void TIntermTraverser::traverseRaw(TIntermRaw *node)
834 : {
835 0 : visitRaw(node);
836 0 : }
837 :
838 : } // namespace sh
|