Edit

kc3-lang/angle/src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp

Branch :

  • Show log

    Commit

  • Author : Shahbaz Youssefi
    Date : 2021-01-14 02:03:07
    Hash : 60015ff6
    Message : Vulkan: Redo RewriteStructSamplers This transformation is split into two. The first transformation solely takes out the samplers out of structs, and potentially generates array of array of samplers. A second transformation is added that takes any array of array of opaque uniforms and flattens it. A follow up change will simplify RewriteAtomicCounters which also handles array of arrays (which is no longer possible), and removes dependency on shaderStorageBufferArrayDynamicIndexing. Bug: angleproject:2703 Bug: angleproject:3881 Bug: angleproject:4071 Bug: angleproject:4211 Change-Id: I352bb2bbe65ac49f4d7d753c0ba3160fa3cc925a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2628138 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp
  • //
    // Copyright 2017 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.
    //
    // RemoveArrayLengthMethod.cpp:
    //   Fold array length expressions, including cases where the "this" node has side effects.
    //   Example:
    //     int i = (a = b).length();
    //     int j = (func()).length();
    //   becomes:
    //     (a = b);
    //     int i = <constant array length>;
    //     func();
    //     int j = <constant array length>;
    //
    //   Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps
    //   have been done to expressions containing calls of the array length method.
    //
    //   Does nothing to length method calls done on runtime-sized arrays.
    
    #include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
    
    #include "compiler/translator/IntermNode.h"
    #include "compiler/translator/tree_util/IntermTraverse.h"
    
    namespace sh
    {
    
    namespace
    {
    
    class RemoveArrayLengthTraverser : public TIntermTraverser
    {
      public:
        RemoveArrayLengthTraverser() : TIntermTraverser(true, false, false), mFoundArrayLength(false) {}
    
        bool visitUnary(Visit visit, TIntermUnary *node) override;
    
        void nextIteration() { mFoundArrayLength = false; }
    
        bool foundArrayLength() const { return mFoundArrayLength; }
    
      private:
        void insertSideEffectsInParentBlock(TIntermTyped *node);
    
        bool mFoundArrayLength;
    };
    
    bool RemoveArrayLengthTraverser::visitUnary(Visit visit, TIntermUnary *node)
    {
        // The only case where we leave array length() in place is for runtime-sized arrays.
        if (node->getOp() == EOpArrayLength && !node->getOperand()->getType().isUnsizedArray())
        {
            mFoundArrayLength = true;
            insertSideEffectsInParentBlock(node->getOperand());
            TConstantUnion *constArray = new TConstantUnion[1];
            constArray->setIConst(node->getOperand()->getOutermostArraySize());
            queueReplacement(new TIntermConstantUnion(constArray, node->getType()),
                             OriginalNode::IS_DROPPED);
            return false;
        }
        return true;
    }
    
    void RemoveArrayLengthTraverser::insertSideEffectsInParentBlock(TIntermTyped *node)
    {
        // If the node is an index type, traverse it and add the indices as side effects.  If at the end
        // an expression without side effect is encountered, such as an opaque uniform or a lone symbol,
        // don't generate a statement for it.
        if (!node->hasSideEffects())
        {
            return;
        }
    
        TIntermBinary *asBinary = node->getAsBinaryNode();
        if (asBinary && !asBinary->isAssignment())
        {
            insertSideEffectsInParentBlock(asBinary->getLeft());
            insertSideEffectsInParentBlock(asBinary->getRight());
        }
        else
        {
            insertStatementInParentBlock(node);
        }
    }
    
    }  // anonymous namespace
    
    bool RemoveArrayLengthMethod(TCompiler *compiler, TIntermBlock *root)
    {
        RemoveArrayLengthTraverser traverser;
        do
        {
            traverser.nextIteration();
            root->traverse(&traverser);
            if (traverser.foundArrayLength())
            {
                if (!traverser.updateTree(compiler, root))
                {
                    return false;
                }
            }
        } while (traverser.foundArrayLength());
    
        return true;
    }
    
    }  // namespace sh