blob: 7ea1ce05522c425abcf30e1a87bbdceecd55e9c2 [file] [log] [blame]
Olli Etuahofc0e2bc2015-04-16 13:39:56 +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 SeparateArrayDeclarations function processes declarations that contain array declarators. Each declarator in
7// such declarations gets its own declaration.
8// This is useful as an intermediate step when initialization needs to be separated from declaration.
9// Example:
10// int a[1] = int[1](1), b[1] = int[1](2);
11// gets transformed when run through this class into the AST equivalent of:
12// int a[1] = int[1](1);
13// int b[1] = int[1](2);
14
15#include "compiler/translator/SeparateDeclarations.h"
16
17#include "compiler/translator/IntermNode.h"
18
19namespace
20{
21
22class SeparateDeclarations : private TIntermTraverser
23{
24 public:
25 static void apply(TIntermNode *root);
26 private:
27 SeparateDeclarations();
28 bool visitAggregate(Visit, TIntermAggregate *node) override;
29};
30
31void SeparateDeclarations::apply(TIntermNode *root)
32{
33 SeparateDeclarations separateDecl;
34 root->traverse(&separateDecl);
35 separateDecl.updateTree();
36}
37
38SeparateDeclarations::SeparateDeclarations()
39 : TIntermTraverser(true, false, false)
40{
41}
42
43bool SeparateDeclarations::visitAggregate(Visit, TIntermAggregate *node)
44{
45 if (node->getOp() == EOpDeclaration)
46 {
47 TIntermSequence *sequence = node->getSequence();
48 bool sequenceContainsArrays = false;
49 for (size_t ii = 0; ii < sequence->size(); ++ii)
50 {
51 TIntermTyped *typed = sequence->at(ii)->getAsTyped();
52 if (typed != nullptr && typed->isArray())
53 {
54 sequenceContainsArrays = true;
55 break;
56 }
57 }
58 if (sequence->size() > 1 && sequenceContainsArrays)
59 {
60 TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
61 ASSERT(parentAgg != nullptr);
62
63 TIntermSequence replacementDeclarations;
64 for (size_t ii = 0; ii < sequence->size(); ++ii)
65 {
66 TIntermAggregate *replacementDeclaration = new TIntermAggregate;
67
68 replacementDeclaration->setOp(EOpDeclaration);
69 replacementDeclaration->getSequence()->push_back(sequence->at(ii));
70 replacementDeclaration->setLine(sequence->at(ii)->getLine());
71 replacementDeclarations.push_back(replacementDeclaration);
72 }
73
74 mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacementDeclarations));
75 }
76 return false;
77 }
78 return true;
79}
80
81} // namespace
82
83void SeparateArrayDeclarations(TIntermNode *root)
84{
85 SeparateDeclarations::apply(root);
86}