Store referenced interface blocks in a cleaner data structure

The previous code was hard to read since the referenced interface
blocks stored a different type of node depending on if the interface
block was instanced or not.

BUG=angleproject:2267
TEST=angle_unittests

Change-Id: Ie8fdb61a17280ca0875159702f819b884d08706b
Reviewed-on: https://chromium-review.googlesource.com/839443
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index ccd6037..04ce8eb 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -82,6 +82,12 @@
 
 }  // anonymous namespace
 
+TReferencedBlock::TReferencedBlock(const TInterfaceBlock *aBlock,
+                                   const TVariable *aInstanceVariable)
+    : block(aBlock), instanceVariable(aInstanceVariable)
+{
+}
+
 void OutputHLSL::writeFloat(TInfoSinkBase &out, float f)
 {
     // This is known not to work for NaN on all drivers but make the best effort to output NaNs
@@ -896,7 +902,16 @@
 
             if (interfaceBlock)
             {
-                mReferencedUniformBlocks[interfaceBlock->uniqueId().get()] = node;
+                if (mReferencedUniformBlocks.count(interfaceBlock->uniqueId().get()) == 0)
+                {
+                    const TVariable *instanceVariable = nullptr;
+                    if (variableType.isInterfaceBlock())
+                    {
+                        instanceVariable = &variable;
+                    }
+                    mReferencedUniformBlocks[interfaceBlock->uniqueId().get()] =
+                        new TReferencedBlock(interfaceBlock, instanceVariable);
+                }
             }
             else
             {
@@ -1242,10 +1257,13 @@
             {
                 if (visit == PreVisit)
                 {
-                    TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock();
                     TIntermSymbol *instanceArraySymbol = node->getLeft()->getAsSymbolNode();
-                    mReferencedUniformBlocks[interfaceBlock->uniqueId().get()] =
-                        instanceArraySymbol;
+                    TInterfaceBlock *interfaceBlock    = leftType.getInterfaceBlock();
+                    if (mReferencedUniformBlocks.count(interfaceBlock->uniqueId().get()) == 0)
+                    {
+                        mReferencedUniformBlocks[interfaceBlock->uniqueId().get()] =
+                            new TReferencedBlock(interfaceBlock, &instanceArraySymbol->variable());
+                    }
                     const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
                     out << mUniformHLSL->UniformBlockInstanceString(instanceArraySymbol->getName(),
                                                                     arrayIndex);
diff --git a/src/compiler/translator/OutputHLSL.h b/src/compiler/translator/OutputHLSL.h
index f046927..0e4135c 100644
--- a/src/compiler/translator/OutputHLSL.h
+++ b/src/compiler/translator/OutputHLSL.h
@@ -24,13 +24,22 @@
 class StructureHLSL;
 class TextureFunctionHLSL;
 class TSymbolTable;
+class TVariable;
 class ImageFunctionHLSL;
 class UnfoldShortCircuit;
 class UniformHLSL;
 
-// Maps from uniqueId to a symbol node or a variable.
-typedef std::map<int, TIntermSymbol *> ReferencedSymbols;
-typedef std::map<int, const TVariable *> ReferencedVariables;
+struct TReferencedBlock : angle::NonCopyable
+{
+    POOL_ALLOCATOR_NEW_DELETE();
+    TReferencedBlock(const TInterfaceBlock *block, const TVariable *instanceVariable);
+    const TInterfaceBlock *block;
+    const TVariable *instanceVariable;  // May be nullptr if the block is not instanced.
+};
+
+// Maps from uniqueId to a variable.
+using ReferencedInterfaceBlocks = std::map<int, const TReferencedBlock *>;
+using ReferencedVariables       = std::map<int, const TVariable *>;
 
 class OutputHLSL : public TIntermTraverser
 {
@@ -158,11 +167,8 @@
 
     ReferencedVariables mReferencedUniforms;
 
-    // Indexed by block id, not instance id. Stored nodes point to either the block instance in
-    // the case of an instanced block, or a member uniform in the case of a non-instanced block.
-    // TODO(oetuaho): Consider a different type of data structure for storing referenced interface
-    // blocks. It needs to know the instance name if any and link to the TInterfaceBlock object.
-    ReferencedSymbols mReferencedUniformBlocks;
+    // Indexed by block id, not instance id.
+    ReferencedInterfaceBlocks mReferencedUniformBlocks;
 
     ReferencedVariables mReferencedAttributes;
     ReferencedVariables mReferencedVaryings;
diff --git a/src/compiler/translator/UniformHLSL.cpp b/src/compiler/translator/UniformHLSL.cpp
index dc467f9..04f0ff7 100644
--- a/src/compiler/translator/UniformHLSL.cpp
+++ b/src/compiler/translator/UniformHLSL.cpp
@@ -457,21 +457,15 @@
     }
 }
 
-TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
+TString UniformHLSL::uniformBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks)
 {
     TString interfaceBlocks;
 
-    for (const auto &interfaceBlockReference : referencedInterfaceBlocks)
+    for (const auto &blockReference : referencedInterfaceBlocks)
     {
-        const TType &nodeType                 = interfaceBlockReference.second->getType();
-        const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
-
-        // nodeType.isInterfaceBlock() == false means the node is a field of a uniform block which
-        // doesn't have instance name.
-        const TString &instanceName =
-            nodeType.isInterfaceBlock() ? interfaceBlockReference.second->getName() : "";
-
-        if (instanceName != "")
+        const TInterfaceBlock &interfaceBlock = *blockReference.second->block;
+        const TVariable *instanceVariable     = blockReference.second->instanceVariable;
+        if (instanceVariable != nullptr)
         {
             interfaceBlocks += uniformBlockStructString(interfaceBlock);
         }
@@ -479,21 +473,20 @@
         unsigned int activeRegister                             = mUniformBlockRegister;
         mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
 
-        if (instanceName != "" && nodeType.isArray())
+        if (instanceVariable != nullptr && instanceVariable->getType().isArray())
         {
-            unsigned int interfaceBlockInstanceArraySize = nodeType.getOutermostArraySize();
-            for (unsigned int arrayIndex = 0; arrayIndex < interfaceBlockInstanceArraySize;
-                 arrayIndex++)
+            unsigned int instanceArraySize = instanceVariable->getType().getOutermostArraySize();
+            for (unsigned int arrayIndex = 0; arrayIndex < instanceArraySize; arrayIndex++)
             {
-                interfaceBlocks += uniformBlockString(interfaceBlock, instanceName,
+                interfaceBlocks += uniformBlockString(interfaceBlock, instanceVariable,
                                                       activeRegister + arrayIndex, arrayIndex);
             }
-            mUniformBlockRegister += interfaceBlockInstanceArraySize;
+            mUniformBlockRegister += instanceArraySize;
         }
         else
         {
-            interfaceBlocks +=
-                uniformBlockString(interfaceBlock, instanceName, activeRegister, GL_INVALID_INDEX);
+            interfaceBlocks += uniformBlockString(interfaceBlock, instanceVariable, activeRegister,
+                                                  GL_INVALID_INDEX);
             mUniformBlockRegister += 1u;
         }
     }
@@ -502,7 +495,7 @@
 }
 
 TString UniformHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock,
-                                        const TString &instanceName,
+                                        const TVariable *instanceVariable,
                                         unsigned int registerIndex,
                                         unsigned int arrayIndex)
 {
@@ -515,10 +508,10 @@
             ")\n"
             "{\n";
 
-    if (instanceName != "")
+    if (instanceVariable != nullptr)
     {
         hlsl += "    " + InterfaceBlockStructName(interfaceBlock) + " " +
-                UniformBlockInstanceString(instanceName, arrayIndex) + ";\n";
+                UniformBlockInstanceString(instanceVariable->name(), arrayIndex) + ";\n";
     }
     else
     {
diff --git a/src/compiler/translator/UniformHLSL.h b/src/compiler/translator/UniformHLSL.h
index 427e713..914d663 100644
--- a/src/compiler/translator/UniformHLSL.h
+++ b/src/compiler/translator/UniformHLSL.h
@@ -37,7 +37,7 @@
     // Must be called after uniformsHeader
     void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg);
 
-    TString uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
+    TString uniformBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks);
 
     // Used for direct index references
     static TString UniformBlockInstanceString(const TString &instanceName, unsigned int arrayIndex);
@@ -53,7 +53,7 @@
 
   private:
     TString uniformBlockString(const TInterfaceBlock &interfaceBlock,
-                               const TString &instanceName,
+                               const TVariable *instanceVariable,
                                unsigned int registerIndex,
                                unsigned int arrayIndex);
     TString uniformBlockMembersString(const TInterfaceBlock &interfaceBlock,