Set proper symbol ids on temporary symbol nodes

Temporary symbols used to all have symbol id 0. Now they get assigned
unique symbol ids. This makes it possible to keep track of them
according to the symbol id instead of their name, paving way to more
robust AST handling in the future.

BUG=angleproject:1490
TEST=angle_unittests

Change-Id: I292e2e483cc39173524fd30a30b48c4c808442e5
Reviewed-on: https://chromium-review.googlesource.com/559335
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/ArrayReturnValueToOutParameter.cpp b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
index 552abc5..5fc885f 100644
--- a/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -60,7 +60,7 @@
 class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
 {
   public:
-    static void apply(TIntermNode *root, unsigned int *temporaryIndex);
+    static void apply(TIntermNode *root, TSymbolUniqueId *temporaryId);
 
   private:
     ArrayReturnValueToOutParameterTraverser();
@@ -74,10 +74,10 @@
     bool mInFunctionWithArrayReturnValue;
 };
 
-void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, unsigned int *temporaryIndex)
+void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
     ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam;
-    arrayReturnValueToOutParam.useTemporaryIndex(temporaryIndex);
+    arrayReturnValueToOutParam.useTemporaryId(temporaryId);
     root->traverse(&arrayReturnValueToOutParam);
     arrayReturnValueToOutParam.updateTree();
 }
@@ -139,7 +139,7 @@
         TIntermBlock *parentBlock = getParentNode()->getAsBlock();
         if (parentBlock)
         {
-            nextTemporaryIndex();
+            nextTemporaryId();
             TIntermSequence replacements;
             replacements.push_back(createTempDeclaration(node->getType()));
             TIntermSymbol *returnSymbol = createTempSymbol(node->getType());
@@ -194,9 +194,9 @@
 
 }  // namespace
 
-void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex)
+void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
-    ArrayReturnValueToOutParameterTraverser::apply(root, temporaryIndex);
+    ArrayReturnValueToOutParameterTraverser::apply(root, temporaryId);
 }
 
 }  // namespace sh
diff --git a/src/compiler/translator/ArrayReturnValueToOutParameter.h b/src/compiler/translator/ArrayReturnValueToOutParameter.h
index 18f5265..cb11194 100644
--- a/src/compiler/translator/ArrayReturnValueToOutParameter.h
+++ b/src/compiler/translator/ArrayReturnValueToOutParameter.h
@@ -12,9 +12,12 @@
 
 namespace sh
 {
-class TIntermNode;
 
-void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex);
+class TIntermNode;
+class TSymbolUniqueId;
+
+void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolUniqueId *temporaryId);
+
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 706bc40..eebc7c8 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -240,7 +240,7 @@
       mDiagnostics(infoSink.info),
       mSourcePath(nullptr),
       mComputeShaderLocalSizeDeclared(false),
-      mTemporaryIndex(0)
+      mTemporaryId()
 {
     mComputeShaderLocalSize.fill(1);
 }
@@ -434,7 +434,7 @@
 
         // This pass might emit short circuits so keep it before the short circuit unfolding
         if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
-            RewriteDoWhile(root, getTemporaryIndex());
+            RewriteDoWhile(root, getTemporaryId());
 
         if (success && (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION))
             sh::AddAndTrueToLoopCondition(root);
@@ -501,7 +501,7 @@
         if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
         {
             ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh,
-                                              &mTemporaryIndex);
+                                              getTemporaryId());
         }
 
         if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
@@ -537,7 +537,7 @@
                                        IntermNodePatternMatcher::kMultiDeclaration |
                                            IntermNodePatternMatcher::kArrayDeclaration |
                                            IntermNodePatternMatcher::kNamelessStructDeclaration,
-                                       getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+                                       getTemporaryId(), getSymbolTable(), getShaderVersion());
             }
             // We only really need to separate array declarations and nameless struct declarations,
             // but it's simpler to just use the regular SeparateDeclarations.
@@ -742,7 +742,7 @@
     nameMap.clear();
 
     mSourcePath     = nullptr;
-    mTemporaryIndex = 0;
+    mTemporaryId    = TSymbolUniqueId();
 }
 
 bool TCompiler::initCallDag(TIntermNode *root)
diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h
index f7cf9e5..4e28026 100644
--- a/src/compiler/translator/Compiler.h
+++ b/src/compiler/translator/Compiler.h
@@ -157,7 +157,7 @@
     const char *getSourcePath() const;
     const TPragma &getPragma() const { return mPragma; }
     void writePragma(ShCompileOptions compileOptions);
-    unsigned int *getTemporaryIndex() { return &mTemporaryIndex; }
+    TSymbolUniqueId *getTemporaryId() { return &mTemporaryId; }
     // Relies on collectVariables having been called.
     bool isVaryingDefined(const char *varyingName);
 
@@ -248,7 +248,7 @@
 
     TPragma mPragma;
 
-    unsigned int mTemporaryIndex;
+    TSymbolUniqueId mTemporaryId;
 };
 
 //
diff --git a/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/src/compiler/translator/ExpandIntegerPowExpressions.cpp
index 9ff2f12..8261e86 100644
--- a/src/compiler/translator/ExpandIntegerPowExpressions.cpp
+++ b/src/compiler/translator/ExpandIntegerPowExpressions.cpp
@@ -22,7 +22,7 @@
 class Traverser : public TIntermTraverser
 {
   public:
-    static void Apply(TIntermNode *root, unsigned int *tempIndex);
+    static void Apply(TIntermNode *root, TSymbolUniqueId *temporaryId);
 
   private:
     Traverser();
@@ -33,10 +33,10 @@
 };
 
 // static
-void Traverser::Apply(TIntermNode *root, unsigned int *tempIndex)
+void Traverser::Apply(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
     Traverser traverser;
-    traverser.useTemporaryIndex(tempIndex);
+    traverser.useTemporaryId(temporaryId);
     do
     {
         traverser.nextIteration();
@@ -55,7 +55,7 @@
 void Traverser::nextIteration()
 {
     mFound = false;
-    nextTemporaryIndex();
+    nextTemporaryId();
 }
 
 bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
@@ -111,7 +111,7 @@
     }
 
     // Potential problem case detected, apply workaround.
-    nextTemporaryIndex();
+    nextTemporaryId();
 
     TIntermTyped *lhs = sequence->at(0)->getAsTyped();
     ASSERT(lhs);
@@ -146,9 +146,9 @@
 
 }  // anonymous namespace
 
-void ExpandIntegerPowExpressions(TIntermNode *root, unsigned int *tempIndex)
+void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
-    Traverser::Apply(root, tempIndex);
+    Traverser::Apply(root, temporaryId);
 }
 
 }  // namespace sh
diff --git a/src/compiler/translator/ExpandIntegerPowExpressions.h b/src/compiler/translator/ExpandIntegerPowExpressions.h
index 8bc8c96..5ab891f 100644
--- a/src/compiler/translator/ExpandIntegerPowExpressions.h
+++ b/src/compiler/translator/ExpandIntegerPowExpressions.h
@@ -16,12 +16,13 @@
 #ifndef COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
 #define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
 
-class TIntermNode;
-
 namespace sh
 {
 
-void ExpandIntegerPowExpressions(TIntermNode *root, unsigned int *tempIndex);
+class TIntermNode;
+class TSymbolUniqueId;
+
+void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolUniqueId *temporaryId);
 
 }  // namespace sh
 
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index aabc90d..9770428 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -997,7 +997,7 @@
     void updateTree();
 
     // Start creating temporary symbols from the given temporary symbol index + 1.
