Edit

kc3-lang/angle/src/compiler/translator/SplitSequenceOperator.cpp

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2017-07-13 16:07:26
    Hash : a5e693af
    Message : Make unique id counter a member of TSymbolTable This makes unique id counting thread-safe. BUG=angleproject:624 TEST=angle_unittests Change-Id: Ie0f2c7e574470b39750d37d2181c790bc874b275 Reviewed-on: https://chromium-review.googlesource.com/570419 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/compiler/translator/SplitSequenceOperator.cpp
  • //
    // Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
    // go through further AST transformations that generate statements, and splits them so that
    // possible side effects of earlier parts of the sequence operator expression are guaranteed to be
    // evaluated before the latter parts of the sequence operator expression are evaluated.
    //
    
    #include "compiler/translator/SplitSequenceOperator.h"
    
    #include "compiler/translator/IntermNodePatternMatcher.h"
    #include "compiler/translator/IntermTraverse.h"
    
    namespace sh
    {
    
    namespace
    {
    
    class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
    {
      public:
        SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
                                       TSymbolTable *symbolTable,
                                       int shaderVersion);
    
        bool visitBinary(Visit visit, TIntermBinary *node) override;
        bool visitAggregate(Visit visit, TIntermAggregate *node) override;
        bool visitTernary(Visit visit, TIntermTernary *node) override;
    
        void nextIteration();
        bool foundExpressionToSplit() const { return mFoundExpressionToSplit; }
    
      protected:
        // Marked to true once an operation that needs to be hoisted out of the expression has been
        // found. After that, no more AST updates are performed on that traversal.
        bool mFoundExpressionToSplit;
        int mInsideSequenceOperator;
    
        IntermNodePatternMatcher mPatternToSplitMatcher;
    };
    
    SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
                                                                   TSymbolTable *symbolTable,
                                                                   int shaderVersion)
        : TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
          mFoundExpressionToSplit(false),
          mInsideSequenceOperator(0),
          mPatternToSplitMatcher(patternsToSplitMask)
    {
    }
    
    void SplitSequenceOperatorTraverser::nextIteration()
    {
        mFoundExpressionToSplit = false;
        mInsideSequenceOperator = 0;
        nextTemporaryId();
    }
    
    bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
    {
        if (mFoundExpressionToSplit)
            return false;
    
        if (mInsideSequenceOperator > 0 && visit == PreVisit)
        {
            // Detect expressions that need to be simplified
            mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
            return !mFoundExpressionToSplit;
        }
    
        return true;
    }
    
    bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node)
    {
        if (node->getOp() == EOpComma)
        {
            if (visit == PreVisit)
            {
                if (mFoundExpressionToSplit)
                {
                    return false;
                }
                mInsideSequenceOperator++;
            }
            else if (visit == PostVisit)
            {
                // Split sequence operators starting from the outermost one to preserve correct
                // execution order.
                if (mFoundExpressionToSplit && mInsideSequenceOperator == 1)
                {
                    // Move the left side operand into a separate statement in the parent block.
                    TIntermSequence insertions;
                    insertions.push_back(node->getLeft());
                    insertStatementsInParentBlock(insertions);
                    // Replace the comma node with its right side operand.
                    queueReplacement(node->getRight(), OriginalNode::IS_DROPPED);
                }
                mInsideSequenceOperator--;
            }
            return true;
        }
    
        if (mFoundExpressionToSplit)
            return false;
    
        if (mInsideSequenceOperator > 0 && visit == PreVisit)
        {
            // Detect expressions that need to be simplified
            mFoundExpressionToSplit =
                mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
            return !mFoundExpressionToSplit;
        }
    
        return true;
    }
    
    bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node)
    {
        if (mFoundExpressionToSplit)
            return false;
    
        if (mInsideSequenceOperator > 0 && visit == PreVisit)
        {
            // Detect expressions that need to be simplified
            mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
            return !mFoundExpressionToSplit;
        }
    
        return true;
    }
    
    }  // namespace
    
    void SplitSequenceOperator(TIntermNode *root,
                               int patternsToSplitMask,
                               TSymbolTable *symbolTable,
                               int shaderVersion)
    {
        SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
        // Separate one expression at a time, and reset the traverser between iterations.
        do
        {
            traverser.nextIteration();
            root->traverse(&traverser);
            if (traverser.foundExpressionToSplit())
                traverser.updateTree();
        } while (traverser.foundExpressionToSplit());
    }
    
    }  // namespace sh