Hash :
4db7ded5
Author :
Date :
2016-10-13T12:23:11
Change comma nodes to TIntermBinary Comma nodes always have just two parameters. If there's an expression with several commas in the middle, it's parsed as a tree of comma operations. It makes more sense to represent it as a binary node rather than an aggregate node. After this patch, TIntermAggregate is still used for function prototypes, function parameter lists, function calls, and variable and invariant declarations. BUG=angleproject:1490 TEST=angle_unittests, angle_end2end_tests Change-Id: I66be10624bf27bcf25987b4d93958d4a07600771 Reviewed-on: https://chromium-review.googlesource.com/397320 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
//
// Copyright (c) 2016 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.
//
// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
// go through further AST transformations that generate statements, and splits them so that
// possible side effects of earlier parts of the sequence operator expression are guaranteed to be
// evaluated before the latter parts of the sequence operator expression are evaluated.
//
#include "compiler/translator/SplitSequenceOperator.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/IntermNodePatternMatcher.h"
namespace
{
class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
{
public:
SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
const TSymbolTable &symbolTable,
int shaderVersion);
bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitTernary(Visit visit, TIntermTernary *node) override;
void nextIteration();
bool foundExpressionToSplit() const { return mFoundExpressionToSplit; }
protected:
// Marked to true once an operation that needs to be hoisted out of the expression has been
// found. After that, no more AST updates are performed on that traversal.
bool mFoundExpressionToSplit;
int mInsideSequenceOperator;
IntermNodePatternMatcher mPatternToSplitMatcher;
};
SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
const TSymbolTable &symbolTable,
int shaderVersion)
: TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
mFoundExpressionToSplit(false),
mInsideSequenceOperator(0),
mPatternToSplitMatcher(patternsToSplitMask)
{
}
void SplitSequenceOperatorTraverser::nextIteration()
{
mFoundExpressionToSplit = false;
mInsideSequenceOperator = 0;
nextTemporaryIndex();
}
bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (mFoundExpressionToSplit)
return false;
if (mInsideSequenceOperator > 0 && visit == PreVisit)
{
// Detect expressions that need to be simplified
mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
return !mFoundExpressionToSplit;
}
return true;
}
bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
if (node->getOp() == EOpComma)
{
if (visit == PreVisit)
{
if (mFoundExpressionToSplit)
{
return false;
}
mInsideSequenceOperator++;
}
else if (visit == PostVisit)
{
// Split sequence operators starting from the outermost one to preserve correct
// execution order.
if (mFoundExpressionToSplit && mInsideSequenceOperator == 1)
{
// Move the left side operand into a separate statement in the parent block.
TIntermSequence insertions;
insertions.push_back(node->getLeft());
insertStatementsInParentBlock(insertions);
// Replace the comma node with its right side operand.
queueReplacement(node, node->getRight(), OriginalNode::IS_DROPPED);
}
mInsideSequenceOperator--;
}
return true;
}
if (mFoundExpressionToSplit)
return false;
if (mInsideSequenceOperator > 0 && visit == PreVisit)
{
// Detect expressions that need to be simplified
mFoundExpressionToSplit =
mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
return !mFoundExpressionToSplit;
}
return true;
}
bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node)
{
if (mFoundExpressionToSplit)
return false;
if (mInsideSequenceOperator > 0 && visit == PreVisit)
{
// Detect expressions that need to be simplified
mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
return !mFoundExpressionToSplit;
}
return true;
}
} // namespace
void SplitSequenceOperator(TIntermNode *root,
int patternsToSplitMask,
unsigned int *temporaryIndex,
const TSymbolTable &symbolTable,
int shaderVersion)
{
SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
ASSERT(temporaryIndex != nullptr);
traverser.useTemporaryIndex(temporaryIndex);
// Separate one expression at a time, and reset the traverser between iterations.
do
{
traverser.nextIteration();
root->traverse(&traverser);
if (traverser.foundExpressionToSplit())
traverser.updateTree();
} while (traverser.foundExpressionToSplit());
}