LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - IntermTraverse.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 439 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 58 0.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13