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/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 47c3894..f3f59e3 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -31,11 +31,6 @@
namespace
{
-bool IsSequence(TIntermNode *node)
-{
- return node->getAsAggregate() != nullptr && node->getAsAggregate()->getOp() == EOpSequence;
-}
-
void WriteSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion)
{
ASSERT(constUnion != nullptr);
@@ -1418,44 +1413,48 @@
}
}
+bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node)
+{
+ TInfoSinkBase &out = getInfoSink();
+
+ if (mInsideFunction)
+ {
+ outputLineDirective(out, node->getLine().first_line);
+ out << "{\n";
+ }
+
+ for (TIntermSequence::iterator sit = node->getSequence()->begin();
+ sit != node->getSequence()->end(); sit++)
+ {
+ outputLineDirective(out, (*sit)->getLine().first_line);
+
+ (*sit)->traverse(this);
+
+ // Don't output ; after case labels, they're terminated by :
+ // This is needed especially since outputting a ; after a case statement would turn empty
+ // case statements into non-empty case statements, disallowing fall-through from them.
+ // Also no need to output ; after if statements or sequences. This is done just for
+ // code clarity.
+ if ((*sit)->getAsCaseNode() == nullptr && (*sit)->getAsIfElseNode() == nullptr &&
+ (*sit)->getAsBlock() == nullptr)
+ out << ";\n";
+ }
+
+ if (mInsideFunction)
+ {
+ outputLineDirective(out, node->getLine().last_line);
+ out << "}\n";
+ }
+
+ return false;
+}
+
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
TInfoSinkBase &out = getInfoSink();
switch (node->getOp())
{
- case EOpSequence:
- {
- if (mInsideFunction)
- {
- outputLineDirective(out, node->getLine().first_line);
- out << "{\n";
- }
-
- for (TIntermSequence::iterator sit = node->getSequence()->begin(); sit != node->getSequence()->end(); sit++)
- {
- outputLineDirective(out, (*sit)->getLine().first_line);
-
- (*sit)->traverse(this);
-
- // Don't output ; after case labels, they're terminated by :
- // This is needed especially since outputting a ; after a case statement would turn empty
- // case statements into non-empty case statements, disallowing fall-through from them.
- // Also no need to output ; after if statements or sequences. This is done just for
- // code clarity.
- if ((*sit)->getAsCaseNode() == nullptr && (*sit)->getAsIfElseNode() == nullptr &&
- !IsSequence(*sit))
- out << ";\n";
- }
-
- if (mInsideFunction)
- {
- outputLineDirective(out, node->getLine().last_line);
- out << "}\n";
- }
-
- return false;
- }
case EOpDeclaration:
if (visit == PreVisit)
{
@@ -1629,7 +1628,7 @@
ASSERT(sequence->size() == 2);
TIntermNode *body = (*sequence)[1];
// The function body node will output braces.
- ASSERT(IsSequence(body));
+ ASSERT(body->getAsBlock() != nullptr);
body->traverse(this);
mInsideFunction = false;
@@ -1928,8 +1927,6 @@
if (node->getTrueBlock())
{
// The trueBlock child node will output braces.
- ASSERT(IsSequence(node->getTrueBlock()));
-
node->getTrueBlock()->traverse(this);
// Detect true discard
@@ -1951,8 +1948,6 @@
outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
// The falseBlock child node will output braces.
- ASSERT(IsSequence(node->getFalseBlock()));
-
node->getFalseBlock()->traverse(this);
outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
@@ -2092,7 +2087,6 @@
if (node->getBody())
{
// The loop body node will output braces.
- ASSERT(IsSequence(node->getBody()));
node->getBody()->traverse(this);
}
else
@@ -2182,15 +2176,15 @@
bool OutputHLSL::isSingleStatement(TIntermNode *node)
{
- TIntermAggregate *aggregate = node->getAsAggregate();
+ if (node->getAsBlock())
+ {
+ return false;
+ }
+ TIntermAggregate *aggregate = node->getAsAggregate();
if (aggregate)
{
- if (aggregate->getOp() == EOpSequence)
- {
- return false;
- }
- else if (aggregate->getOp() == EOpDeclaration)
+ if (aggregate->getOp() == EOpDeclaration)
{
// Declaring multiple comma-separated variables must be considered multiple statements
// because each individual declaration has side effects which are visible in the next.