Implement user-defined name hashing.

ANGLEBUG=315
Review URL: https://codereview.appspot.com/6818109

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1469 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputGLSLBase.cpp b/src/compiler/OutputGLSLBase.cpp
index 552fa50..ed86c68 100644
--- a/src/compiler/OutputGLSLBase.cpp
+++ b/src/compiler/OutputGLSLBase.cpp
@@ -9,35 +9,6 @@
 
 namespace
 {
-TString getTypeName(const TType& type)
-{
-    TInfoSinkBase out;
-    if (type.isMatrix())
-    {
-        out << "mat";
-        out << type.getNominalSize();
-    }
-    else if (type.isVector())
-    {
-        switch (type.getBasicType())
-        {
-            case EbtFloat: out << "vec"; break;
-            case EbtInt: out << "ivec"; break;
-            case EbtBool: out << "bvec"; break;
-            default: UNREACHABLE(); break;
-        }
-        out << type.getNominalSize();
-    }
-    else
-    {
-        if (type.getBasicType() == EbtStruct)
-            out << type.getTypeName();
-        else
-            out << type.getBasicString();
-    }
-    return TString(out.c_str());
-}
-
 TString arrayBrackets(const TType& type)
 {
     ASSERT(type.isArray());
@@ -66,10 +37,16 @@
 }
 }  // namespace
 
-TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink)
+TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
+                                 ShHashFunction64 hashFunction,
+                                 NameMap& nameMap,
+                                 TSymbolTable& symbolTable)
     : TIntermTraverser(true, true, true),
       mObjSink(objSink),
-      mDeclaringVariables(false)
+      mDeclaringVariables(false),
+      mHashFunction(hashFunction),
+      mNameMap(nameMap),
+      mSymbolTable(symbolTable)
 {
 }
 
@@ -101,7 +78,7 @@
     if ((type.getBasicType() == EbtStruct) &&
         (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
     {
-        out << "struct " << type.getTypeName() << "{\n";
+        out << "struct " << hashName(type.getTypeName()) << "{\n";
         const TTypeList* structure = type.getStruct();
         ASSERT(structure != NULL);
         for (size_t i = 0; i < structure->size(); ++i)
@@ -110,7 +87,7 @@
             ASSERT(fieldType != NULL);
             if (writeVariablePrecision(fieldType->getPrecision()))
                 out << " ";
-            out << getTypeName(*fieldType) << " " << fieldType->getFieldName();
+            out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName());
             if (fieldType->isArray())
                 out << arrayBrackets(*fieldType);
             out << ";\n";
@@ -140,7 +117,7 @@
 
         const TString& name = arg->getSymbol();
         if (!name.empty())
-            out << " " << name;
+            out << " " << hashName(name);
         if (type.isArray())
             out << arrayBrackets(type);
 
@@ -157,7 +134,7 @@
 
     if (type.getBasicType() == EbtStruct)
     {
-        out << type.getTypeName() << "(";
+        out << hashName(type.getTypeName()) << "(";
         const TTypeList* structure = type.getStruct();
         ASSERT(structure != NULL);
         for (size_t i = 0; i < structure->size(); ++i)
@@ -196,7 +173,7 @@
     if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
         out << mLoopUnroll.GetLoopIndexValue(node);
     else
-        out << node->getSymbol();
+        out << hashVariableName(node->getSymbol());
 
     if (mDeclaringVariables && node->getType().isArray())
         out << arrayBrackets(node->getType());
@@ -243,7 +220,7 @@
             {
                 out << ".";
                 // TODO(alokp): ASSERT
-                out << node->getType().getFieldName();
+                out << hashName(node->getType().getFieldName());
                 visitChildren = false;
             }
             break;
@@ -467,7 +444,7 @@
             // Function declaration.
             ASSERT(visit == PreVisit);
             writeVariableType(node->getType());
-            out << " " << node->getName();
+            out << " " << hashName(node->getName());
 
             out << "(";
             writeFunctionParameters(node->getSequence());
@@ -480,7 +457,7 @@
             // Function definition.
             ASSERT(visit == PreVisit);
             writeVariableType(node->getType());
-            out << " " << TFunction::unmangleName(node->getName());
+            out << " " << hashFunctionName(node->getName());
 
             incrementDepth();
             // Function definition node contains one or two children nodes
@@ -510,8 +487,7 @@
             // Function call.
             if (visit == PreVisit)
             {
-                TString functionName = TFunction::unmangleName(node->getName());
-                out << functionName << "(";
+                out << hashFunctionName(node->getName()) << "(";
             }
             else if (visit == InVisit)
             {
@@ -572,7 +548,7 @@
             {
                 const TType& type = node->getType();
                 ASSERT(type.getBasicType() == EbtStruct);
-                out << type.getTypeName() << "(";
+                out << hashName(type.getTypeName()) << "(";
             }
             else if (visit == InVisit)
             {
@@ -718,3 +694,59 @@
         out << "{\n}\n";  // Empty code block.
     }
 }
+
+TString TOutputGLSLBase::getTypeName(const TType& type)
+{
+    TInfoSinkBase out;
+    if (type.isMatrix())
+    {
+        out << "mat";
+        out << type.getNominalSize();
+    }
+    else if (type.isVector())
+    {
+        switch (type.getBasicType())
+        {
+            case EbtFloat: out << "vec"; break;
+            case EbtInt: out << "ivec"; break;
+            case EbtBool: out << "bvec"; break;
+            default: UNREACHABLE(); break;
+        }
+        out << type.getNominalSize();
+    }
+    else
+    {
+        if (type.getBasicType() == EbtStruct)
+            out << hashName(type.getTypeName());
+        else
+            out << type.getBasicString();
+    }
+    return TString(out.c_str());
+}
+
+TString TOutputGLSLBase::hashName(const TString& name)
+{
+    if (mHashFunction == NULL || name.empty())
+        return name;
+    NameMap::const_iterator it = mNameMap.find(name.c_str());
+    if (it != mNameMap.end())
+        return it->second.c_str();
+    TString hashedName = TIntermTraverser::hash(name, mHashFunction);
+    mNameMap[name.c_str()] = hashedName.c_str();
+    return hashedName;
+}
+
+TString TOutputGLSLBase::hashVariableName(const TString& name)
+{
+    if (mSymbolTable.findBuiltIn(name) != NULL)
+        return name;
+    return hashName(name);
+}
+
+TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
+{
+    TString name = TFunction::unmangleName(mangled_name);
+    if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main")
+        return name;
+    return hashName(name);
+}