-    void useTemporaryIndex(unsigned int *temporaryIndex);
+    void useTemporaryId(TSymbolUniqueId *temporaryId);
 
     static TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(
         const TType &returnType,
@@ -1123,7 +1123,7 @@
     // Create a node that assigns rightNode to the current temporary symbol.
     TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
     // Increment temporary symbol index.
-    void nextTemporaryIndex();
+    void nextTemporaryId();
 
     enum class OriginalNode
     {
@@ -1200,7 +1200,7 @@
     // All the code blocks from the root to the current node's parent during traversal.
     std::vector<ParentBlock> mParentBlockStack;
 
-    unsigned int *mTemporaryIndex;
+    TSymbolUniqueId *mTemporaryId;
 };
 
 // Traverser parent class that tracks where a node is a destination of a write operation and so is
diff --git a/src/compiler/translator/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index 1819ab8..2b0e4b2 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -108,7 +108,7 @@
       mDepth(-1),
       mMaxDepth(0),
       mInGlobalScope(true),
-      mTemporaryIndex(nullptr)
+      mTemporaryId(nullptr)
 {
 }
 
@@ -167,11 +167,11 @@
     // 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);
+    ASSERT(mTemporaryId != nullptr);
+    symbolNameOut << "s" << (mTemporaryId->get());
     TString symbolName = symbolNameOut.c_str();
 
-    TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
+    TIntermSymbol *node = new TIntermSymbol(mTemporaryId->get(), symbolName, type);
     node->setInternal(true);
 
     ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
@@ -217,15 +217,15 @@
     return assignment;
 }
 
-void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
+void TIntermTraverser::useTemporaryId(TSymbolUniqueId *temporaryId)
 {
-    mTemporaryIndex = temporaryIndex;
+    mTemporaryId = temporaryId;
 }
 
-void TIntermTraverser::nextTemporaryIndex()
+void TIntermTraverser::nextTemporaryId()
 {
-    ASSERT(mTemporaryIndex != nullptr);
-    ++(*mTemporaryIndex);
+    ASSERT(mTemporaryId != nullptr);
+    *mTemporaryId = TSymbolUniqueId();
 }
 
 void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id,
diff --git a/src/compiler/translator/RecordConstantPrecision.cpp b/src/compiler/translator/RecordConstantPrecision.cpp
index 5106f9e..edfd6d5 100644
--- a/src/compiler/translator/RecordConstantPrecision.cpp
+++ b/src/compiler/translator/RecordConstantPrecision.cpp
@@ -145,17 +145,17 @@
 
 void RecordConstantPrecisionTraverser::nextIteration()
 {
-    nextTemporaryIndex();
+    nextTemporaryId();
     mFoundHigherPrecisionConstant = false;
 }
 
 }  // namespace
 
-void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex)
+void RecordConstantPrecision(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
     RecordConstantPrecisionTraverser traverser;
-    ASSERT(temporaryIndex != nullptr);
-    traverser.useTemporaryIndex(temporaryIndex);
+    ASSERT(temporaryId != nullptr);
+    traverser.useTemporaryId(temporaryId);
     // Iterate as necessary, and reset the traverser between iterations.
     do
     {
diff --git a/src/compiler/translator/RecordConstantPrecision.h b/src/compiler/translator/RecordConstantPrecision.h
index cbe92d4..f10428c 100644
--- a/src/compiler/translator/RecordConstantPrecision.h
+++ b/src/compiler/translator/RecordConstantPrecision.h
@@ -20,8 +20,9 @@
 namespace sh
 {
 class TIntermNode;
+class TSymbolUniqueId;
 
-void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex);
+void RecordConstantPrecision(TIntermNode *root, TSymbolUniqueId *temporaryId);
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
diff --git a/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/compiler/translator/RemoveDynamicIndexing.cpp
index 32fe444..9144adf 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -478,15 +478,15 @@
                 initIndex->setLine(node->getLine());
                 insertionsBefore.push_back(initIndex);
 
-                // Create a node for referring to the index after the nextTemporaryIndex() call
+                // Create a node for referring to the index after the nextTemporaryId() call
                 // below.
                 TIntermSymbol *tempIndex = createTempSymbol(indexInitializer->getType());
 
                 TIntermAggregate *indexingCall =
                     CreateIndexFunctionCall(node, tempIndex, indexingFunctionId);
 
-                nextTemporaryIndex();  // From now on, creating temporary symbols that refer to the
-                                       // field value.
+                nextTemporaryId();  // From now on, creating temporary symbols that refer to the
+                                    // field value.
                 insertionsBefore.push_back(createTempInitDeclaration(indexingCall));
 
                 TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall(
@@ -517,19 +517,19 @@
 {
     mUsedTreeInsertion               = false;
     mRemoveIndexSideEffectsInSubtree = false;
-    nextTemporaryIndex();
+    nextTemporaryId();
 }
 
 }  // namespace
 
 void RemoveDynamicIndexing(TIntermNode *root,
-                           unsigned int *temporaryIndex,
+                           TSymbolUniqueId *temporaryId,
                            const TSymbolTable &symbolTable,
                            int shaderVersion)
 {
     RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion);
-    ASSERT(temporaryIndex != nullptr);
-    traverser.useTemporaryIndex(temporaryIndex);
+    ASSERT(temporaryId != nullptr);
+    traverser.useTemporaryId(temporaryId);
     do
     {
         traverser.nextIteration();
diff --git a/src/compiler/translator/RemoveDynamicIndexing.h b/src/compiler/translator/RemoveDynamicIndexing.h
index 06305d0..c0a1056 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.h
+++ b/src/compiler/translator/RemoveDynamicIndexing.h
@@ -15,9 +15,10 @@
 
 class TIntermNode;
 class TSymbolTable;
+class TSymbolUniqueId;
 
 void RemoveDynamicIndexing(TIntermNode *root,
-                           unsigned int *temporaryIndex,
+                           TSymbolUniqueId *temporaryId,
                            const TSymbolTable &symbolTable,
                            int shaderVersion);
 
diff --git a/src/compiler/translator/RewriteDoWhile.cpp b/src/compiler/translator/RewriteDoWhile.cpp
index 7999cbf..e10ec74 100644
--- a/src/compiler/translator/RewriteDoWhile.cpp
+++ b/src/compiler/translator/RewriteDoWhile.cpp
@@ -138,7 +138,7 @@
 
             node->replaceChildNodeWithMultiple(loop, replacement);
 
-            nextTemporaryIndex();
+            nextTemporaryId();
         }
         return true;
     }
@@ -146,12 +146,12 @@
 
 }  // anonymous namespace
 
-void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex)
+void RewriteDoWhile(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
-    ASSERT(temporaryIndex != 0);
+    ASSERT(temporaryId != 0);
 
     DoWhileRewriter rewriter;
-    rewriter.useTemporaryIndex(temporaryIndex);
+    rewriter.useTemporaryId(temporaryId);
 
     root->traverse(&rewriter);
 }
diff --git a/src/compiler/translator/RewriteDoWhile.h b/src/compiler/translator/RewriteDoWhile.h
index 91a7958..9920426 100644
--- a/src/compiler/translator/RewriteDoWhile.h
+++ b/src/compiler/translator/RewriteDoWhile.h
@@ -12,8 +12,12 @@
 
 namespace sh
 {
+
 class TIntermNode;
-void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex);
+class TSymbolUniqueId;
+
+void RewriteDoWhile(TIntermNode *root, TSymbolUniqueId *temporaryId);
+
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
diff --git a/src/compiler/translator/RewriteElseBlocks.cpp b/src/compiler/translator/RewriteElseBlocks.cpp
index 33dd86e..e3d58d8 100644
--- a/src/compiler/translator/RewriteElseBlocks.cpp
+++ b/src/compiler/translator/RewriteElseBlocks.cpp
@@ -67,7 +67,7 @@
 {
     ASSERT(ifElse != nullptr);
 
-    nextTemporaryIndex();
+    nextTemporaryId();
 
     TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
 
@@ -110,10 +110,10 @@
 
 }  // anonymous namespace
 
-void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
+void RewriteElseBlocks(TIntermNode *node, TSymbolUniqueId *temporaryId)
 {
     ElseBlockRewriter rewriter;
-    rewriter.useTemporaryIndex(temporaryIndex);
+    rewriter.useTemporaryId(temporaryId);
     node->traverse(&rewriter);
 }
 
diff --git a/src/compiler/translator/RewriteElseBlocks.h b/src/compiler/translator/RewriteElseBlocks.h
index 05a8634..17fc6b1 100644
--- a/src/compiler/translator/RewriteElseBlocks.h
+++ b/src/compiler/translator/RewriteElseBlocks.h
@@ -15,7 +15,7 @@
 namespace sh
 {
 
-void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex);
+void RewriteElseBlocks(TIntermNode *node, TSymbolUniqueId *temporaryId);
 }
 
 #endif  // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
diff --git a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
index e09241a..1553288 100644
--- a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
+++ b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
@@ -63,12 +63,12 @@
   public:
     ScalarizeArgsTraverser(sh::GLenum shaderType,
                            bool fragmentPrecisionHigh,
-                           unsigned int *temporaryIndex)
+                           TSymbolUniqueId *temporaryId)
         : TIntermTraverser(true, false, false),
           mShaderType(shaderType),
           mFragmentPrecisionHigh(fragmentPrecisionHigh)
     {
-        useTemporaryIndex(temporaryIndex);
+        useTemporaryId(temporaryId);
     }
 
   protected:
@@ -204,7 +204,7 @@
 void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original)
 {
     ASSERT(original);
-    nextTemporaryIndex();
+    nextTemporaryId();
     TIntermDeclaration *decl = createTempInitDeclaration(original);
 
     TType type = original->getType();
@@ -230,9 +230,9 @@
 void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
                                        sh::GLenum shaderType,
                                        bool fragmentPrecisionHigh,
-                                       unsigned int *temporaryIndex)
+                                       TSymbolUniqueId *temporaryId)
 {
-    ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, temporaryIndex);
+    ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, temporaryId);
     root->traverse(&scalarizer);
 }
 
diff --git a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
index 14bbbe1..3a02632 100644
--- a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
+++ b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
@@ -16,11 +16,12 @@
 namespace sh
 {
 class TIntermBlock;
+class TSymbolUniqueId;
 
 void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
                                        sh::GLenum shaderType,
                                        bool fragmentPrecisionHigh,
-                                       unsigned int *temporaryIndex);
+                                       TSymbolUniqueId *temporaryId);
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
diff --git a/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
index 1e7000b..9d45915 100644
--- a/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
+++ b/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
@@ -105,16 +105,16 @@
 void SeparateExpressionsTraverser::nextIteration()
 {
     mFoundArrayExpression = false;
-    nextTemporaryIndex();
+    nextTemporaryId();
 }
 
 }  // namespace
 
-void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex)
+void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
     SeparateExpressionsTraverser traverser;
