tor-browser

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

SeparateArrayInitialization.cpp (3122B)


      1 //
      2 // Copyright 2002 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 // The SeparateArrayInitialization function splits each array initialization into a declaration and
      7 // an assignment.
      8 // Example:
      9 //     type[n] a = initializer;
     10 // will effectively become
     11 //     type[n] a;
     12 //     a = initializer;
     13 //
     14 // Note that if the array is declared as const, the initialization may still be split, making the
     15 // AST technically invalid. Because of that this transformation should only be used when subsequent
     16 // stages don't care about const qualifiers. However, the initialization will not be split if the
     17 // initializer can be written as a HLSL literal.
     18 
     19 #include "compiler/translator/tree_ops/d3d/SeparateArrayInitialization.h"
     20 
     21 #include "compiler/translator/IntermNode.h"
     22 #include "compiler/translator/OutputHLSL.h"
     23 
     24 namespace sh
     25 {
     26 
     27 namespace
     28 {
     29 
     30 class SeparateArrayInitTraverser : private TIntermTraverser
     31 {
     32  public:
     33    [[nodiscard]] static bool apply(TCompiler *compiler, TIntermNode *root);
     34 
     35  private:
     36    SeparateArrayInitTraverser();
     37    bool visitDeclaration(Visit, TIntermDeclaration *node) override;
     38 };
     39 
     40 bool SeparateArrayInitTraverser::apply(TCompiler *compiler, TIntermNode *root)
     41 {
     42    SeparateArrayInitTraverser separateInit;
     43    root->traverse(&separateInit);
     44    return separateInit.updateTree(compiler, root);
     45 }
     46 
     47 SeparateArrayInitTraverser::SeparateArrayInitTraverser() : TIntermTraverser(true, false, false) {}
     48 
     49 bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
     50 {
     51    TIntermSequence *sequence = node->getSequence();
     52    TIntermBinary *initNode   = sequence->back()->getAsBinaryNode();
     53    if (initNode != nullptr && initNode->getOp() == EOpInitialize)
     54    {
     55        TIntermTyped *initializer = initNode->getRight();
     56        if (initializer->isArray() && !initializer->hasConstantValue())
     57        {
     58            // We rely on that array declarations have been isolated to single declarations.
     59            ASSERT(sequence->size() == 1);
     60            TIntermTyped *symbol      = initNode->getLeft();
     61            TIntermBlock *parentBlock = getParentNode()->getAsBlock();
     62            ASSERT(parentBlock != nullptr);
     63 
     64            TIntermSequence replacements;
     65 
     66            TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
     67            replacementDeclaration->appendDeclarator(symbol);
     68            replacementDeclaration->setLine(symbol->getLine());
     69            replacements.push_back(replacementDeclaration);
     70 
     71            TIntermBinary *replacementAssignment =
     72                new TIntermBinary(EOpAssign, symbol, initializer);
     73            replacementAssignment->setLine(symbol->getLine());
     74            replacements.push_back(replacementAssignment);
     75 
     76            mMultiReplacements.emplace_back(parentBlock, node, std::move(replacements));
     77        }
     78    }
     79    return false;
     80 }
     81 
     82 }  // namespace
     83 
     84 bool SeparateArrayInitialization(TCompiler *compiler, TIntermNode *root)
     85 {
     86    return SeparateArrayInitTraverser::apply(compiler, root);
     87 }
     88 
     89 }  // namespace sh