1 //
2 // Copyright 2002 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/tree_ops/SeparateDeclarations.h"
17 
18 #include "compiler/translator/tree_util/IntermTraverse.h"
19 
20 namespace sh
21 {
22 
23 namespace
24 {
25 
26 class SeparateDeclarationsTraverser : private TIntermTraverser
27 {
28   public:
29     ANGLE_NO_DISCARD static bool apply(TCompiler *compiler, TIntermNode *root);
30 
31   private:
32     SeparateDeclarationsTraverser();
33     bool visitDeclaration(Visit, TIntermDeclaration *node) override;
34 };
35 
apply(TCompiler * compiler,TIntermNode * root)36 bool SeparateDeclarationsTraverser::apply(TCompiler *compiler, TIntermNode *root)
37 {
38     SeparateDeclarationsTraverser separateDecl;
39     root->traverse(&separateDecl);
40     return separateDecl.updateTree(compiler, root);
41 }
42 
SeparateDeclarationsTraverser()43 SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
44     : TIntermTraverser(true, false, false)
45 {}
46 
visitDeclaration(Visit,TIntermDeclaration * node)47 bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
48 {
49     TIntermSequence *sequence = node->getSequence();
50     if (sequence->size() > 1)
51     {
52         TIntermBlock *parentBlock = getParentNode()->getAsBlock();
53         ASSERT(parentBlock != nullptr);
54 
55         TIntermSequence replacementDeclarations;
56         for (size_t ii = 0; ii < sequence->size(); ++ii)
57         {
58             TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
59 
60             replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
61             replacementDeclaration->setLine(sequence->at(ii)->getLine());
62             replacementDeclarations.push_back(replacementDeclaration);
63         }
64 
65         mMultiReplacements.emplace_back(parentBlock, node, std::move(replacementDeclarations));
66     }
67     return false;
68 }
69 
70 }  // namespace
71 
SeparateDeclarations(TCompiler * compiler,TIntermNode * root)72 bool SeparateDeclarations(TCompiler *compiler, TIntermNode *root)
73 {
74     return SeparateDeclarationsTraverser::apply(compiler, root);
75 }
76 
77 }  // namespace sh
78