michael@0: // michael@0: // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: #include "compiler/intermediate.h" michael@0: michael@0: // michael@0: // Traverse the intermediate representation tree, and michael@0: // call a node type specific function for each node. michael@0: // Done recursively through the member function Traverse(). michael@0: // Node types can be skipped if their function to call is 0, michael@0: // but their subtree will still be traversed. michael@0: // Nodes with children can have their whole subtree skipped michael@0: // if preVisit is turned on and the type specific function michael@0: // returns false. michael@0: // michael@0: // preVisit, postVisit, and rightToLeft control what order michael@0: // nodes are visited in. michael@0: // michael@0: michael@0: // michael@0: // Traversal functions for terminals are straighforward.... michael@0: // michael@0: void TIntermSymbol::traverse(TIntermTraverser* it) michael@0: { michael@0: it->visitSymbol(this); michael@0: } michael@0: michael@0: void TIntermConstantUnion::traverse(TIntermTraverser* it) michael@0: { michael@0: it->visitConstantUnion(this); michael@0: } michael@0: michael@0: // michael@0: // Traverse a binary node. michael@0: // michael@0: void TIntermBinary::traverse(TIntermTraverser* it) michael@0: { michael@0: bool visit = true; michael@0: michael@0: // michael@0: // visit the node before children if pre-visiting. michael@0: // michael@0: if(it->preVisit) michael@0: { michael@0: visit = it->visitBinary(PreVisit, this); michael@0: } michael@0: michael@0: // michael@0: // Visit the children, in the right order. michael@0: // michael@0: if(visit) michael@0: { michael@0: it->incrementDepth(); michael@0: michael@0: if(it->rightToLeft) michael@0: { michael@0: if(right) michael@0: { michael@0: right->traverse(it); michael@0: } michael@0: michael@0: if(it->inVisit) michael@0: { michael@0: visit = it->visitBinary(InVisit, this); michael@0: } michael@0: michael@0: if(visit && left) michael@0: { michael@0: left->traverse(it); michael@0: } michael@0: } michael@0: else michael@0: { michael@0: if(left) michael@0: { michael@0: left->traverse(it); michael@0: } michael@0: michael@0: if(it->inVisit) michael@0: { michael@0: visit = it->visitBinary(InVisit, this); michael@0: } michael@0: michael@0: if(visit && right) michael@0: { michael@0: right->traverse(it); michael@0: } michael@0: } michael@0: michael@0: it->decrementDepth(); michael@0: } michael@0: michael@0: // michael@0: // Visit the node after the children, if requested and the traversal michael@0: // hasn't been cancelled yet. michael@0: // michael@0: if(visit && it->postVisit) michael@0: { michael@0: it->visitBinary(PostVisit, this); michael@0: } michael@0: } michael@0: michael@0: // michael@0: // Traverse a unary node. Same comments in binary node apply here. michael@0: // michael@0: void TIntermUnary::traverse(TIntermTraverser* it) michael@0: { michael@0: bool visit = true; michael@0: michael@0: if (it->preVisit) michael@0: visit = it->visitUnary(PreVisit, this); michael@0: michael@0: if (visit) { michael@0: it->incrementDepth(); michael@0: operand->traverse(it); michael@0: it->decrementDepth(); michael@0: } michael@0: michael@0: if (visit && it->postVisit) michael@0: it->visitUnary(PostVisit, this); michael@0: } michael@0: michael@0: // michael@0: // Traverse an aggregate node. Same comments in binary node apply here. michael@0: // michael@0: void TIntermAggregate::traverse(TIntermTraverser* it) michael@0: { michael@0: bool visit = true; michael@0: michael@0: if(it->preVisit) michael@0: { michael@0: visit = it->visitAggregate(PreVisit, this); michael@0: } michael@0: michael@0: if(visit) michael@0: { michael@0: it->incrementDepth(); michael@0: michael@0: if(it->rightToLeft) michael@0: { michael@0: for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) michael@0: { michael@0: (*sit)->traverse(it); michael@0: michael@0: if(visit && it->inVisit) michael@0: { michael@0: if(*sit != sequence.front()) michael@0: { michael@0: visit = it->visitAggregate(InVisit, this); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: else michael@0: { michael@0: for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) michael@0: { michael@0: (*sit)->traverse(it); michael@0: michael@0: if(visit && it->inVisit) michael@0: { michael@0: if(*sit != sequence.back()) michael@0: { michael@0: visit = it->visitAggregate(InVisit, this); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: it->decrementDepth(); michael@0: } michael@0: michael@0: if(visit && it->postVisit) michael@0: { michael@0: it->visitAggregate(PostVisit, this); michael@0: } michael@0: } michael@0: michael@0: // michael@0: // Traverse a selection node. Same comments in binary node apply here. michael@0: // michael@0: void TIntermSelection::traverse(TIntermTraverser* it) michael@0: { michael@0: bool visit = true; michael@0: michael@0: if (it->preVisit) michael@0: visit = it->visitSelection(PreVisit, this); michael@0: michael@0: if (visit) { michael@0: it->incrementDepth(); michael@0: if (it->rightToLeft) { michael@0: if (falseBlock) michael@0: falseBlock->traverse(it); michael@0: if (trueBlock) michael@0: trueBlock->traverse(it); michael@0: condition->traverse(it); michael@0: } else { michael@0: condition->traverse(it); michael@0: if (trueBlock) michael@0: trueBlock->traverse(it); michael@0: if (falseBlock) michael@0: falseBlock->traverse(it); michael@0: } michael@0: it->decrementDepth(); michael@0: } michael@0: michael@0: if (visit && it->postVisit) michael@0: it->visitSelection(PostVisit, this); michael@0: } michael@0: michael@0: // michael@0: // Traverse a loop node. Same comments in binary node apply here. michael@0: // michael@0: void TIntermLoop::traverse(TIntermTraverser* it) michael@0: { michael@0: bool visit = true; michael@0: michael@0: if(it->preVisit) michael@0: { michael@0: visit = it->visitLoop(PreVisit, this); michael@0: } michael@0: michael@0: if(visit) michael@0: { michael@0: it->incrementDepth(); michael@0: michael@0: if(it->rightToLeft) michael@0: { michael@0: if(expr) michael@0: { michael@0: expr->traverse(it); michael@0: } michael@0: michael@0: if(body) michael@0: { michael@0: body->traverse(it); michael@0: } michael@0: michael@0: if(cond) michael@0: { michael@0: cond->traverse(it); michael@0: } michael@0: } michael@0: else michael@0: { michael@0: if(cond) michael@0: { michael@0: cond->traverse(it); michael@0: } michael@0: michael@0: if(body) michael@0: { michael@0: body->traverse(it); michael@0: } michael@0: michael@0: if(expr) michael@0: { michael@0: expr->traverse(it); michael@0: } michael@0: } michael@0: michael@0: it->decrementDepth(); michael@0: } michael@0: michael@0: if(visit && it->postVisit) michael@0: { michael@0: it->visitLoop(PostVisit, this); michael@0: } michael@0: } michael@0: michael@0: // michael@0: // Traverse a branch node. Same comments in binary node apply here. michael@0: // michael@0: void TIntermBranch::traverse(TIntermTraverser* it) michael@0: { michael@0: bool visit = true; michael@0: michael@0: if (it->preVisit) michael@0: visit = it->visitBranch(PreVisit, this); michael@0: michael@0: if (visit && expression) { michael@0: it->incrementDepth(); michael@0: expression->traverse(it); michael@0: it->decrementDepth(); michael@0: } michael@0: michael@0: if (visit && it->postVisit) michael@0: it->visitBranch(PostVisit, this); michael@0: } michael@0: