tor-browser

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

RemoveArrayLengthMethod.cpp (3284B)


      1 //
      2 // Copyright 2017 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 // RemoveArrayLengthMethod.cpp:
      7 //   Fold array length expressions, including cases where the "this" node has side effects.
      8 //   Example:
      9 //     int i = (a = b).length();
     10 //     int j = (func()).length();
     11 //   becomes:
     12 //     (a = b);
     13 //     int i = <constant array length>;
     14 //     func();
     15 //     int j = <constant array length>;
     16 //
     17 //   Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps
     18 //   have been done to expressions containing calls of the array length method.
     19 //
     20 //   Does nothing to length method calls done on runtime-sized arrays.
     21 
     22 #include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
     23 
     24 #include "compiler/translator/IntermNode.h"
     25 #include "compiler/translator/tree_util/IntermTraverse.h"
     26 
     27 namespace sh
     28 {
     29 
     30 namespace
     31 {
     32 
     33 class RemoveArrayLengthTraverser : public TIntermTraverser
     34 {
     35  public:
     36    RemoveArrayLengthTraverser() : TIntermTraverser(true, false, false), mFoundArrayLength(false) {}
     37 
     38    bool visitUnary(Visit visit, TIntermUnary *node) override;
     39 
     40    void nextIteration() { mFoundArrayLength = false; }
     41 
     42    bool foundArrayLength() const { return mFoundArrayLength; }
     43 
     44  private:
     45    void insertSideEffectsInParentBlock(TIntermTyped *node);
     46 
     47    bool mFoundArrayLength;
     48 };
     49 
     50 bool RemoveArrayLengthTraverser::visitUnary(Visit visit, TIntermUnary *node)
     51 {
     52    // The only case where we leave array length() in place is for runtime-sized arrays.
     53    if (node->getOp() == EOpArrayLength && !node->getOperand()->getType().isUnsizedArray())
     54    {
     55        mFoundArrayLength = true;
     56        insertSideEffectsInParentBlock(node->getOperand());
     57        TConstantUnion *constArray = new TConstantUnion[1];
     58        constArray->setIConst(node->getOperand()->getOutermostArraySize());
     59        queueReplacement(new TIntermConstantUnion(constArray, node->getType()),
     60                         OriginalNode::IS_DROPPED);
     61        return false;
     62    }
     63    return true;
     64 }
     65 
     66 void RemoveArrayLengthTraverser::insertSideEffectsInParentBlock(TIntermTyped *node)
     67 {
     68    // If the node is an index type, traverse it and add the indices as side effects.  If at the end
     69    // an expression without side effect is encountered, such as an opaque uniform or a lone symbol,
     70    // don't generate a statement for it.
     71    if (!node->hasSideEffects())
     72    {
     73        return;
     74    }
     75 
     76    TIntermBinary *asBinary = node->getAsBinaryNode();
     77    if (asBinary && !asBinary->isAssignment())
     78    {
     79        insertSideEffectsInParentBlock(asBinary->getLeft());
     80        insertSideEffectsInParentBlock(asBinary->getRight());
     81    }
     82    else
     83    {
     84        insertStatementInParentBlock(node);
     85    }
     86 }
     87 
     88 }  // anonymous namespace
     89 
     90 bool RemoveArrayLengthMethod(TCompiler *compiler, TIntermBlock *root)
     91 {
     92    RemoveArrayLengthTraverser traverser;
     93    do
     94    {
     95        traverser.nextIteration();
     96        root->traverse(&traverser);
     97        if (traverser.foundArrayLength())
     98        {
     99            if (!traverser.updateTree(compiler, root))
    100            {
    101                return false;
    102            }
    103        }
    104    } while (traverser.foundArrayLength());
    105 
    106    return true;
    107 }
    108 
    109 }  // namespace sh