Edit

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

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2016-07-20 18:45:09
    Hash : 7da98506
    Message : Cover vector dynamic indexing case in SplitSequenceOperator Vectors or matrices that are dynamically indexed as a part of an l-value generate new statements in the RemoveDynamicIndexing AST transformation step. SplitSequenceOperator needs to detect this case and split the sequence operator before statements are generated from its operands to ensure the correct order of execution. BUG=angleproject:1341 TEST=angle_end2end_tests Change-Id: I84e41a59c88fb5d0111669cab60312b930531a22 Reviewed-on: https://chromium-review.googlesource.com/361695 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>

  • src/compiler/translator/IntermNodePatternMatcher.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.
    //
    // IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
    // It can be used whenever the same checks for certain node structures are common to multiple AST
    // traversers.
    //
    
    #include "compiler/translator/IntermNodePatternMatcher.h"
    
    #include "compiler/translator/IntermNode.h"
    
    namespace
    {
    
    bool IsNodeBlock(TIntermNode *node)
    {
        ASSERT(node != nullptr);
        return (node->getAsAggregate() && node->getAsAggregate()->getOp() == EOpSequence);
    }
    
    }  // anonymous namespace
    
    IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
    {
    }
    
    // static
    bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
    {
        return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
               node->getLeft()->getBasicType() != EbtStruct;
    }
    
    bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
    {
        if ((mMask & kExpressionReturningArray) != 0)
        {
            if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
                !IsNodeBlock(parentNode))
            {
                return true;
            }
        }
    
        if ((mMask & kUnfoldedShortCircuitExpression) != 0)
        {
            if (node->getRight()->hasSideEffects() &&
                (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
            {
                return true;
            }
        }
        return false;
    }
    
    bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
    {
        // L-value tracking information is needed to check for dynamic indexing in L-value.
        // Traversers that don't track l-values can still use this class and match binary nodes with
        // this variation of this method if they don't need to check for dynamic indexing in l-values.
        ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
        return matchInternal(node, parentNode);
    }
    
    bool IntermNodePatternMatcher::match(TIntermBinary *node,
                                         TIntermNode *parentNode,
                                         bool isLValueRequiredHere)
    {
        if (matchInternal(node, parentNode))
        {
            return true;
        }
        if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
        {
            if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
            {
                return true;
            }
        }
        return false;
    }
    
    bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
    {
        if ((mMask & kExpressionReturningArray) != 0)
        {
            if (parentNode != nullptr)
            {
                TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
                bool parentIsAssignment =
                    (parentBinary != nullptr &&
                     (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
    
                if (node->getType().isArray() && !parentIsAssignment &&
                    (node->isConstructor() || node->getOp() == EOpFunctionCall) &&
                    !IsNodeBlock(parentNode))
                {
                    return true;
                }
            }
        }
        return false;
    }
    
    bool IntermNodePatternMatcher::match(TIntermSelection *node)
    {
        if ((mMask & kUnfoldedShortCircuitExpression) != 0)
        {
            if (node->usesTernaryOperator())
            {
                return true;
            }
        }
        return false;
    }