Fix VectorizeVectorScalarArithmetic statement insertion

The traverser must avoid inserting two statements to the same position
on a single traversal, so it doesn't trigger an assert.

BUG=chromium:784078
TEST=angle_unittests

Change-Id: I855054e62cc1b1cf4e6bb02af527954151c7d0e7
Reviewed-on: https://chromium-review.googlesource.com/771611
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 53ff8f9..6c25c6c 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -122,6 +122,15 @@
 {
 }
 
+const TIntermBlock *TIntermTraverser::getParentBlock() const
+{
+    if (!mParentBlockStack.empty())
+    {
+        return mParentBlockStack.back().node;
+    }
+    return nullptr;
+}
+
 void TIntermTraverser::pushParentBlock(TIntermBlock *node)
 {
     mParentBlockStack.push_back(ParentBlock(node, 0));
diff --git a/src/compiler/translator/IntermTraverse.h b/src/compiler/translator/IntermTraverse.h
index d9912c3..f0300b5 100644
--- a/src/compiler/translator/IntermTraverse.h
+++ b/src/compiler/translator/IntermTraverse.h
@@ -143,6 +143,8 @@
         return nullptr;
     }
 
+    const TIntermBlock *getParentBlock() const;
+
     void pushParentBlock(TIntermBlock *node);
     void incrementParentBlockPos();
     void popParentBlock();
diff --git a/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp b/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
index d1ea069..1e79a60 100644
--- a/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
+++ b/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
@@ -11,6 +11,8 @@
 
 #include "compiler/translator/VectorizeVectorScalarArithmetic.h"
 
+#include <set>
+
 #include "compiler/translator/IntermNode.h"
 #include "compiler/translator/IntermTraverse.h"
 
@@ -29,7 +31,11 @@
     }
 
     bool didReplaceScalarsWithVectors() { return mReplaced; }
-    void nextIteration() { mReplaced = false; }
+    void nextIteration()
+    {
+        mReplaced = false;
+        mModifiedBlocks.clear();
+    }
 
   protected:
     bool visitBinary(Visit visit, TIntermBinary *node) override;
@@ -47,6 +53,7 @@
                                    TIntermTraverser::OriginalNode *originalNodeFate);
 
     bool mReplaced;
+    std::set<const TIntermBlock *> mModifiedBlocks;
 };
 
 TIntermTyped *VectorizeVectorScalarArithmeticTraverser::Vectorize(
@@ -241,11 +248,17 @@
             // leave that be.
             if (!argBinary->getLeft()->hasSideEffects())
             {
-                replaceAssignInsideConstructor(node, argBinary);
-                mReplaced = true;
-                // Don't replace more nodes in the same subtree on this traversal.
-                // However, nodes elsewhere in the tree may still be replaced.
-                return false;
+                const TIntermBlock *parentBlock = getParentBlock();
+                // We can't do more than one insertion to the same block on the same traversal.
+                if (mModifiedBlocks.find(parentBlock) == mModifiedBlocks.end())
+                {
+                    replaceAssignInsideConstructor(node, argBinary);
+                    mModifiedBlocks.insert(parentBlock);
+                    mReplaced = true;
+                    // Don't replace more nodes in the same subtree on this traversal.
+                    // However, nodes elsewhere in the tree may still be replaced.
+                    return false;
+                }
             }
             break;
         }