blob: e1026cb4fd34675f78851d86857863b3f23d1bdb [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//
Jamie Madilld7b1ab52016-12-12 14:42:19 -05006// The SeparateArrayInitialization function splits each array initialization into a declaration and
7// an assignment.
Olli Etuaho822fa842015-04-16 14:26:10 +03008// Example:
9// type[n] a = initializer;
10// will effectively become
11// type[n] a;
12// a = initializer;
Olli Etuahob1edc4f2015-11-02 17:20:03 +020013//
Olli Etuaho18b9deb2015-11-05 12:14:50 +020014// Note that if the array is declared as const, the initialization may still be split, making the
15// AST technically invalid. Because of that this transformation should only be used when subsequent
16// stages don't care about const qualifiers. However, the initialization will not be split if the
17// initializer can be written as a HLSL literal.
Olli Etuaho822fa842015-04-16 14:26:10 +030018
19#include "compiler/translator/SeparateArrayInitialization.h"
20
21#include "compiler/translator/IntermNode.h"
Olli Etuaho18b9deb2015-11-05 12:14:50 +020022#include "compiler/translator/OutputHLSL.h"
Olli Etuaho822fa842015-04-16 14:26:10 +030023
Jamie Madill45bcc782016-11-07 13:58:48 -050024namespace sh
25{
26
Olli Etuaho822fa842015-04-16 14:26:10 +030027namespace
28{
29
30class SeparateArrayInitTraverser : private TIntermTraverser
31{
32 public:
33 static void apply(TIntermNode *root);
Jamie Madilld7b1ab52016-12-12 14:42:19 -050034
Olli Etuaho822fa842015-04-16 14:26:10 +030035 private:
36 SeparateArrayInitTraverser();
Olli Etuaho13389b62016-10-16 11:48:18 +010037 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
Olli Etuaho822fa842015-04-16 14:26:10 +030038};
39
40void SeparateArrayInitTraverser::apply(TIntermNode *root)
41{
42 SeparateArrayInitTraverser separateInit;
43 root->traverse(&separateInit);
44 separateInit.updateTree();
45}
46
Jamie Madilld7b1ab52016-12-12 14:42:19 -050047SeparateArrayInitTraverser::SeparateArrayInitTraverser() : TIntermTraverser(true, false, false)
Olli Etuaho822fa842015-04-16 14:26:10 +030048{
49}
50
Olli Etuaho13389b62016-10-16 11:48:18 +010051bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
Olli Etuaho822fa842015-04-16 14:26:10 +030052{
Olli Etuaho13389b62016-10-16 11:48:18 +010053 TIntermSequence *sequence = node->getSequence();
54 TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
55 if (initNode != nullptr && initNode->getOp() == EOpInitialize)
Olli Etuaho822fa842015-04-16 14:26:10 +030056 {
Olli Etuaho13389b62016-10-16 11:48:18 +010057 TIntermTyped *initializer = initNode->getRight();
Olli Etuahoea22b7a2018-01-04 17:09:11 +020058 if (initializer->isArray() && !initializer->hasConstantValue())
Olli Etuaho822fa842015-04-16 14:26:10 +030059 {
Olli Etuaho13389b62016-10-16 11:48:18 +010060 // We rely on that array declarations have been isolated to single declarations.
61 ASSERT(sequence->size() == 1);
62 TIntermTyped *symbol = initNode->getLeft();
63 TIntermBlock *parentBlock = getParentNode()->getAsBlock();
64 ASSERT(parentBlock != nullptr);
Olli Etuaho822fa842015-04-16 14:26:10 +030065
Olli Etuaho13389b62016-10-16 11:48:18 +010066 TIntermSequence replacements;
Olli Etuaho822fa842015-04-16 14:26:10 +030067
Olli Etuaho13389b62016-10-16 11:48:18 +010068 TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
69 replacementDeclaration->appendDeclarator(symbol);
70 replacementDeclaration->setLine(symbol->getLine());
71 replacements.push_back(replacementDeclaration);
Olli Etuaho822fa842015-04-16 14:26:10 +030072
Olli Etuaho13389b62016-10-16 11:48:18 +010073 TIntermBinary *replacementAssignment =
74 new TIntermBinary(EOpAssign, symbol, initializer);
75 replacementAssignment->setLine(symbol->getLine());
76 replacements.push_back(replacementAssignment);
Olli Etuaho822fa842015-04-16 14:26:10 +030077
Olli Etuaho13389b62016-10-16 11:48:18 +010078 mMultiReplacements.push_back(
79 NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
Olli Etuaho822fa842015-04-16 14:26:10 +030080 }
Olli Etuaho822fa842015-04-16 14:26:10 +030081 }
Olli Etuaho13389b62016-10-16 11:48:18 +010082 return false;
Olli Etuaho822fa842015-04-16 14:26:10 +030083}
84
Jamie Madilld7b1ab52016-12-12 14:42:19 -050085} // namespace
Olli Etuaho822fa842015-04-16 14:26:10 +030086
87void SeparateArrayInitialization(TIntermNode *root)
88{
89 SeparateArrayInitTraverser::apply(root);
90}
Jamie Madill45bcc782016-11-07 13:58:48 -050091
92} // namespace sh