• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // SeparateArrayConstructorStatements splits statements that are array constructors and drops all of
7 // their constant arguments. For example, a statement like:
8 //   int[2](0, i++);
9 // Will be changed to:
10 //   i++;
11 
12 #include "compiler/translator/tree_ops/SeparateArrayConstructorStatements.h"
13 
14 #include "compiler/translator/tree_util/IntermTraverse.h"
15 
16 namespace sh
17 {
18 
19 namespace
20 {
21 
SplitConstructorArgs(const TIntermSequence & originalArgs,TIntermSequence * argsOut)22 void SplitConstructorArgs(const TIntermSequence &originalArgs, TIntermSequence *argsOut)
23 {
24     for (TIntermNode *arg : originalArgs)
25     {
26         TIntermTyped *argTyped = arg->getAsTyped();
27         if (argTyped->hasSideEffects())
28         {
29             TIntermAggregate *argAggregate = argTyped->getAsAggregate();
30             if (argTyped->isArray() && argAggregate && argAggregate->isConstructor())
31             {
32                 SplitConstructorArgs(*argAggregate->getSequence(), argsOut);
33             }
34             else
35             {
36                 argsOut->push_back(argTyped);
37             }
38         }
39     }
40 }
41 
42 class SeparateArrayConstructorStatementsTraverser : public TIntermTraverser
43 {
44   public:
45     SeparateArrayConstructorStatementsTraverser();
46 
47     bool visitAggregate(Visit visit, TIntermAggregate *node) override;
48 };
49 
SeparateArrayConstructorStatementsTraverser()50 SeparateArrayConstructorStatementsTraverser::SeparateArrayConstructorStatementsTraverser()
51     : TIntermTraverser(true, false, false)
52 {}
53 
visitAggregate(Visit visit,TIntermAggregate * node)54 bool SeparateArrayConstructorStatementsTraverser::visitAggregate(Visit visit,
55                                                                  TIntermAggregate *node)
56 {
57     TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
58     if (!parentAsBlock)
59     {
60         return false;
61     }
62     if (!node->isArray() || !node->isConstructor())
63     {
64         return false;
65     }
66 
67     TIntermSequence constructorArgs;
68     SplitConstructorArgs(*node->getSequence(), &constructorArgs);
69     mMultiReplacements.push_back(
70         NodeReplaceWithMultipleEntry(parentAsBlock, node, constructorArgs));
71 
72     return false;
73 }
74 
75 }  // namespace
76 
SeparateArrayConstructorStatements(TCompiler * compiler,TIntermBlock * root)77 bool SeparateArrayConstructorStatements(TCompiler *compiler, TIntermBlock *root)
78 {
79     SeparateArrayConstructorStatementsTraverser traverser;
80     root->traverse(&traverser);
81     return traverser.updateTree(compiler, root);
82 }
83 
84 }  // namespace sh
85