Refactor GLSL scoped structure handling.

With a unique ID, similar to how we handle scoped structures
in the HLSL translator, we can simplify the declared structure
check.

BUG=angle:618

Change-Id: I5fe61c8d353650ac67a7c7ecdf53a70b91a9b717
Reviewed-on: https://chromium-review.googlesource.com/202500
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 6995594..6eaadd2 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -55,8 +55,6 @@
       mSymbolTable(symbolTable),
       mShaderVersion(shaderVersion)
 {
-    // Set up global scope.
-    mDeclaredStructs.push_back(ScopedDeclaredStructs());
 }
 
 void TOutputGLSLBase::writeTriplet(
@@ -89,8 +87,14 @@
     // Declare the struct if we have not done so already.
     if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
     {
-        declareStruct(type.getStruct());
-        mDeclaredStructs[mDeclaredStructs.size() - 1].push_back(type.getStruct());
+        TStructure *structure = type.getStruct();
+
+        declareStruct(structure);
+
+        if (!structure->name().empty())
+        {
+            mDeclaredStructs.insert(structure->uniqueId());
+        }
     }
     else
     {
@@ -604,7 +608,6 @@
         if (depth > 0)
         {
             out << "{\n";
-            pushDeclaredStructsScope();
         }
 
         incrementDepth(node);
@@ -623,7 +626,6 @@
         // Scope the sequences except when at the global scope.
         if (depth > 0)
         {
-            popDeclaredStructsScope();
             out << "}\n";
         }
         visitChildren = false;
@@ -1035,17 +1037,12 @@
 bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
 {
     ASSERT(structure);
-    ASSERT(mDeclaredStructs.size() > 0);
-    for (size_t ii = mDeclaredStructs.size(); ii > 0; --ii)
+    if (structure->name().empty())
     {
-        const ScopedDeclaredStructs &scope = mDeclaredStructs[ii - 1];
-        for (size_t jj = 0; jj < scope.size(); ++jj)
-        {
-            if (scope[jj]->equals(*structure))
-                return true;
-        }
+        return false;
     }
-    return false;
+
+    return (mDeclaredStructs.count(structure->uniqueId()) > 0);
 }
 
 void TOutputGLSLBase::declareStruct(const TStructure *structure)
@@ -1067,14 +1064,3 @@
     out << "}";
 }
 
-void TOutputGLSLBase::pushDeclaredStructsScope()
-{
-    mDeclaredStructs.push_back(ScopedDeclaredStructs());
-}
-
-void TOutputGLSLBase::popDeclaredStructsScope()
-{
-    // We should never pop the global scope.
-    ASSERT(mDeclaredStructs.size() >= 2);
-    mDeclaredStructs.pop_back();
-}
diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h
index ae40f85..42364de 100644
--- a/src/compiler/translator/OutputGLSLBase.h
+++ b/src/compiler/translator/OutputGLSLBase.h
@@ -7,7 +7,7 @@
 #ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
 #define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
 
-#include <vector>
+#include <set>
 
 #include "compiler/translator/intermediate.h"
 #include "compiler/translator/LoopInfo.h"
@@ -56,22 +56,14 @@
   private:
     bool structDeclared(const TStructure *structure) const;
     void declareStruct(const TStructure *structure);
-    void pushDeclaredStructsScope();
-    void popDeclaredStructsScope();
 
     void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction);
 
     TInfoSinkBase &mObjSink;
     bool mDeclaringVariables;
 
-    // Structs are declared as the tree is traversed. This list contains all
-    // the structs already declared within a scope. It is maintained so that
-    // a struct is declared only once within a scope.
-    typedef std::vector<TStructure *> ScopedDeclaredStructs;
-    // This vector contains all the structs from the global scope to the
-    // current scope.  When the traverser exits a scope, the scope is discarded. 
-    typedef std::vector<ScopedDeclaredStructs> DeclaredStructs;
-    DeclaredStructs mDeclaredStructs;
+    // This set contains all the ids of the structs from every scope.
+    std::set<int> mDeclaredStructs;
 
     // Stack of loops that need to be unrolled.
     TLoopStack mLoopUnrollStack;
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 3f932a4..078e0be 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -298,7 +298,6 @@
 
   protected:
     tLevel level;
-    static int uniqueId; // for unique identification in code generation
 };
 
 enum ESymbolLevel
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index 4763920..bafad0d 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -22,57 +22,9 @@
         structure = p.userDef->getStruct();
 }
 
-bool TType::equals(const TType &other) const
-{
-    if (type != other.type || precision != other.precision ||
-        primarySize != other.primarySize || secondarySize != other.secondarySize ||
-        array != other.array || (array && arraySize != other.arraySize) ||
-        interfaceBlock != other.interfaceBlock || structure != other.structure)
-    {
-        return false;
-    }
-    if (interfaceBlock && !interfaceBlock->equals(*(other.interfaceBlock)))
-        return false;
-    if (structure && !structure->equals(*(other.structure)))
-        return false;
-    return true;
-}
-
-bool TField::equals(const TField &other) const
-{
-    ASSERT(mType && mName);
-    ASSERT(other.mType && other.mName);
-    return mType->equals(*(other.mType)) && *mName == *(other.mName);
-}
-
-bool TFieldListCollection::equals(const TFieldListCollection &other) const
-{
-    ASSERT(mName && mFields);
-    ASSERT(other.mName && other.mFields);
-    if (*mName != *(other.mName))
-         return false;
-    if (mFields->size() != other.mFields->size())
-        return false;
-    for (size_t ii = 0; ii < mFields->size(); ++ii)
-    {
-        ASSERT((*mFields)[ii] && (*(other.mFields))[ii]);
-        if (!(*mFields)[ii]->equals(*((*(other.mFields))[ii])))
-            return false;
-    }
-    return true;
-}
-
 bool TStructure::equals(const TStructure &other) const
 {
-    return TFieldListCollection::equals(other);
-}
-
-bool TInterfaceBlock::equals(const TInterfaceBlock &other) const
-{
-    if (!TFieldListCollection::equals(other))
-        return false;
-    // TODO(zmo): do we need to consider mBlockStorage and mMatrixPacking?
-    return mArraySize == other.mArraySize;
+    return (uniqueId() == other.uniqueId());
 }
 
 //
diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h
index 7629720..bc50a4d 100644
--- a/src/compiler/translator/Types.h
+++ b/src/compiler/translator/Types.h
@@ -48,8 +48,6 @@
         return mLine;
     }
 
-    bool equals(const TField &other) const;
-
   private:
     DISALLOW_COPY_AND_ASSIGN(TField);
     TType *mType;
@@ -100,8 +98,6 @@
     size_t calculateObjectSize() const;
     virtual TString mangledNamePrefix() const = 0;
 
-    bool equals(const TFieldListCollection &other) const;
-
     const TString *mName;
     TFieldList *mFields;
 
@@ -193,8 +189,6 @@
         return mMatrixPacking;
     }
 
-    bool equals(const TInterfaceBlock &other) const;
-
   private:
     DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
     virtual TString mangledNamePrefix() const
@@ -385,10 +379,6 @@
         return mangled;
     }
 
-    // This is different from operator== as we also compare
-    // precision here.
-    bool equals(const TType &other) const;
-
     bool sameElementType(const TType &right) const
     {
         return type == right.type &&