-    ASSERT(temporaryIndex != nullptr);
-    traverser.useTemporaryIndex(temporaryIndex);
+    ASSERT(temporaryId != nullptr);
+    traverser.useTemporaryId(temporaryId);
     // Separate one expression at a time, and reset the traverser between iterations.
     do
     {
diff --git a/src/compiler/translator/SeparateExpressionsReturningArrays.h b/src/compiler/translator/SeparateExpressionsReturningArrays.h
index 1ed50a0..f5be848 100644
--- a/src/compiler/translator/SeparateExpressionsReturningArrays.h
+++ b/src/compiler/translator/SeparateExpressionsReturningArrays.h
@@ -15,8 +15,9 @@
 namespace sh
 {
 class TIntermNode;
+class TSymbolUniqueId;
 
-void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex);
+void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolUniqueId *temporaryId);
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
diff --git a/src/compiler/translator/SimplifyLoopConditions.cpp b/src/compiler/translator/SimplifyLoopConditions.cpp
index 2e40a76..61d69e5 100644
--- a/src/compiler/translator/SimplifyLoopConditions.cpp
+++ b/src/compiler/translator/SimplifyLoopConditions.cpp
@@ -146,7 +146,7 @@
 
     if (mFoundLoopToChange)
     {
-        nextTemporaryIndex();
+        nextTemporaryId();
 
         // Replace the loop condition with a boolean variable that's updated on each iteration.
         TLoopType loopType = node->getType();
@@ -284,13 +284,13 @@
 
 void SimplifyLoopConditions(TIntermNode *root,
                             unsigned int conditionsToSimplifyMask,
-                            unsigned int *temporaryIndex,
+                            TSymbolUniqueId *temporaryId,
                             const TSymbolTable &symbolTable,
                             int shaderVersion)
 {
     SimplifyLoopConditionsTraverser traverser(conditionsToSimplifyMask, symbolTable, shaderVersion);
-    ASSERT(temporaryIndex != nullptr);
-    traverser.useTemporaryIndex(temporaryIndex);
+    ASSERT(temporaryId != nullptr);
+    traverser.useTemporaryId(temporaryId);
     root->traverse(&traverser);
     traverser.updateTree();
 }
diff --git a/src/compiler/translator/SimplifyLoopConditions.h b/src/compiler/translator/SimplifyLoopConditions.h
index 968089d..a2fcf8f 100644
--- a/src/compiler/translator/SimplifyLoopConditions.h
+++ b/src/compiler/translator/SimplifyLoopConditions.h
@@ -15,10 +15,11 @@
 {
 class TIntermNode;
 class TSymbolTable;
+class TSymbolUniqueId;
 
 void SimplifyLoopConditions(TIntermNode *root,
                             unsigned int conditionsToSimplify,
-                            unsigned int *temporaryIndex,
+                            TSymbolUniqueId *temporaryId,
                             const TSymbolTable &symbolTable,
                             int shaderVersion);
 }  // namespace sh
diff --git a/src/compiler/translator/SplitSequenceOperator.cpp b/src/compiler/translator/SplitSequenceOperator.cpp
index 4c63b59..f42c064 100644
--- a/src/compiler/translator/SplitSequenceOperator.cpp
+++ b/src/compiler/translator/SplitSequenceOperator.cpp
@@ -57,7 +57,7 @@
 {
     mFoundExpressionToSplit = false;
     mInsideSequenceOperator = 0;
-    nextTemporaryIndex();
+    nextTemporaryId();
 }
 
 bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
@@ -138,13 +138,13 @@
 
 void SplitSequenceOperator(TIntermNode *root,
                            int patternsToSplitMask,
-                           unsigned int *temporaryIndex,
+                           TSymbolUniqueId *temporaryId,
                            const TSymbolTable &symbolTable,
                            int shaderVersion)
 {
     SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
-    ASSERT(temporaryIndex != nullptr);
-    traverser.useTemporaryIndex(temporaryIndex);
+    ASSERT(temporaryId != nullptr);
+    traverser.useTemporaryId(temporaryId);
     // Separate one expression at a time, and reset the traverser between iterations.
     do
     {
diff --git a/src/compiler/translator/SplitSequenceOperator.h b/src/compiler/translator/SplitSequenceOperator.h
index 6df9d45..1bcb969 100644
--- a/src/compiler/translator/SplitSequenceOperator.h
+++ b/src/compiler/translator/SplitSequenceOperator.h
@@ -17,10 +17,11 @@
 
 class TIntermNode;
 class TSymbolTable;
+class TSymbolUniqueId;
 
 void SplitSequenceOperator(TIntermNode *root,
                            int patternsToSplitMask,
-                           unsigned int *temporaryIndex,
+                           TSymbolUniqueId *temporaryId,
                            const TSymbolTable &symbolTable,
                            int shaderVersion);
 
diff --git a/src/compiler/translator/TranslatorESSL.cpp b/src/compiler/translator/TranslatorESSL.cpp
index 5d58430..aef369f 100644
--- a/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/compiler/translator/TranslatorESSL.cpp
@@ -62,7 +62,7 @@
         emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
     }
 
-    RecordConstantPrecision(root, getTemporaryIndex());
+    RecordConstantPrecision(root, getTemporaryId());
 
     // Write emulated built-in functions if needed.
     if (!getBuiltInFunctionEmulator().isOutputEmpty())
diff --git a/src/compiler/translator/TranslatorHLSL.cpp b/src/compiler/translator/TranslatorHLSL.cpp
index 67cd53f..dada1ee 100644
--- a/src/compiler/translator/TranslatorHLSL.cpp
+++ b/src/compiler/translator/TranslatorHLSL.cpp
@@ -46,7 +46,7 @@
                                IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
                                IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue |
                                IntermNodePatternMatcher::kMultiDeclaration,
-                           getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+                           getTemporaryId(), getSymbolTable(), getShaderVersion());
 
     // Note that separate declarations need to be run before other AST transformations that
     // generate new statements from expressions.
@@ -56,31 +56,31 @@
                           IntermNodePatternMatcher::kExpressionReturningArray |
                               IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
                               IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
-                          getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+                          getTemporaryId(), getSymbolTable(), getShaderVersion());
 
     // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
