blob: 78aeb8d29f21108b5506f4d297b628ff90d93305 [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;
Olli Etuahob1edc4f2015-11-02 17:20:03 +020012//
13// Note that if the array is declared as const, the initialization is still split, making the AST
14// technically invalid. Because of that this transformation should only be used when subsequent
15// stages don't care about const qualifiers.
Olli Etuaho822fa842015-04-16 14:26:10 +030016
17#include "compiler/translator/SeparateArrayInitialization.h"
18
19#include "compiler/translator/IntermNode.h"
20
21namespace
22{
23
24class SeparateArrayInitTraverser : private TIntermTraverser
25{
26 public:
27 static void apply(TIntermNode *root);
28 private:
29 SeparateArrayInitTraverser();
30 bool visitAggregate(Visit, TIntermAggregate *node) override;
31};
32
33void SeparateArrayInitTraverser::apply(TIntermNode *root)
34{
35 SeparateArrayInitTraverser separateInit;
36 root->traverse(&separateInit);
37 separateInit.updateTree();
38}
39
40SeparateArrayInitTraverser::SeparateArrayInitTraverser()
41 : TIntermTraverser(true, false, false)
42{
43}
44
45bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node)
46{
47 if (node->getOp() == EOpDeclaration)
48 {
49 TIntermSequence *sequence = node->getSequence();
50 TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
51 if (initNode != nullptr && initNode->getOp() == EOpInitialize)
52 {
53 TIntermTyped *initializer = initNode->getRight();
54 if (initializer->isArray())
55 {
56 // We rely on that array declarations have been isolated to single declarations.
57 ASSERT(sequence->size() == 1);
58 TIntermTyped *symbol = initNode->getLeft();
59 TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
60 ASSERT(parentAgg != nullptr);
61
62 TIntermSequence replacements;
63
64 TIntermAggregate *replacementDeclaration = new TIntermAggregate;
65 replacementDeclaration->setOp(EOpDeclaration);
66 replacementDeclaration->getSequence()->push_back(symbol);
67 replacementDeclaration->setLine(symbol->getLine());
68 replacements.push_back(replacementDeclaration);
69
70 TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign);
71 replacementAssignment->setLeft(symbol);
72 replacementAssignment->setRight(initializer);
73 replacementAssignment->setType(initializer->getType());
74 replacementAssignment->setLine(symbol->getLine());
75 replacements.push_back(replacementAssignment);
76
77 mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacements));
78 }
79 }
80 return false;
81 }
82 return true;
83}
84
85} // namespace
86
87void SeparateArrayInitialization(TIntermNode *root)
88{
89 SeparateArrayInitTraverser::apply(root);
90}