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/RewriteElseBlocks.cpp b/src/compiler/translator/RewriteElseBlocks.cpp
index 13d71c7..c9427e2 100644
--- a/src/compiler/translator/RewriteElseBlocks.cpp
+++ b/src/compiler/translator/RewriteElseBlocks.cpp
@@ -26,6 +26,7 @@
 
   protected:
     bool visitAggregate(Visit visit, TIntermAggregate *aggregate) override;
+    bool visitBlock(Visit visit, TIntermBlock *block) override;
 
   private:
     const TType *mFunctionType;
@@ -40,31 +41,29 @@
 
 bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
 {
-    switch (node->getOp())
+    if (node->getOp() == EOpFunction)
     {
-      case EOpSequence:
-        if (visit == PostVisit)
+        // Store the current function context (see comment below)
+        mFunctionType = ((visit == PreVisit) ? &node->getType() : nullptr);
+    }
+    return true;
+}
+
+bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
+{
+    if (visit == PostVisit)
+    {
+        for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
+             statementIndex++)
         {
-            for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++)
+            TIntermNode *statement = (*node->getSequence())[statementIndex];
+            TIntermIfElse *ifElse  = statement->getAsIfElseNode();
+            if (ifElse && ifElse->getFalseBlock() != nullptr)
             {
-                TIntermNode *statement = (*node->getSequence())[statementIndex];
-                TIntermIfElse *ifElse  = statement->getAsIfElseNode();
-                if (ifElse && ifElse->getFalseBlock() != nullptr)
-                {
-                    (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
-                }
+                (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
             }
         }
-        break;
-
-      case EOpFunction:
-        // Store the current function context (see comment below)
-        mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
-        break;
-
-      default: break;
     }
-
     return true;
 }
 
@@ -77,13 +76,13 @@
     TIntermTyped *typedCondition     = ifElse->getCondition()->getAsTyped();
     TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
 
-    TIntermAggregate *falseBlock = nullptr;
+    TIntermBlock *falseBlock = nullptr;
 
     TType boolType(EbtBool, EbpUndefined, EvqTemporary);
 
     if (ifElse->getFalseBlock())
     {
-        TIntermAggregate *negatedElse = nullptr;
+        TIntermBlock *negatedElse = nullptr;
         // crbug.com/346463
         // D3D generates error messages claiming a function has no return value, when rewriting
         // an if-else clause that returns something non-void in a function. By appending dummy
@@ -94,7 +93,7 @@
                 mFunctionType->getBasicString();
             TString rawText = "return (" + typeString + ")0";
             TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
-            negatedElse = new TIntermAggregate(EOpSequence);
+            negatedElse            = new TIntermBlock();
             negatedElse->getSequence()->push_back(returnNode);
         }
 
@@ -102,14 +101,14 @@
         TIntermUnary *negatedCondition     = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
         TIntermIfElse *falseIfElse =
             new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
-        falseBlock = TIntermediate::EnsureSequence(falseIfElse);
+        falseBlock = TIntermediate::EnsureBlock(falseIfElse);
     }
 
     TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
     TIntermIfElse *newIfElse =
         new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
 
-    TIntermAggregate *block = new TIntermAggregate(EOpSequence);
+    TIntermBlock *block = new TIntermBlock();
     block->getSequence()->push_back(storeCondition);
     block->getSequence()->push_back(newIfElse);