Remove TFunctionSymbolInfo from TIntermAggregate

All the information stored in TFunctionSymbolInfo was duplicated from
the TFunction that the aggregate node pointed to.

BUG=angleproject:2267
TEST=angle_unittests

Change-Id: I1f5574ab0416e5cae00c3dae6fc11d2fe1fa128c
Reviewed-on: https://chromium-review.googlesource.com/827065
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ASTMetadataHLSL.cpp b/src/compiler/translator/ASTMetadataHLSL.cpp
index b04fc28..d1ae057 100644
--- a/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -119,7 +119,7 @@
         {
             if (node->getOp() == EOpCallFunctionInAST)
             {
-                size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+                size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId());
                 ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
 
                 if ((*mMetadataList)[calleeIndex].mUsesGradient)
@@ -129,7 +129,7 @@
             }
             else if (node->getOp() == EOpCallBuiltInFunction)
             {
-                if (mGradientBuiltinFunctions.find(node->getFunctionSymbolInfo()->getName()) !=
+                if (mGradientBuiltinFunctions.find(*node->getFunction()->name()) !=
                     mGradientBuiltinFunctions.end())
                 {
                     onGradient();
@@ -288,7 +288,7 @@
     {
         if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
         {
-            size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+            size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId());
             ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
 
             if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph)
@@ -367,7 +367,7 @@
             case EOpCallFunctionInAST:
                 if (visit == PreVisit && mNestedDiscont > 0)
                 {
-                    size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+                    size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId());
                     ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
 
                     (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
diff --git a/src/compiler/translator/CallDAG.cpp b/src/compiler/translator/CallDAG.cpp
index 5d4e561..5403a7f 100644
--- a/src/compiler/translator/CallDAG.cpp
+++ b/src/compiler/translator/CallDAG.cpp
@@ -287,9 +287,9 @@
 
 const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max();
 
-size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const
+size_t CallDAG::findIndex(const TSymbolUniqueId &id) const
 {
-    auto it = mFunctionIdToIndex.find(functionInfo->getId().get());
+    auto it = mFunctionIdToIndex.find(id.get());
 
     if (it == mFunctionIdToIndex.end())
     {
@@ -307,13 +307,6 @@
     return mRecords[index];
 }
 
-const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const
-{
-    size_t index = findIndex(function->getFunctionSymbolInfo());
-    ASSERT(index != InvalidIndex && index < mRecords.size());
-    return mRecords[index];
-}
-
 size_t CallDAG::size() const
 {
     return mRecords.size();
diff --git a/src/compiler/translator/CallDAG.h b/src/compiler/translator/CallDAG.h
index 155081c..9bd22e4 100644
--- a/src/compiler/translator/CallDAG.h
+++ b/src/compiler/translator/CallDAG.h
@@ -58,10 +58,9 @@
     InitResult init(TIntermNode *root, TDiagnostics *diagnostics);
 
     // Returns InvalidIndex if the function wasn't found
-    size_t findIndex(const TFunctionSymbolInfo *functionInfo) const;
+    size_t findIndex(const TSymbolUniqueId &id) const;
 
     const Record &getRecordFromIndex(size_t index) const;
-    const Record &getRecord(const TIntermAggregate *function) const;
     size_t size() const;
     void clear();
 
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 77b06f8..4ae8d7e 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -1008,7 +1008,7 @@
             return false;
         }
 
-        size_t callDagIndex = mCallDag->findIndex(functionInfo);
+        size_t callDagIndex = mCallDag->findIndex(functionInfo->getId());
         if (callDagIndex == CallDAG::InvalidIndex)
         {
             // This happens only for unimplemented prototypes which are thus unused
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 335da38..a2fdf4d 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -148,6 +148,11 @@
 {
 }
 
+TName::TName(const TSymbol *symbol)
+    : mName(*symbol->name()), mIsInternal(symbol->symbolType() == SymbolType::AngleInternal)
+{
+}
+
 ////////////////////////////////////////////////////////////////
 //
 // Member functions of the nodes used for building the tree.
@@ -336,10 +341,7 @@
     {
         mArguments.swap(*arguments);
     }
-    if (mFunction)
-    {
-        mFunctionInfo.setFromFunction(*mFunction);
-    }
+    ASSERT(mFunction == nullptr || mFunction->symbolType() != SymbolType::Empty);
     setTypePrecisionAndQualifier(type);
 }
 
@@ -454,7 +456,7 @@
     }
     // ESSL 3.0 spec section 8: textureSize always gets highp precision.
     // All other functions that take a sampler are assumed to be texture functions.
-    if (mFunctionInfo.getName().find("textureSize") == 0)
+    if (mFunction->name()->find("textureSize") == 0)
         mType.setPrecision(EbpHigh);
     else
         mType.setPrecision(precision);
@@ -468,7 +470,7 @@
         case EOpCallInternalRawFunction:
         case EOpCallBuiltInFunction:
         case EOpCallFunctionInAST:
-            return TFunction::GetMangledNameFromCall(mFunctionInfo.getName(), mArguments);
+            return TFunction::GetMangledNameFromCall(*mFunction->name(), mArguments);
         default:
             TString opString = GetOperatorString(mOp);
             return TFunction::GetMangledNameFromCall(opString, mArguments);
@@ -642,7 +644,6 @@
     : TIntermOperator(node),
       mUseEmulatedFunction(node.mUseEmulatedFunction),
       mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
-      mFunctionInfo(node.mFunctionInfo),
       mFunction(node.mFunction)
 {
     for (TIntermNode *arg : node.mArguments)
@@ -659,7 +660,6 @@
     TIntermSequence *copySeq = new TIntermSequence();
     copySeq->insert(copySeq->begin(), getSequence()->begin(), getSequence()->end());
     TIntermAggregate *copyNode = new TIntermAggregate(mFunction, mType, mOp, copySeq);
-    copyNode->mFunctionInfo    = mFunctionInfo;
     copyNode->setLine(mLine);
     return copyNode;
 }
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 0da7e67..e4de2f3 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -67,6 +67,7 @@
   public:
     POOL_ALLOCATOR_NEW_DELETE();
     explicit TName(const TString *name);
+    explicit TName(const TSymbol *symbol);
     TName() : mName(), mIsInternal(false) {}
     TName(const TName &) = default;
     TName &operator=(const TName &) = default;
@@ -542,11 +543,6 @@
     void setId(const TSymbolUniqueId &functionId);
     const TSymbolUniqueId &getId() const;
 
-    bool isImageFunction() const
-    {
-        return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore";
-    }
-
   private:
     TName mName;
     TSymbolUniqueId *mId;
@@ -625,8 +621,6 @@
     // Returns true if changing parameter precision may affect the return value.
     bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
 
-    const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
-
     const TFunction *getFunction() const { return mFunction; }
 
     // Get the function name to display to the user in an error message.
@@ -641,9 +635,6 @@
 
     bool mGotPrecisionFromChildren;
 
-    // TODO(oetuaho): Get rid of mFunctionInfo and just keep mFunction.
-    TFunctionSymbolInfo mFunctionInfo;
-
     const TFunction *const mFunction;
 
   private:
diff --git a/src/compiler/translator/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index 65fe819..5c23e6d 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -185,14 +185,13 @@
 bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
 {
     ASSERT(callNode->getOp() == EOpCallFunctionInAST);
-    return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) !=
-            mFunctionMap.end());
+    return (mFunctionMap.find(callNode->getFunction()->uniqueId().get()) != mFunctionMap.end());
 }
 
 TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
 {
     ASSERT(isInFunctionMap(callNode));
-    return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()];
+    return mFunctionMap[callNode->getFunction()->uniqueId().get()];
 }
 
 void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 9d02919..4ffa5b2 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -938,11 +938,11 @@
             {
                 if (node->getOp() == EOpCallBuiltInFunction)
                 {
-                    out << translateTextureFunction(node->getFunctionSymbolInfo()->getName());
+                    out << translateTextureFunction(*node->getFunction()->name());
                 }
                 else
                 {
-                    out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
+                    out << hashFunctionNameIfNeeded(node->getFunction());
                 }
                 out << "(";
             }
@@ -1143,6 +1143,18 @@
     return hashName(name);
 }
 
+TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunction *func)
+{
+    if (func->isMain())
+    {
+        return *func->name();
+    }
+    else
+    {
+        return hashName(TName(func));
+    }
+}
+
 TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
 {
     if (info.isMain())
diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h
index 592a310..51f7242 100644
--- a/src/compiler/translator/OutputGLSLBase.h
+++ b/src/compiler/translator/OutputGLSLBase.h
@@ -72,6 +72,7 @@
     // Same as hashName(), but without hashing built-in variables.
     TString hashVariableName(const TName &name);
     // Same as hashName(), but without hashing internal functions or "main".
+    TString hashFunctionNameIfNeeded(const TFunction *func);
     TString hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info);
     // Used to translate function names for differences between ESSL and GLSL
     virtual TString translateTextureFunction(const TString &name) { return name; }
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index ef727c8..40372c6 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1723,7 +1723,7 @@
 
     ASSERT(mCurrentFunctionMetadata == nullptr);
 
-    size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+    size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()->getId());
     ASSERT(index != CallDAG::InvalidIndex);
     mCurrentFunctionMetadata = &mASTMetadataList[index];
 
@@ -1851,7 +1851,7 @@
     TInfoSinkBase &out = getInfoSink();
 
     ASSERT(visit == PreVisit);
-    size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+    size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()->getId());
     // Skip the prototype if it is not implemented (and thus not used)
     if (index == CallDAG::InvalidIndex)
     {
@@ -1910,11 +1910,11 @@
                 {
                     UNIMPLEMENTED();
                 }
-                size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+                size_t index = mCallDag.findIndex(node->getFunction()->uniqueId());
                 ASSERT(index != CallDAG::InvalidIndex);
                 lod0 &= mASTMetadataList[index].mNeedsLod0;
 
-                out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+                out << DecorateFunctionIfNeeded(TName(node->getFunction()));
                 out << DisambiguateFunctionName(node->getSequence());
                 out << (lod0 ? "Lod0(" : "(");
             }
