Refactoring: Make creating temporary symbols in AST traversal reusable

Temporary symbols will also be needed to store temporary arrays when complex
array expressions are unfolded.

Also clear tree update related structures at the end of updateTree(), so that
the traverser can be reused for several rounds of replacement more easily, and
remove unnecessary InVisit step from UnfoldShortCircuitToIf.

BUG=angleproject:971
TEST=angle_end2end_tests, WebGL conformance tests

Change-Id: Iecdd3008d43f01b02fe344ccde8614f70e6c0c65
Reviewed-on: https://chromium-review.googlesource.com/272121
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index 2f401da..9d5d870 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -5,6 +5,7 @@
 //
 
 #include "compiler/translator/IntermNode.h"
+#include "compiler/translator/InfoSink.h"
 
 void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
 {
@@ -35,6 +36,56 @@
     mInsertions.push_back(insert);
 }
 
+TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
+{
+    // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
+    TInfoSinkBase symbolNameOut;
+    ASSERT(mTemporaryIndex != nullptr);
+    symbolNameOut << "s" << (*mTemporaryIndex);
+    TString symbolName = symbolNameOut.c_str();
+
+    TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
+    node->setInternal(true);
+    node->getTypePointer()->setQualifier(EvqTemporary);
+    return node;
+}
+
+
+TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
+{
+    ASSERT(initializer != nullptr);
+    TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType());
+    TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
+    TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
+    tempInit->setLeft(tempSymbol);
+    tempInit->setRight(initializer);
+    tempInit->setType(tempSymbol->getType());
+    tempDeclaration->getSequence()->push_back(tempInit);
+    return tempDeclaration;
+}
+
+TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
+{
+    ASSERT(rightNode != nullptr);
+    TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
+    TIntermBinary *assignment = new TIntermBinary(EOpAssign);
+    assignment->setLeft(tempSymbol);
+    assignment->setRight(rightNode);
+    assignment->setType(tempSymbol->getType());
+    return assignment;
+}
+
+void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
+{
+    mTemporaryIndex = temporaryIndex;
+}
+
+void TIntermTraverser::nextTemporaryIndex()
+{
+    ASSERT(mTemporaryIndex != nullptr);
+    ++(*mTemporaryIndex);
+}
+
 //
 // Traverse the intermediate representation tree, and
 // call a node type specific function for each node.