1 //
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 SeparateDeclarations function processes declarations, so that in the end each declaration
7 // contains only one declarator.
8 // This is useful as an intermediate step when initialization needs to be separated from
9 // declaration, or when things need to be unfolded out of the initializer.
10 // Example:
11 // int a[1] = int[1](1), b[1] = int[1](2);
12 // gets transformed when run through this class into the AST equivalent of:
13 // int a[1] = int[1](1);
14 // int b[1] = int[1](2);
15
16 #include "compiler/translator/SeparateDeclarations.h"
17
18 #include "compiler/translator/IntermTraverse.h"
19
20 namespace sh
21 {
22
23 namespace
24 {
25
26 class SeparateDeclarationsTraverser : private TIntermTraverser
27 {
28 public:
29 static void apply(TIntermNode *root);
30
31 private:
32 SeparateDeclarationsTraverser();
33 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
34 };
35
apply(TIntermNode * root)36 void SeparateDeclarationsTraverser::apply(TIntermNode *root)
37 {
38 SeparateDeclarationsTraverser separateDecl;
39 root->traverse(&separateDecl);
40 separateDecl.updateTree();
41 }
42
SeparateDeclarationsTraverser()43 SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
44 : TIntermTraverser(true, false, false)
45 {
46 }
47
visitDeclaration(Visit,TIntermDeclaration * node)48 bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
49 {
50 TIntermSequence *sequence = node->getSequence();
51 if (sequence->size() > 1)
52 {
53 TIntermBlock *parentBlock = getParentNode()->getAsBlock();
54 ASSERT(parentBlock != nullptr);
55
56 TIntermSequence replacementDeclarations;
57 for (size_t ii = 0; ii < sequence->size(); ++ii)
58 {
59 TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
60
61 replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
62 replacementDeclaration->setLine(sequence->at(ii)->getLine());
63 replacementDeclarations.push_back(replacementDeclaration);
64 }
65
66 mMultiReplacements.push_back(
67 NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
68 }
69 return false;
70 }
71
72 } // namespace
73
SeparateDeclarations(TIntermNode * root)74 void SeparateDeclarations(TIntermNode *root)
75 {
76 SeparateDeclarationsTraverser::apply(root);
77 }
78
79 } // namespace sh
80