tor-browser

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

SplitSequenceOperator.cpp (5537B)


      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 // SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
      7 // go through further AST transformations that generate statements, and splits them so that
      8 // possible side effects of earlier parts of the sequence operator expression are guaranteed to be
      9 // evaluated before the latter parts of the sequence operator expression are evaluated.
     10 //
     11 
     12 #include "compiler/translator/tree_ops/SplitSequenceOperator.h"
     13 
     14 #include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
     15 #include "compiler/translator/tree_util/IntermTraverse.h"
     16 
     17 namespace sh
     18 {
     19 
     20 namespace
     21 {
     22 
     23 class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
     24 {
     25  public:
     26    SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask, TSymbolTable *symbolTable);
     27 
     28    bool visitUnary(Visit visit, TIntermUnary *node) override;
     29    bool visitBinary(Visit visit, TIntermBinary *node) override;
     30    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
     31    bool visitTernary(Visit visit, TIntermTernary *node) override;
     32 
     33    void nextIteration();
     34    bool foundExpressionToSplit() const { return mFoundExpressionToSplit; }
     35 
     36  protected:
     37    // Marked to true once an operation that needs to be hoisted out of the expression has been
     38    // found. After that, no more AST updates are performed on that traversal.
     39    bool mFoundExpressionToSplit;
     40    int mInsideSequenceOperator;
     41 
     42    IntermNodePatternMatcher mPatternToSplitMatcher;
     43 };
     44 
     45 SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
     46                                                               TSymbolTable *symbolTable)
     47    : TLValueTrackingTraverser(true, false, true, symbolTable),
     48      mFoundExpressionToSplit(false),
     49      mInsideSequenceOperator(0),
     50      mPatternToSplitMatcher(patternsToSplitMask)
     51 {}
     52 
     53 void SplitSequenceOperatorTraverser::nextIteration()
     54 {
     55    mFoundExpressionToSplit = false;
     56    mInsideSequenceOperator = 0;
     57 }
     58 
     59 bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
     60 {
     61    if (mFoundExpressionToSplit)
     62        return false;
     63 
     64    if (mInsideSequenceOperator > 0 && visit == PreVisit)
     65    {
     66        // Detect expressions that need to be simplified
     67        mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
     68        return !mFoundExpressionToSplit;
     69    }
     70 
     71    return true;
     72 }
     73 
     74 bool SplitSequenceOperatorTraverser::visitUnary(Visit visit, TIntermUnary *node)
     75 {
     76    if (mFoundExpressionToSplit)
     77        return false;
     78 
     79    if (mInsideSequenceOperator > 0 && visit == PreVisit)
     80    {
     81        // Detect expressions that need to be simplified
     82        mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
     83        return !mFoundExpressionToSplit;
     84    }
     85 
     86    return true;
     87 }
     88 
     89 bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node)
     90 {
     91    if (node->getOp() == EOpComma)
     92    {
     93        if (visit == PreVisit)
     94        {
     95            if (mFoundExpressionToSplit)
     96            {
     97                return false;
     98            }
     99            mInsideSequenceOperator++;
    100        }
    101        else if (visit == PostVisit)
    102        {
    103            // Split sequence operators starting from the outermost one to preserve correct
    104            // execution order.
    105            if (mFoundExpressionToSplit && mInsideSequenceOperator == 1)
    106            {
    107                // Move the left side operand into a separate statement in the parent block.
    108                TIntermSequence insertions;
    109                insertions.push_back(node->getLeft());
    110                insertStatementsInParentBlock(insertions);
    111                // Replace the comma node with its right side operand.
    112                queueReplacement(node->getRight(), OriginalNode::IS_DROPPED);
    113            }
    114            mInsideSequenceOperator--;
    115        }
    116        return true;
    117    }
    118 
    119    if (mFoundExpressionToSplit)
    120        return false;
    121 
    122    if (mInsideSequenceOperator > 0 && visit == PreVisit)
    123    {
    124        // Detect expressions that need to be simplified
    125        mFoundExpressionToSplit =
    126            mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
    127        return !mFoundExpressionToSplit;
    128    }
    129 
    130    return true;
    131 }
    132 
    133 bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node)
    134 {
    135    if (mFoundExpressionToSplit)
    136        return false;
    137 
    138    if (mInsideSequenceOperator > 0 && visit == PreVisit)
    139    {
    140        // Detect expressions that need to be simplified
    141        mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
    142        return !mFoundExpressionToSplit;
    143    }
    144 
    145    return true;
    146 }
    147 
    148 }  // namespace
    149 
    150 bool SplitSequenceOperator(TCompiler *compiler,
    151                           TIntermNode *root,
    152                           int patternsToSplitMask,
    153                           TSymbolTable *symbolTable)
    154 {
    155    SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable);
    156    // Separate one expression at a time, and reset the traverser between iterations.
    157    do
    158    {
    159        traverser.nextIteration();
    160        root->traverse(&traverser);
    161        if (traverser.foundExpressionToSplit())
    162        {
    163            if (!traverser.updateTree(compiler, root))
    164            {
    165                return false;
    166            }
    167        }
    168    } while (traverser.foundExpressionToSplit());
    169 
    170    return true;
    171 }
    172 
    173 }  // namespace sh