@@ -1922,20 +1922,20 @@
             {
                 // This path is used for internal functions that don't have their definitions in the
                 // AST, such as precision emulation functions.
-                out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
+                out << DecorateFunctionIfNeeded(TName(node->getFunction())) << "(";
             }
-            else if (node->getFunctionSymbolInfo()->isImageFunction())
+            else if (node->getFunction()->isImageFunction())
             {
-                TString name              = node->getFunctionSymbolInfo()->getName();
+                const TString *name       = node->getFunction()->name();
                 TType type                = (*arguments)[0]->getAsTyped()->getType();
                 TString imageFunctionName = mImageFunctionHLSL->useImageFunction(
-                    name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat,
+                    *name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat,
                     type.getMemoryQualifier().readonly);
                 out << imageFunctionName << "(";
             }
             else
             {
-                const TString &name    = node->getFunctionSymbolInfo()->getName();
+                const TString *name    = node->getFunction()->name();
                 TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType();
                 int coords = 0;  // textureSize(gsampler2DMS) doesn't have a second argument.
                 if (arguments->size() > 1)
@@ -1943,7 +1943,7 @@
                     coords = (*arguments)[1]->getAsTyped()->getNominalSize();
                 }
                 TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction(
-                    name, samplerType, coords, arguments->size(), lod0, mShaderType);
+                    *name, samplerType, coords, arguments->size(), lod0, mShaderType);
                 out << textureFunctionName << "(";
             }
 
diff --git a/src/compiler/translator/OutputTree.cpp b/src/compiler/translator/OutputTree.cpp
index 6798b35..8bacce9 100644
--- a/src/compiler/translator/OutputTree.cpp
+++ b/src/compiler/translator/OutputTree.cpp
@@ -20,6 +20,14 @@
         << info->getId().get() << ")";
 }
 
+void OutputFunction(TInfoSinkBase &out, const char *str, const TFunction *func)
+{
+    const char *internal =
+        (func->symbolType() == SymbolType::AngleInternal) ? " (internal function)" : "";
+    out << str << internal << ": " << *func->name() << " (symbol id " << func->uniqueId().get()
+        << ")";
+}
+
 // Two purposes:
 // 1.  Show an example of how to iterate tree.  Functions can also directly call traverse() on
 //     children themselves to have finer grained control over the process than shown here, though
