Make AST path always include the current node being traversed
AST traversers tend to sometimes call traverse() functions manually
during PreVisit. Change TIntermTraverser so that even if this happens,
all the nodes are automatically added to the traversal path, instead
of having to add them manually in each individual AST traverser.
This also makes calling getParentNode() return the correct node during
InVisit.
This does cause the same node being added to the traversal path twice
in some cases, where nodes are repeatedly traversed, like in
OutputHLSL, but this should not have adverse side effects. The more
common case is that the traverse() function is called on the children
of the node being currently traversed.
This fixes a bug in OVR_multiview validation, which did not previously
call incrementDepth and decrementDepth when it should have.
BUG=angleproject:1725
TEST=angle_unittests, angle_end2end_tests
Change-Id: I6ae762eef760509ebe853eefa37dac28c16e7a9b
Reviewed-on: https://chromium-review.googlesource.com/430732
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index 36f8f5a..b5d42cc 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -105,7 +105,7 @@
: preVisit(preVisit),
inVisit(inVisit),
postVisit(postVisit),
- mDepth(0),
+ mDepth(-1),
mMaxDepth(0),
mInGlobalScope(true),
mTemporaryIndex(nullptr)
@@ -142,8 +142,16 @@
const TIntermSequence &insertionsAfter)
{
ASSERT(!mParentBlockStack.empty());
- NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
- insertionsBefore, insertionsAfter);
+ ParentBlock &parentBlock = mParentBlockStack.back();
+ if (mPath.back() == parentBlock.node)
+ {
+ ASSERT(mParentBlockStack.size() >= 2u);
+ // The current node is a block node, so the parent block is not the topmost one in the block
+ // stack, but the one below that.
+ parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u);
+ }
+ NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore,
+ insertionsAfter);
mInsertions.push_back(insert);
}
@@ -264,16 +272,20 @@
//
void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitSymbol(node);
}
void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitConstantUnion(node);
}
void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -281,11 +293,7 @@
if (visit)
{
- incrementDepth(node);
-
node->getOperand()->traverse(this);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -297,6 +305,8 @@
//
void TIntermTraverser::traverseBinary(TIntermBinary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
//
@@ -310,8 +320,6 @@
//
if (visit)
{
- incrementDepth(node);
-
if (node->getLeft())
node->getLeft()->traverse(this);
@@ -320,8 +328,6 @@
if (visit && node->getRight())
node->getRight()->traverse(this);
-
- decrementDepth();
}
//
@@ -334,6 +340,8 @@
void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
//
@@ -347,8 +355,6 @@
//
if (visit)
{
- incrementDepth(node);
-
// Some binary operations like indexing can be inside an expression which must be an
// l-value.
bool parentOperatorRequiresLValue = operatorRequiresLValue();
@@ -383,8 +389,6 @@
setOperatorRequiresLValue(parentOperatorRequiresLValue);
setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
-
- decrementDepth();
}
//
@@ -400,6 +404,8 @@
//
void TIntermTraverser::traverseUnary(TIntermUnary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -407,11 +413,7 @@
if (visit)
{
- incrementDepth(node);
-
node->getOperand()->traverse(this);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -420,6 +422,8 @@
void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -427,8 +431,6 @@
if (visit)
{
- incrementDepth(node);
-
ASSERT(!operatorRequiresLValue());
switch (node->getOp())
{
@@ -445,8 +447,6 @@
node->getOperand()->traverse(this);
setOperatorRequiresLValue(false);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -456,6 +456,8 @@
// Traverse a function definition node.
void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -463,7 +465,6 @@
if (visit)
{
- incrementDepth(node);
mInGlobalScope = false;
node->getFunctionPrototype()->traverse(this);
@@ -472,7 +473,6 @@
node->getBody()->traverse(this);
mInGlobalScope = true;
- decrementDepth();
}
if (visit && postVisit)
@@ -482,6 +482,9 @@
// Traverse a block node.
void TIntermTraverser::traverseBlock(TIntermBlock *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+ pushParentBlock(node);
+
bool visit = true;
TIntermSequence *sequence = node->getSequence();
@@ -491,9 +494,6 @@
if (visit)
{
- incrementDepth(node);
- pushParentBlock(node);
-
for (auto *child : *sequence)
{
child->traverse(this);
@@ -505,17 +505,18 @@
incrementParentBlockPos();
}
-
- popParentBlock();
- decrementDepth();
}
if (visit && postVisit)
visitBlock(PostVisit, node);
+
+ popParentBlock();
}
void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -536,6 +537,8 @@
// Traverse a declaration node.
void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
TIntermSequence *sequence = node->getSequence();
@@ -545,8 +548,6 @@
if (visit)
{
- incrementDepth(node);
-
for (auto *child : *sequence)
{
child->traverse(this);
@@ -556,8 +557,6 @@
visit = visitDeclaration(InVisit, node);
}
}
-
- decrementDepth();
}
if (visit && postVisit)
@@ -566,6 +565,8 @@
void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
TIntermSequence *sequence = node->getSequence();
@@ -575,8 +576,6 @@
if (visit)
{
- incrementDepth(node);
-
for (auto *child : *sequence)
{
child->traverse(this);
@@ -586,8 +585,6 @@
visit = visitFunctionPrototype(InVisit, node);
}
}
-
- decrementDepth();
}
if (visit && postVisit)
@@ -597,6 +594,8 @@
// Traverse an aggregate node. Same comments in binary node apply here.
void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
TIntermSequence *sequence = node->getSequence();
@@ -606,8 +605,6 @@
if (visit)
{
- incrementDepth(node);
-
for (auto *child : *sequence)
{
child->traverse(this);
@@ -617,8 +614,6 @@
visit = visitAggregate(InVisit, node);
}
}
-
- decrementDepth();
}
if (visit && postVisit)
@@ -635,6 +630,8 @@
void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
TIntermSequence *sequence = node->getSequence();
@@ -656,8 +653,6 @@
}
}
- incrementDepth(node);
-
if (inFunctionMap)
{
TIntermSequence *params = getFunctionParameters(node);
@@ -728,8 +723,6 @@
setInFunctionCallOutParameter(false);
}
-
- decrementDepth();
}
if (visit && postVisit)
@@ -741,6 +734,8 @@
//
void TIntermTraverser::traverseTernary(TIntermTernary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -748,13 +743,11 @@
if (visit)
{
- incrementDepth(node);
node->getCondition()->traverse(this);
if (node->getTrueExpression())
node->getTrueExpression()->traverse(this);
if (node->getFalseExpression())
node->getFalseExpression()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -764,6 +757,8 @@
// Traverse an if-else node. Same comments in binary node apply here.
void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -771,13 +766,11 @@
if (visit)
{
- incrementDepth(node);
node->getCondition()->traverse(this);
if (node->getTrueBlock())
node->getTrueBlock()->traverse(this);
if (node->getFalseBlock())
node->getFalseBlock()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -789,6 +782,8 @@
//
void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -796,13 +791,11 @@
if (visit)
{
- incrementDepth(node);
node->getInit()->traverse(this);
if (inVisit)
visit = visitSwitch(InVisit, node);
if (visit && node->getStatementList())
node->getStatementList()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -814,6 +807,8 @@
//
void TIntermTraverser::traverseCase(TIntermCase *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -821,9 +816,7 @@
if (visit && node->getCondition())
{
- incrementDepth(node);
node->getCondition()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -835,6 +828,8 @@
//
void TIntermTraverser::traverseLoop(TIntermLoop *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -842,8 +837,6 @@
if (visit)
{
- incrementDepth(node);
-
if (node->getInit())
node->getInit()->traverse(this);
@@ -855,8 +848,6 @@
if (node->getExpression())
node->getExpression()->traverse(this);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -868,6 +859,8 @@
//
void TIntermTraverser::traverseBranch(TIntermBranch *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -875,9 +868,7 @@
if (visit && node->getExpression())
{
- incrementDepth(node);
node->getExpression()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -886,6 +877,7 @@
void TIntermTraverser::traverseRaw(TIntermRaw *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitRaw(node);
}