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