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>
diff --git a/src/compiler/translator/SeparateDeclarations.cpp b/src/compiler/translator/SeparateDeclarations.cpp
index 7ea1ce0..d33747f 100644
--- a/src/compiler/translator/SeparateDeclarations.cpp
+++ b/src/compiler/translator/SeparateDeclarations.cpp
@@ -3,9 +3,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// The SeparateArrayDeclarations function processes declarations that contain array declarators. Each declarator in
-// such declarations gets its own declaration.
-// This is useful as an intermediate step when initialization needs to be separated from declaration.
+// 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:
@@ -19,43 +20,33 @@
namespace
{
-class SeparateDeclarations : private TIntermTraverser
+class SeparateDeclarationsTraverser : private TIntermTraverser
{
public:
static void apply(TIntermNode *root);
private:
- SeparateDeclarations();
+ SeparateDeclarationsTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override;
};
-void SeparateDeclarations::apply(TIntermNode *root)
+void SeparateDeclarationsTraverser::apply(TIntermNode *root)
{
- SeparateDeclarations separateDecl;
+ SeparateDeclarationsTraverser separateDecl;
root->traverse(&separateDecl);
separateDecl.updateTree();
}
-SeparateDeclarations::SeparateDeclarations()
+SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
: TIntermTraverser(true, false, false)
{
}
-bool SeparateDeclarations::visitAggregate(Visit, TIntermAggregate *node)
+bool SeparateDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node)
{
if (node->getOp() == EOpDeclaration)
{
TIntermSequence *sequence = node->getSequence();
- bool sequenceContainsArrays = false;
- for (size_t ii = 0; ii < sequence->size(); ++ii)
- {
- TIntermTyped *typed = sequence->at(ii)->getAsTyped();
- if (typed != nullptr && typed->isArray())
- {
- sequenceContainsArrays = true;
- break;
- }
- }
- if (sequence->size() > 1 && sequenceContainsArrays)
+ if (sequence->size() > 1)
{
TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
ASSERT(parentAgg != nullptr);
@@ -80,7 +71,7 @@
} // namespace
-void SeparateArrayDeclarations(TIntermNode *root)
+void SeparateDeclarations(TIntermNode *root)
{
- SeparateDeclarations::apply(root);
+ SeparateDeclarationsTraverser::apply(root);
}