-    UnfoldShortCircuitToIf(root, getTemporaryIndex());
+    UnfoldShortCircuitToIf(root, getTemporaryId());
 
-    SeparateExpressionsReturningArrays(root, getTemporaryIndex());
+    SeparateExpressionsReturningArrays(root, getTemporaryId());
 
     // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
     SeparateArrayInitialization(root);
 
     // HLSL doesn't support arrays as return values, we'll need to make functions that have an array
     // as a return value to use an out parameter to transfer the array data instead.
-    ArrayReturnValueToOutParameter(root, getTemporaryIndex());
+    ArrayReturnValueToOutParameter(root, getTemporaryId());
 
     if (!shouldRunLoopAndIndexingValidation(compileOptions))
     {
         // HLSL doesn't support dynamic indexing of vectors and matrices.
-        RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+        RemoveDynamicIndexing(root, getTemporaryId(), getSymbolTable(), getShaderVersion());
     }
 
     // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
     // use a vertex attribute as a condition, and some related computation in the else block.
     if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
     {
-        sh::RewriteElseBlocks(root, getTemporaryIndex());
+        sh::RewriteElseBlocks(root, getTemporaryId());
     }
 
     // Work around an HLSL compiler frontend aliasing optimization bug.
@@ -103,7 +103,7 @@
 
     if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0)
     {
-        sh::ExpandIntegerPowExpressions(root, getTemporaryIndex());
+        sh::ExpandIntegerPowExpressions(root, getTemporaryId());
     }
 
     if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
diff --git a/src/compiler/translator/UnfoldShortCircuitToIf.cpp b/src/compiler/translator/UnfoldShortCircuitToIf.cpp
index 3751128..0a3f696 100644
--- a/src/compiler/translator/UnfoldShortCircuitToIf.cpp
+++ b/src/compiler/translator/UnfoldShortCircuitToIf.cpp
@@ -165,16 +165,16 @@
 void UnfoldShortCircuitTraverser::nextIteration()
 {
     mFoundShortCircuit = false;
-    nextTemporaryIndex();
+    nextTemporaryId();
 }
 
 }  // namespace
 
-void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex)
+void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolUniqueId *temporaryId)
 {
     UnfoldShortCircuitTraverser traverser;
-    ASSERT(temporaryIndex != nullptr);
-    traverser.useTemporaryIndex(temporaryIndex);
+    ASSERT(temporaryId != nullptr);
+    traverser.useTemporaryId(temporaryId);
     // Unfold one operator at a time, and reset the traverser between iterations.
     do
     {
diff --git a/src/compiler/translator/UnfoldShortCircuitToIf.h b/src/compiler/translator/UnfoldShortCircuitToIf.h
index b1ff064..bb9933e 100644
--- a/src/compiler/translator/UnfoldShortCircuitToIf.h
+++ b/src/compiler/translator/UnfoldShortCircuitToIf.h
@@ -14,9 +14,12 @@
 
 namespace sh
 {
-class TIntermNode;
 
-void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex);
+class TIntermNode;
+class TSymbolUniqueId;
+
+void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolUniqueId *temporaryId);
+
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/compiler/translator/intermOut.cpp b/src/compiler/translator/intermOut.cpp
index d3e48ed..fe65249 100644
--- a/src/compiler/translator/intermOut.cpp
+++ b/src/compiler/translator/intermOut.cpp
@@ -88,7 +88,9 @@
     OutputTreeText(sink, node, mDepth);
 
     sink << "'" << node->getSymbol() << "' ";
-    sink << "(" << node->getCompleteString() << ")\n";
+    sink << "(symbol id " << node->getId() << ") ";
+    sink << "(" << node->getCompleteString() << ")";
+    sink << "\n";
 }
 
 bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)