blob: f8d14660a43c226f6170518203e7ed0e928a321b [file] [log] [blame]
Olli Etuaho822fa842015-04-16 14:26:10 +03001//
2// Copyright (c) 2002-2015 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 an assignment.
7// Example:
8// type[n] a = initializer;
9// will effectively become
10// type[n] a;
11// a = initializer;
12
13#include "compiler/translator/SeparateArrayInitialization.h"
14
15#include "compiler/translator/IntermNode.h"
16
17namespace
18{
19
20class SeparateArrayInitTraverser : private TIntermTraverser
21{
22 public:
23 static void apply(TIntermNode *root);
24 private:
25 SeparateArrayInitTraverser();
26 bool visitAggregate(Visit, TIntermAggregate *node) override;
27};
28
29void SeparateArrayInitTraverser::apply(TIntermNode *root)
30{
31 SeparateArrayInitTraverser separateInit;
32 root->traverse(&separateInit);
33 separateInit.updateTree();
34}
35
36SeparateArrayInitTraverser::SeparateArrayInitTraverser()
37 : TIntermTraverser(true, false, false)
38{
39}
40
41bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node)
42{
43 if (node->getOp() == EOpDeclaration)
44 {
45 TIntermSequence *sequence = node->getSequence();
46 TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
47 if (initNode != nullptr && initNode->getOp() == EOpInitialize)
48 {
49 TIntermTyped *initializer = initNode->getRight();
50 if (initializer->isArray())
51 {
52 // We rely on that array declarations have been isolated to single declarations.
53 ASSERT(sequence->size() == 1);
54 TIntermTyped *symbol = initNode->getLeft();
55 TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
56 ASSERT(parentAgg != nullptr);
57
58 TIntermSequence replacements;
59
60 TIntermAggregate *replacementDeclaration = new TIntermAggregate;
61 replacementDeclaration->setOp(EOpDeclaration);
62 replacementDeclaration->getSequence()->push_back(symbol);
63 replacementDeclaration->setLine(symbol->getLine());
64 replacements.push_back(replacementDeclaration);
65
66 TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign);
67 replacementAssignment->setLeft(symbol);
68 replacementAssignment->setRight(initializer);
69 replacementAssignment->setType(initializer->getType());
70 replacementAssignment->setLine(symbol->getLine());
71 replacements.push_back(replacementAssignment);
72
73 mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacements));
74 }
75 }
76 return false;
77 }
78 return true;
79}
80
81} // namespace
82
83void SeparateArrayInitialization(TIntermNode *root)
84{
85 SeparateArrayInitTraverser::apply(root);
86}