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

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2015 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             : // SeparateExpressionsReturningArrays splits array-returning expressions that are not array names from more complex
       7             : // expressions, assigning them to a temporary variable a#.
       8             : // Examples where a, b and c are all arrays:
       9             : // (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2;
      10             : // type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i];
      11             : 
      12             : #include "compiler/translator/SeparateExpressionsReturningArrays.h"
      13             : 
      14             : #include "compiler/translator/IntermNode.h"
      15             : #include "compiler/translator/IntermNodePatternMatcher.h"
      16             : 
      17             : namespace sh
      18             : {
      19             : 
      20             : namespace
      21             : {
      22             : 
      23             : // Traverser that separates one array expression into a statement at a time.
      24           0 : class SeparateExpressionsTraverser : public TIntermTraverser
      25             : {
      26             :   public:
      27             :     SeparateExpressionsTraverser();
      28             : 
      29             :     bool visitBinary(Visit visit, TIntermBinary *node) override;
      30             :     bool visitAggregate(Visit visit, TIntermAggregate *node) override;
      31             : 
      32             :     void nextIteration();
      33           0 :     bool foundArrayExpression() const { return mFoundArrayExpression; }
      34             : 
      35             :   protected:
      36             :     // Marked to true once an operation that needs to be hoisted out of the expression has been found.
      37             :     // After that, no more AST updates are performed on that traversal.
      38             :     bool mFoundArrayExpression;
      39             : 
      40             :     IntermNodePatternMatcher mPatternToSeparateMatcher;
      41             : };
      42             : 
      43           0 : SeparateExpressionsTraverser::SeparateExpressionsTraverser()
      44             :     : TIntermTraverser(true, false, false),
      45             :       mFoundArrayExpression(false),
      46           0 :       mPatternToSeparateMatcher(IntermNodePatternMatcher::kExpressionReturningArray)
      47             : {
      48           0 : }
      49             : 
      50             : // Performs a shallow copy of an assignment node.
      51             : // These shallow copies are useful when a node gets inserted into an aggregate node
      52             : // and also needs to be replaced in its original location by a different node.
      53           0 : TIntermBinary *CopyAssignmentNode(TIntermBinary *node)
      54             : {
      55           0 :     return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight());
      56             : }
      57             : 
      58             : // Performs a shallow copy of a constructor/function call node.
      59           0 : TIntermAggregate *CopyAggregateNode(TIntermAggregate *node)
      60             : {
      61           0 :     TIntermAggregate *copyNode = new TIntermAggregate(node->getOp());
      62           0 :     TIntermSequence *copySeq = copyNode->getSequence();
      63           0 :     copySeq->insert(copySeq->begin(), node->getSequence()->begin(), node->getSequence()->end());
      64           0 :     copyNode->setType(node->getType());
      65           0 :     *copyNode->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo();
      66           0 :     if (node->isUserDefined())
      67             :     {
      68           0 :         copyNode->setUserDefined();
      69             :     }
      70           0 :     return copyNode;
      71             : }
      72             : 
      73           0 : bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
      74             : {
      75           0 :     if (mFoundArrayExpression)
      76           0 :         return false;
      77             : 
      78             :     // Return if the expression is not an array or if we're not inside a complex expression.
      79           0 :     if (!mPatternToSeparateMatcher.match(node, getParentNode()))
      80           0 :         return true;
      81             : 
      82           0 :     ASSERT(node->getOp() == EOpAssign);
      83             : 
      84           0 :     mFoundArrayExpression = true;
      85             : 
      86           0 :     TIntermSequence insertions;
      87           0 :     insertions.push_back(CopyAssignmentNode(node));
      88             :     // TODO(oetuaho): In some cases it would be more optimal to not add the temporary node, but just
      89             :     // use the original target of the assignment. Care must be taken so that this doesn't happen
      90             :     // when the same array symbol is a target of assignment more than once in one expression.
      91           0 :     insertions.push_back(createTempInitDeclaration(node->getLeft()));
      92           0 :     insertStatementsInParentBlock(insertions);
      93             : 
      94           0 :     queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
      95             : 
      96           0 :     return false;
      97             : }
      98             : 
      99           0 : bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
     100             : {
     101           0 :     if (mFoundArrayExpression)
     102           0 :         return false; // No need to traverse further
     103             : 
     104           0 :     if (!mPatternToSeparateMatcher.match(node, getParentNode()))
     105           0 :         return true;
     106             : 
     107           0 :     ASSERT(node->isConstructor() || node->getOp() == EOpFunctionCall);
     108             : 
     109           0 :     mFoundArrayExpression = true;
     110             : 
     111           0 :     TIntermSequence insertions;
     112           0 :     insertions.push_back(createTempInitDeclaration(CopyAggregateNode(node)));
     113           0 :     insertStatementsInParentBlock(insertions);
     114             : 
     115           0 :     queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
     116             : 
     117           0 :     return false;
     118             : }
     119             : 
     120           0 : void SeparateExpressionsTraverser::nextIteration()
     121             : {
     122           0 :     mFoundArrayExpression = false;
     123           0 :     nextTemporaryIndex();
     124           0 : }
     125             : 
     126             : } // namespace
     127             : 
     128           0 : void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex)
     129             : {
     130           0 :     SeparateExpressionsTraverser traverser;
     131           0 :     ASSERT(temporaryIndex != nullptr);
     132           0 :     traverser.useTemporaryIndex(temporaryIndex);
     133             :     // Separate one expression at a time, and reset the traverser between iterations.
     134           0 :     do
     135             :     {
     136           0 :         traverser.nextIteration();
     137           0 :         root->traverse(&traverser);
     138           0 :         if (traverser.foundArrayExpression())
     139           0 :             traverser.updateTree();
     140             :     }
     141             :     while (traverser.foundArrayExpression());
     142           0 : }
     143             : 
     144             : }  // namespace sh

Generated by: LCOV version 1.13