@@ -379,14 +387,14 @@
     switch (node->getOp())
     {
         case EOpCallFunctionInAST:
-            OutputFunction(mOut, "Call an user-defined function", node->getFunctionSymbolInfo());
+            OutputFunction(mOut, "Call an user-defined function", node->getFunction());
             break;
         case EOpCallInternalRawFunction:
             OutputFunction(mOut, "Call an internal function with raw implementation",
-                           node->getFunctionSymbolInfo());
+                           node->getFunction());
             break;
         case EOpCallBuiltInFunction:
-            OutputFunction(mOut, "Call a built-in function", node->getFunctionSymbolInfo());
+            OutputFunction(mOut, "Call a built-in function", node->getFunction());
             break;
 
         case EOpConstruct:
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 1ead5a5..8ed358d 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -5483,7 +5483,7 @@
 void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
 {
     ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
-    const TString &name        = functionCall->getFunctionSymbolInfo()->getName();
+    const TString &name        = *functionCall->getFunction()->name();
     bool isTextureGather       = (name == "textureGather");
     bool isTextureGatherOffset = (name == "textureGatherOffset");
     if (isTextureGather || isTextureGatherOffset)
@@ -5549,7 +5549,7 @@
 void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
 {
     ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
-    const TString &name        = functionCall->getFunctionSymbolInfo()->getName();
+    const TString &name                    = *functionCall->getFunction()->name();
     TIntermNode *offset        = nullptr;
     TIntermSequence *arguments = functionCall->getSequence();
     bool useTextureGatherOffsetConstraints = false;
@@ -5625,7 +5625,8 @@
 
 void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
 {
-    const TString &name = functionCall->getFunctionSymbolInfo()->getName();
+    ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
+    const TString &name = *functionCall->getFunction()->name();
     if (IsAtomicBuiltin(name))
     {
         TIntermSequence *arguments = functionCall->getSequence();
@@ -5648,7 +5649,7 @@
         error(memNode->getLine(),
               "The value passed to the mem argument of an atomic memory function does not "
               "correspond to a buffer or shared variable.",
-              functionCall->getFunctionSymbolInfo()->getName().c_str());
+              functionCall->getFunction()->name()->c_str());
     }
 }
 
@@ -5656,7 +5657,7 @@
 void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
 {
     ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
-    const TString &name = functionCall->getFunctionSymbolInfo()->getName();
+    const TString &name = *functionCall->getFunction()->name();
 
     if (name.compare(0, 5, "image") == 0)
     {
diff --git a/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/compiler/translator/RewriteTexelFetchOffset.cpp
index b602e0c..ceb903c 100644
--- a/src/compiler/translator/RewriteTexelFetchOffset.cpp
+++ b/src/compiler/translator/RewriteTexelFetchOffset.cpp
@@ -72,7 +72,7 @@
         return true;
     }
 
-    if (node->getFunctionSymbolInfo()->getName() != "texelFetchOffset")
+    if (*node->getFunction()->name() != "texelFetchOffset")
     {
         return true;
     }
diff --git a/src/compiler/translator/Symbol.cpp b/src/compiler/translator/Symbol.cpp
index f6a782b..fe5914c 100644
--- a/src/compiler/translator/Symbol.cpp
+++ b/src/compiler/translator/Symbol.cpp
@@ -183,4 +183,15 @@
     return *NewPoolTString(newName.c_str());
 }
 
+bool TFunction::isMain() const
+{
+    return symbolType() == SymbolType::UserDefined && *name() == "main";
+}
+
+bool TFunction::isImageFunction() const
+{
+    return symbolType() == SymbolType::BuiltIn &&
+           (*name() == "imageSize" || *name() == "imageLoad" || *name() == "imageStore");
+}
+
 }  // namespace sh
diff --git a/src/compiler/translator/Symbol.h b/src/compiler/translator/Symbol.h
index 2073740..eba4d38 100644
--- a/src/compiler/translator/Symbol.h
+++ b/src/compiler/translator/Symbol.h
@@ -225,6 +225,9 @@
 
     bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
 
+    bool isMain() const;
+    bool isImageFunction() const;
+
   private:
     void clearParameters();