blob: 8cd1fa1096c0deefa92f846f599143195a5d2b8d [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//
Olli Etuaho18b9deb2015-11-05 12:14:50 +020013// 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.
Olli Etuaho822fa842015-04-16 14:26:10 +030017
18#include "compiler/translator/SeparateArrayInitialization.h"
19
20#include "compiler/translator/IntermNode.h"
Olli Etuaho18b9deb2015-11-05 12:14:50 +020021#include "compiler/translator/OutputHLSL.h"
Olli Etuaho822fa842015-04-16 14:26:10 +030022
23namespace
24{
25
26class SeparateArrayInitTraverser : private TIntermTraverser
27{
28 public:
29 static void apply(TIntermNode *root);
30 private:
31 SeparateArrayInitTraverser();
32 bool visitAggregate(Visit, TIntermAggregate *node) override;
33};
34
35void SeparateArrayInitTraverser::apply(TIntermNode *root)
36{
37 SeparateArrayInitTraverser separateInit;
38 root->traverse(&separateInit);
39 separateInit.updateTree();
40}
41
42SeparateArrayInitTraverser::SeparateArrayInitTraverser()
43 : TIntermTraverser(true, false, false)
44{
45}
46
47bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node)
48{
49 if (node->getOp() == EOpDeclaration)
50 {
51 TIntermSequence *sequence = node->getSequence();
52 TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
53 if (initNode != nullptr && initNode->getOp() == EOpInitialize)
54 {
55 TIntermTyped *initializer = initNode->getRight();
Olli Etuaho18b9deb2015-11-05 12:14:50 +020056 if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
Olli Etuaho822fa842015-04-16 14:26:10 +030057 {
58 // We rely on that array declarations have been isolated to single declarations.
59 ASSERT(sequence->size() == 1);
60 TIntermTyped *symbol = initNode->getLeft();
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010061 TIntermBlock *parentBlock = getParentNode()->getAsBlock();
62 ASSERT(parentBlock != nullptr);
Olli Etuaho822fa842015-04-16 14:26:10 +030063
64 TIntermSequence replacements;
65
66 TIntermAggregate *replacementDeclaration = new TIntermAggregate;
67 replacementDeclaration->setOp(EOpDeclaration);
68 replacementDeclaration->getSequence()->push_back(symbol);
69 replacementDeclaration->setLine(symbol->getLine());
70 replacements.push_back(replacementDeclaration);
71
Olli Etuaho3272a6d2016-08-29 17:54:50 +030072 TIntermBinary *replacementAssignment =
73 new TIntermBinary(EOpAssign, symbol, initializer);
Olli Etuaho822fa842015-04-16 14:26:10 +030074 replacementAssignment->setLine(symbol->getLine());
75 replacements.push_back(replacementAssignment);
76
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010077 mMultiReplacements.push_back(
78 NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
Olli Etuaho822fa842015-04-16 14:26:10 +030079 }
80 }
81 return false;
82 }
83 return true;
84}
85
86} // namespace
87
88void SeparateArrayInitialization(TIntermNode *root)
89{
90 SeparateArrayInitTraverser::apply(root);
91}