tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

IntermNodePatternMatcher.cpp (6229B)


      1 //
      2 // Copyright 2016 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 // IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
      7 // It can be used whenever the same checks for certain node structures are common to multiple AST
      8 // traversers.
      9 //
     10 
     11 #include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
     12 
     13 #include "compiler/translator/IntermNode.h"
     14 #include "compiler/translator/SymbolTable.h"
     15 #include "compiler/translator/util.h"
     16 
     17 namespace sh
     18 {
     19 
     20 namespace
     21 {
     22 
     23 bool ContainsMatrixNode(const TIntermSequence &sequence)
     24 {
     25    for (size_t ii = 0; ii < sequence.size(); ++ii)
     26    {
     27        TIntermTyped *node = sequence[ii]->getAsTyped();
     28        if (node && node->isMatrix())
     29            return true;
     30    }
     31    return false;
     32 }
     33 
     34 bool ContainsVectorNode(const TIntermSequence &sequence)
     35 {
     36    for (size_t ii = 0; ii < sequence.size(); ++ii)
     37    {
     38        TIntermTyped *node = sequence[ii]->getAsTyped();
     39        if (node && node->isVector())
     40            return true;
     41    }
     42    return false;
     43 }
     44 
     45 }  // anonymous namespace
     46 
     47 IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask) {}
     48 
     49 // static
     50 bool IntermNodePatternMatcher::IsDynamicIndexingOfNonSSBOVectorOrMatrix(TIntermBinary *node)
     51 {
     52    return IsDynamicIndexingOfVectorOrMatrix(node) && !IsInShaderStorageBlock(node->getLeft());
     53 }
     54 
     55 // static
     56 bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
     57 {
     58    return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
     59           node->getLeft()->getBasicType() != EbtStruct;
     60 }
     61 
     62 // static
     63 bool IntermNodePatternMatcher::IsDynamicIndexingOfSwizzledVector(TIntermBinary *node)
     64 {
     65    return IsDynamicIndexingOfVectorOrMatrix(node) && node->getLeft()->getAsSwizzleNode();
     66 }
     67 
     68 bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode) const
     69 {
     70    if ((mMask & kExpressionReturningArray) != 0)
     71    {
     72        if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
     73            !parentNode->getAsBlock())
     74        {
     75            return true;
     76        }
     77    }
     78 
     79    if ((mMask & kUnfoldedShortCircuitExpression) != 0)
     80    {
     81        if (node->getRight()->hasSideEffects() &&
     82            (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
     83        {
     84            return true;
     85        }
     86    }
     87    return false;
     88 }
     89 
     90 bool IntermNodePatternMatcher::match(TIntermUnary *node) const
     91 {
     92    if ((mMask & kArrayLengthMethod) != 0)
     93    {
     94        if (node->getOp() == EOpArrayLength)
     95        {
     96            return true;
     97        }
     98    }
     99    return false;
    100 }
    101 
    102 bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode) const
    103 {
    104    // L-value tracking information is needed to check for dynamic indexing in L-value.
    105    // Traversers that don't track l-values can still use this class and match binary nodes with
    106    // this variation of this method if they don't need to check for dynamic indexing in l-values.
    107    ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
    108    return matchInternal(node, parentNode);
    109 }
    110 
    111 bool IntermNodePatternMatcher::match(TIntermBinary *node,
    112                                     TIntermNode *parentNode,
    113                                     bool isLValueRequiredHere) const
    114 {
    115    if (matchInternal(node, parentNode))
    116    {
    117        return true;
    118    }
    119    if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
    120    {
    121        if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
    122        {
    123            return true;
    124        }
    125    }
    126    return false;
    127 }
    128 
    129 bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode) const
    130 {
    131    if ((mMask & kExpressionReturningArray) != 0)
    132    {
    133        if (parentNode != nullptr)
    134        {
    135            TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
    136            bool parentIsAssignment =
    137                (parentBinary != nullptr &&
    138                 (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
    139 
    140            if (node->getType().isArray() && !parentIsAssignment &&
    141                (node->isConstructor() || node->isFunctionCall() ||
    142                 (BuiltInGroup::IsBuiltIn(node->getOp()) &&
    143                  !BuiltInGroup::IsMath(node->getOp()))) &&
    144                !parentNode->getAsBlock())
    145            {
    146                return true;
    147            }
    148        }
    149    }
    150    if ((mMask & kScalarizedVecOrMatConstructor) != 0)
    151    {
    152        if (node->getOp() == EOpConstruct)
    153        {
    154            if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence())))
    155            {
    156                return true;
    157            }
    158            else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence())))
    159            {
    160                return true;
    161            }
    162        }
    163    }
    164    return false;
    165 }
    166 
    167 bool IntermNodePatternMatcher::match(TIntermTernary *node) const
    168 {
    169    if ((mMask & kUnfoldedShortCircuitExpression) != 0)
    170    {
    171        return true;
    172    }
    173    return false;
    174 }
    175 
    176 bool IntermNodePatternMatcher::match(TIntermDeclaration *node) const
    177 {
    178    if ((mMask & kMultiDeclaration) != 0)
    179    {
    180        if (node->getSequence()->size() > 1)
    181        {
    182            return true;
    183        }
    184    }
    185    if ((mMask & kArrayDeclaration) != 0)
    186    {
    187        if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays())
    188        {
    189            return true;
    190        }
    191        // Need to check from all declarators whether they are arrays since that may vary between
    192        // declarators.
    193        for (TIntermNode *declarator : *node->getSequence())
    194        {
    195            if (declarator->getAsTyped()->isArray())
    196            {
    197                return true;
    198            }
    199        }
    200    }
    201    if ((mMask & kNamelessStructDeclaration) != 0)
    202    {
    203        TIntermTyped *declarator = node->getSequence()->front()->getAsTyped();
    204        if (declarator->getBasicType() == EbtStruct &&
    205            declarator->getType().getStruct()->symbolType() == SymbolType::Empty)
    206        {
    207            return true;
    208        }
    209    }
    210    return false;
    211 }
    212 
    213 }  // namespace sh