Clean up storing interface blocks in the symbol table

Merge TInterfaceBlock with TInterfaceBlockName, so that there are no
duplicate data structures for interface blocks. This is similar to the
refactoring that was already done to structs.

BUG=angleproject:2267
TEST=angle_unittests

Change-Id: I67d2af6ccbe5344bddf9c99030d118fe532fbbd8
Reviewed-on: https://chromium-review.googlesource.com/805819
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/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 49da220..df67a31 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -573,7 +573,7 @@
 
         const TFieldList &fields = structure->fields();
 
-        for (TField *field : fields)
+        for (const TField *field : fields)
         {
             // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
             // ShaderVariable objects.
diff --git a/src/compiler/translator/FlagStd140Structs.cpp b/src/compiler/translator/FlagStd140Structs.cpp
index fba837f..37f7225 100644
--- a/src/compiler/translator/FlagStd140Structs.cpp
+++ b/src/compiler/translator/FlagStd140Structs.cpp
@@ -9,6 +9,7 @@
 #include "compiler/translator/FlagStd140Structs.h"
 
 #include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
 
 namespace sh
 {
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index 8d65a6f..6f6ee43 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -1015,29 +1015,31 @@
 
             // Add built-in interface block gl_PerVertex and the built-in array gl_in.
             // TODO(jiawei.shao@intel.com): implement GL_OES_geometry_point_size.
-            const TString *glPerVertexString = NewPoolTString("gl_PerVertex");
-            symbolTable.insertInterfaceBlockNameExt(ESSL3_1_BUILTINS, extension, glPerVertexString);
-
-            TFieldList *fieldList    = new TFieldList();
+            TFieldList *glPerVertexFieldList = new TFieldList();
             TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
             TField *glPositionField  = new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4),
                                                  NewPoolTString("gl_Position"), zeroSourceLoc);
-            fieldList->push_back(glPositionField);
+            glPerVertexFieldList->push_back(glPositionField);
 
-            TInterfaceBlock *glInBlock =
-                new TInterfaceBlock(glPerVertexString, fieldList, TLayoutQualifier::Create());
+            const TString *glPerVertexString    = NewPoolTString("gl_PerVertex");
+            TInterfaceBlock *glPerVertexInBlock = new TInterfaceBlock(
+                &symbolTable, glPerVertexString, glPerVertexFieldList, TLayoutQualifier::Create());
+            glPerVertexInBlock->relateToExtension(extension);
+            symbolTable.insertInterfaceBlock(ESSL3_1_BUILTINS, glPerVertexInBlock);
 
             // The array size of gl_in is undefined until we get a valid input primitive
             // declaration.
-            TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::Create());
+            TType glInType(glPerVertexInBlock, EvqPerVertexIn, TLayoutQualifier::Create());
             glInType.makeArray(0u);
             symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType);
 
+            TInterfaceBlock *glPerVertexOutBlock = new TInterfaceBlock(
+                &symbolTable, glPerVertexString, glPerVertexFieldList, TLayoutQualifier::Create());
             TType glPositionType(EbtFloat, EbpHigh, EvqPosition, 4);
-            glPositionType.setInterfaceBlock(
-                new TInterfaceBlock(glPerVertexString, fieldList, TLayoutQualifier::Create()));
+            glPositionType.setInterfaceBlock(glPerVertexOutBlock);
             symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Position",
                                           glPositionType);
+
             symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveIDIn",
                                           TType(EbtInt, EbpHigh, EvqPrimitiveIDIn, 1));
             symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_InvocationID",
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 7149cde..e346b8b 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -3713,11 +3713,6 @@
 
     checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
 
-    if (!symbolTable.declareInterfaceBlockName(&blockName))
-    {
-        error(nameLine, "redefinition of an interface block name", blockName.c_str());
-    }
-
     // check for sampler types and apply layout qualifiers
     for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
     {
@@ -3814,7 +3809,12 @@
     }
 
     TInterfaceBlock *interfaceBlock =
-        new TInterfaceBlock(&blockName, fieldList, blockLayoutQualifier);
+        new TInterfaceBlock(&symbolTable, &blockName, fieldList, blockLayoutQualifier);
+    if (!symbolTable.declareInterfaceBlock(interfaceBlock))
+    {
+        error(nameLine, "redefinition of an interface block name", blockName.c_str());
+    }
+
     TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
     if (arrayIndex != nullptr)
     {
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 62bd3ba..adf1e4e 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -70,6 +70,17 @@
     *mutableName         = name;
 }
 
+TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
+                                 const TString *name,
+                                 const TFieldList *fields,
+                                 const TLayoutQualifier &layoutQualifier)
+    : TSymbol(symbolTable, name),
+      TFieldListCollection(fields),
+      mBlockStorage(layoutQualifier.blockStorage),
+      mBinding(layoutQualifier.binding)
+{
+}
+
 //
 // Functions have buried pointers to delete.
 //
@@ -315,27 +326,9 @@
     return insertStructType(currentLevel(), str);
 }
 
