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