Split TIntermBlock from TIntermAggregate
The new TIntermBlock node class replaces TIntermAggregate nodes with
the EOpSequence op. It represents the root node of the tree which is
a list of declarations and function definitions, and any code blocks
that can be denoted by curly braces. These include function and loop
bodies, and if-else branches.
This change enables a bunch of more compile-time type checking, and
makes the AST code easier to understand and less error-prone.
The PostProcess step that used to be done to ensure that the root node
is TIntermAggregate is removed in favor of making sure that the root
node is a TIntermBlock in the glslang.y parsing code.
Intermediate output formatting is improved to print the EOpNull error
in a clearer way.
After this patch, TIntermAggregate is still used for function
definitions, function prototypes, function parameter lists, function
calls, variable and invariant declarations and the comma (sequence)
operator.
BUG=angleproject:1490
TEST=angle_unittests, angle_end2end_tests
Change-Id: I04044affff979a11577bc1fe75d747e538b799c8
Reviewed-on: https://chromium-review.googlesource.com/393726
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 32db9de..ecd47fa 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -24,8 +24,11 @@
{
if (const TIntermAggregate *aggregate = node->getAsAggregate())
{
- return (aggregate->getOp() != EOpFunction) &&
- (aggregate->getOp() != EOpSequence);
+ return (aggregate->getOp() != EOpFunction);
+ }
+ else if (node->getAsBlock())
+ {
+ return false;
}
else if (node->getAsIfElseNode())
{
@@ -753,6 +756,36 @@
}
}
+bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
+{
+ TInfoSinkBase &out = objSink();
+ // Scope the blocks except when at the global scope.
+ if (mDepth > 0)
+ {
+ out << "{\n";
+ }
+
+ incrementDepth(node);
+ for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
+ iter != node->getSequence()->end(); ++iter)
+ {
+ TIntermNode *curNode = *iter;
+ ASSERT(curNode != nullptr);
+ curNode->traverse(this);
+
+ if (isSingleStatement(curNode))
+ out << ";\n";
+ }
+ decrementDepth();
+
+ // Scope the blocks except when at the global scope.
+ if (mDepth > 0)
+ {
+ out << "}\n";
+ }
+ return false;
+}
+
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
{
bool visitChildren = true;
@@ -760,33 +793,6 @@
bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
switch (node->getOp())
{
- case EOpSequence:
- // Scope the sequences except when at the global scope.
- if (mDepth > 0)
- {
- out << "{\n";
- }
-
- incrementDepth(node);
- for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
- iter != node->getSequence()->end(); ++iter)
- {
- TIntermNode *curNode = *iter;
- ASSERT(curNode != NULL);
- curNode->traverse(this);
-
- if (isSingleStatement(curNode))
- out << ";\n";
- }
- decrementDepth();
-
- // Scope the sequences except when at the global scope.
- if (mDepth > 0)
- {
- out << "}\n";
- }
- visitChildren = false;
- break;
case EOpPrototype:
// Function declaration.
ASSERT(visit == PreVisit);
@@ -830,7 +836,7 @@
params->traverse(this);
// Traverse function body.
- TIntermAggregate *body = sequence[1]->getAsAggregate();
+ TIntermBlock *body = sequence[1]->getAsBlock();
visitCodeBlock(body);
decrementDepth();
@@ -1106,7 +1112,7 @@
return true;
}
-void TOutputGLSLBase::visitCodeBlock(TIntermNode *node)
+void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node)
{
TInfoSinkBase &out = objSink();
if (node != NULL)