-TInterfaceBlockName *TSymbolTable::declareInterfaceBlockName(const TString *name)
+bool TSymbolTable::declareInterfaceBlock(TInterfaceBlock *interfaceBlock)
 {
-    TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
-    if (insert(currentLevel(), blockNameSymbol))
-    {
-        return blockNameSymbol;
-    }
-    return nullptr;
-}
-
-TInterfaceBlockName *TSymbolTable::insertInterfaceBlockNameExt(ESymbolLevel level,
-                                                               TExtension ext,
-                                                               const TString *name)
-{
-    TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
-    blockNameSymbol->relateToExtension(ext);
-    if (insert(level, blockNameSymbol))
-    {
-        return blockNameSymbol;
-    }
-    return nullptr;
+    return insert(currentLevel(), interfaceBlock);
 }
 
 TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type)
@@ -379,11 +372,13 @@
 bool TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
 {
     ASSERT(str);
-    if (insert(level, str))
-    {
-        return true;
-    }
-    return false;
+    return insert(level, str);
+}
+
+bool TSymbolTable::insertInterfaceBlock(ESymbolLevel level, TInterfaceBlock *interfaceBlock)
+{
+    ASSERT(interfaceBlock);
+    return insert(level, interfaceBlock);
 }
 
 void TSymbolTable::insertBuiltIn(ESymbolLevel level,
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 2b749d3..f7486a2 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -122,6 +122,26 @@
     bool mAtGlobalScope;
 };
 
+// Interface block. Note that this contains the block name, not the instance name. Interface block
+// instances are stored as TVariable.
+class TInterfaceBlock : public TSymbol, public TFieldListCollection
+{
+  public:
+    TInterfaceBlock(TSymbolTable *symbolTable,
+                    const TString *name,
+                    const TFieldList *fields,
+                    const TLayoutQualifier &layoutQualifier);
+
+    TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
+    int blockBinding() const { return mBinding; }
+
+  private:
+    TLayoutBlockStorage mBlockStorage;
+    int mBinding;
+
+    // Note that we only record matrix packing on a per-field granularity.
+};
+
 // Immutable version of TParameter.
 struct TConstParameter
 {
@@ -226,20 +246,6 @@
     bool mHasPrototypeDeclaration;
 };
 
-// Reserved interface block name. Note that this simply reserves the block name, not the instance
-// name. Interface block instances are stored as TVariable.
-class TInterfaceBlockName : public TSymbol
-{
-  public:
-    virtual ~TInterfaceBlockName() {}
-
-  private:
-    friend class TSymbolTable;
-    TInterfaceBlockName(TSymbolTable *symbolTable, const TString *name) : TSymbol(symbolTable, name)
-    {
-    }
-};
-
 class TSymbolTableLevel
 {
   public:
@@ -338,7 +344,7 @@
     // false if the declaration failed due to redefinition.
     TVariable *declareVariable(const TString *name, const TType &type);
     bool declareStructType(TStructure *str);
-    TInterfaceBlockName *declareInterfaceBlockName(const TString *name);
+    bool declareInterfaceBlock(TInterfaceBlock *interfaceBlock);
 
     // The insert* entry points are used when initializing the symbol table with built-ins.
     // They return the created symbol / true in case the declaration was successful, and nullptr /
@@ -349,9 +355,7 @@
                                  const char *name,
                                  const TType &type);
     bool insertStructType(ESymbolLevel level, TStructure *str);
-    TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level,
-                                                     TExtension ext,
-                                                     const TString *name);
+    bool insertInterfaceBlock(ESymbolLevel level, TInterfaceBlock *interfaceBlock);
 
     bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
     {
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index 5118f68..94694fa 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -932,16 +932,6 @@
     return 1 + maxNesting;
 }
 
-TInterfaceBlock::TInterfaceBlock(const TString *name,
-                                 const TFieldList *fields,
-                                 const TLayoutQualifier &layoutQualifier)
-    : TFieldListCollection(fields),
-      mName(name),
-      mBlockStorage(layoutQualifier.blockStorage),
-      mBinding(layoutQualifier.binding)
-{
-}
-
 // TPublicType implementation.
 void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
 {
diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h
index 02b5c53..04f46f1 100644
--- a/src/compiler/translator/Types.h
+++ b/src/compiler/translator/Types.h
@@ -19,6 +19,7 @@
 
 struct TPublicType;
 class TType;
+class TInterfaceBlock;
 class TStructure;
 class TSymbol;
 class TIntermSymbol;
@@ -80,27 +81,6 @@
     mutable TString mMangledFieldList;
 };
 
-class TInterfaceBlock : public TFieldListCollection
-{
-  public:
-    POOL_ALLOCATOR_NEW_DELETE();
-    TInterfaceBlock(const TString *name,
-                    const TFieldList *fields,
-                    const TLayoutQualifier &layoutQualifier);
-
-    const TString &name() const { return *mName; }
-    TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
-    int blockBinding() const { return mBinding; }
-
-  private:
-    const TString *mName;  // Name of the block, not the instance name. Instance name is only stored
-                           // in the interface block symbols.
-    TLayoutBlockStorage mBlockStorage;
-    int mBinding;
-
-    // Note that we only record matrix packing on a per-field granularity.
-};
-
 //
 // Base class for things that have a type.
 //