Hash :
a6f22096
Author :
Date :
2015-05-08T18:31:10
Make UnfoldShortCircuit to change AST instead of writing output This is needed to make way for further AST transformations to handle array expressions that need to work correctly together with unfolding short- circuiting operators. This also improves the maintainability of HLSL output by isolating the unfolding into a separate compilation step. The new version of UnfoldShortCircuit traverser will traverse the tree until an expression that needs to be unfolded is encountered. It then unfolds it and gets reset. The traverser will be run repeatedly until no more operations to unfold are found. This helps with keeping the traverser's design relatively simple. All declarations are separated to single declarations before short-circuit unfolding is run. Previously OutputHLSL already output every declaration separately. BUG=angleproject:960 TEST=WebGL conformance tests, angle_unittests, angle_end2end_tests Change-Id: Id769be396adbd4c0223e418980dc464dd855f019 Reviewed-on: https://chromium-review.googlesource.com/270460 Tested-by: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
//
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// The SeparateDeclarations function processes declarations, so that in the end each declaration
// contains only one declarator.
// This is useful as an intermediate step when initialization needs to be separated from declaration,
// or when things need to be unfolded out of the initializer.
// Example:
// int a[1] = int[1](1), b[1] = int[1](2);
// gets transformed when run through this class into the AST equivalent of:
// int a[1] = int[1](1);
// int b[1] = int[1](2);
#include "compiler/translator/SeparateDeclarations.h"
#include "compiler/translator/IntermNode.h"
namespace
{
class SeparateDeclarationsTraverser : private TIntermTraverser
{
public:
static void apply(TIntermNode *root);
private:
SeparateDeclarationsTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override;
};
void SeparateDeclarationsTraverser::apply(TIntermNode *root)
{
SeparateDeclarationsTraverser separateDecl;
root->traverse(&separateDecl);
separateDecl.updateTree();
}
SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
: TIntermTraverser(true, false, false)
{
}
bool SeparateDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node)
{
if (node->getOp() == EOpDeclaration)
{
TIntermSequence *sequence = node->getSequence();
if (sequence->size() > 1)
{
TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
ASSERT(parentAgg != nullptr);
TIntermSequence replacementDeclarations;
for (size_t ii = 0; ii < sequence->size(); ++ii)
{
TIntermAggregate *replacementDeclaration = new TIntermAggregate;
replacementDeclaration->setOp(EOpDeclaration);
replacementDeclaration->getSequence()->push_back(sequence->at(ii));
replacementDeclaration->setLine(sequence->at(ii)->getLine());
replacementDeclarations.push_back(replacementDeclaration);
}
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacementDeclarations));
}
return false;
}
return true;
}
} // namespace
void SeparateDeclarations(TIntermNode *root)
{
SeparateDeclarationsTraverser::apply(root);
}