blob: 2c853e36d629669891e6ee1f120e2a5599909009 [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();
Olli Etuaho13389b62016-10-16 11:48:18 +010032 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
Olli Etuaho822fa842015-04-16 14:26:10 +030033};
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
Olli Etuaho13389b62016-10-16 11:48:18 +010047bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
Olli Etuaho822fa842015-04-16 14:26:10 +030048{
Olli Etuaho13389b62016-10-16 11:48:18 +010049 TIntermSequence *sequence = node->getSequence();
50 TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
51 if (initNode != nullptr && initNode->getOp() == EOpInitialize)
Olli Etuaho822fa842015-04-16 14:26:10 +030052 {
Olli Etuaho13389b62016-10-16 11:48:18 +010053 TIntermTyped *initializer = initNode->getRight();
54 if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
Olli Etuaho822fa842015-04-16 14:26:10 +030055 {
Olli Etuaho13389b62016-10-16 11:48:18 +010056 // We rely on that array declarations have been isolated to single declarations.
57 ASSERT(sequence->size() == 1);
58 TIntermTyped *symbol = initNode->getLeft();
59 TIntermBlock *parentBlock = getParentNode()->getAsBlock();
60 ASSERT(parentBlock != nullptr);
Olli Etuaho822fa842015-04-16 14:26:10 +030061
Olli Etuaho13389b62016-10-16 11:48:18 +010062 TIntermSequence replacements;
Olli Etuaho822fa842015-04-16 14:26:10 +030063
Olli Etuaho13389b62016-10-16 11:48:18 +010064 TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
65 replacementDeclaration->appendDeclarator(symbol);
66 replacementDeclaration->setLine(symbol->getLine());
67 replacements.push_back(replacementDeclaration);
Olli Etuaho822fa842015-04-16 14:26:10 +030068
Olli Etuaho13389b62016-10-16 11:48:18 +010069 TIntermBinary *replacementAssignment =
70 new TIntermBinary(EOpAssign, symbol, initializer);
71 replacementAssignment->setLine(symbol->getLine());
72 replacements.push_back(replacementAssignment);
Olli Etuaho822fa842015-04-16 14:26:10 +030073
Olli Etuaho13389b62016-10-16 11:48:18 +010074 mMultiReplacements.push_back(
75 NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
Olli Etuaho822fa842015-04-16 14:26:10 +030076 }
Olli Etuaho822fa842015-04-16 14:26:10 +030077 }
Olli Etuaho13389b62016-10-16 11:48:18 +010078 return false;
Olli Etuaho822fa842015-04-16 14:26:10 +030079}
80
81} // namespace
82
83void SeparateArrayInitialization(TIntermNode *root)
84{
85 SeparateArrayInitTraverser::apply(root);
86}