Split vector swizzle AST nodes into a different node class

This avoids creating a weird aggregate node with a sequence of
constant union nodes to store the offsets. They're stored neatly
inside a vector instead. This makes code that needs to iterate
over the swizzle offsets much simpler.

BUG=angleproject:1490
TEST=angle_unittests

Change-Id: I156b95723529ee05a94d30295ffb6d0952a98564
Reviewed-on: https://chromium-review.googlesource.com/390832
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/intermOut.cpp b/src/compiler/translator/intermOut.cpp
index 2eb0441..aed53d4 100644
--- a/src/compiler/translator/intermOut.cpp
+++ b/src/compiler/translator/intermOut.cpp
@@ -42,6 +42,7 @@
   protected:
     void visitSymbol(TIntermSymbol *) override;
     void visitConstantUnion(TIntermConstantUnion *) override;
+    bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
     bool visitBinary(Visit visit, TIntermBinary *) override;
     bool visitUnary(Visit visit, TIntermUnary *) override;
     bool visitTernary(Visit visit, TIntermTernary *node) override;
@@ -84,6 +85,14 @@
     sink << "(" << node->getCompleteString() << ")\n";
 }
 
+bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
+{
+    TInfoSinkBase &out = sink;
+    OutputTreeText(out, node, mDepth);
+    out << "vector swizzle";
+    return true;
+}
+
 bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
 {
     TInfoSinkBase& out = sink;
@@ -153,9 +162,6 @@
       case EOpIndexDirectInterfaceBlock:
         out << "direct index for interface block";
         break;
-      case EOpVectorSwizzle:
-        out << "vector swizzle";
-        break;
 
       case EOpAdd:
         out << "add";