Always use TFunction instead of TFunctionSymbolInfo

This reduces unnecessary memory allocations and conversions between
different objects containing the same data.

BUG=angleproject:2267
TEST=angle_unittests

Change-Id: I87316509ab1cd6d36756ff6af7fa2b5c5a76a8ea
Reviewed-on: https://chromium-review.googlesource.com/827134
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
index c1a0ab7..9299019 100644
--- a/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -12,6 +12,7 @@
 
 #include "compiler/translator/IntermNode_util.h"
 #include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/StaticType.h"
 #include "compiler/translator/SymbolTable.h"
 
 namespace sh
@@ -29,24 +30,6 @@
     }
 }
 
-TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall,
-                                        TIntermTyped *returnValueTarget)
-{
-    TIntermSequence *replacementArguments = new TIntermSequence();
-    TIntermSequence *originalArguments    = originalCall->getSequence();
-    for (auto &arg : *originalArguments)
-    {
-        replacementArguments->push_back(arg);
-    }
-    replacementArguments->push_back(returnValueTarget);
-    ASSERT(originalCall->getFunction());
-    TIntermAggregate *replacementCall =
-        TIntermAggregate::CreateFunctionCall(*originalCall->getFunction(), replacementArguments);
-    replacementCall->setType(TType(EbtVoid));
-    replacementCall->setLine(originalCall->getLine());
-    return replacementCall;
-}
-
 class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
 {
   public:
@@ -61,15 +44,43 @@
     bool visitBranch(Visit visit, TIntermBranch *node) override;
     bool visitBinary(Visit visit, TIntermBinary *node) override;
 
+    TIntermAggregate *createReplacementCall(TIntermAggregate *originalCall,
+                                            TIntermTyped *returnValueTarget);
+
     // Set when traversal is inside a function with array return value.
     TIntermFunctionDefinition *mFunctionWithArrayReturnValue;
 
-    // Map from function symbol ids to array return value variables.
-    std::map<int, TVariable *> mReturnValueVariables;
+    struct ChangedFunction
+    {
+        const TVariable *returnValueVariable;
+        const TFunction *func;
+    };
+
+    // Map from function symbol ids to the changed function.
+    std::map<int, ChangedFunction> mChangedFunctions;
 
     const TString *const mReturnValueVariableName;
 };
 
+TIntermAggregate *ArrayReturnValueToOutParameterTraverser::createReplacementCall(
+    TIntermAggregate *originalCall,
+    TIntermTyped *returnValueTarget)
+{
+    TIntermSequence *replacementArguments = new TIntermSequence();
+    TIntermSequence *originalArguments    = originalCall->getSequence();
+    for (auto &arg : *originalArguments)
+    {
+        replacementArguments->push_back(arg);
+    }
+    replacementArguments->push_back(returnValueTarget);
+    ASSERT(originalCall->getFunction());
+    const TSymbolUniqueId &originalId = originalCall->getFunction()->uniqueId();
+    TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall(
+        *mChangedFunctions[originalId.get()].func, replacementArguments);
+    replacementCall->setLine(originalCall->getLine());
+    return replacementCall;
+}
+
 void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable)
 {
     ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable);
@@ -108,21 +119,25 @@
     {
         // Replace the whole prototype node with another node that has the out parameter
         // added. Also set the function to return void.
-        TIntermFunctionPrototype *replacement =
-            new TIntermFunctionPrototype(TType(EbtVoid), node->getFunctionSymbolInfo()->getId());
-        CopyAggregateChildren(node, replacement);
-        const TSymbolUniqueId &functionId = node->getFunctionSymbolInfo()->getId();
-        if (mReturnValueVariables.find(functionId.get()) == mReturnValueVariables.end())
+        const TSymbolUniqueId &functionId = node->getFunction()->uniqueId();
+        if (mChangedFunctions.find(functionId.get()) == mChangedFunctions.end())
         {
             TType returnValueVariableType(node->getType());
             returnValueVariableType.setQualifier(EvqOut);
-            mReturnValueVariables[functionId.get()] =
+            ChangedFunction changedFunction;
+            changedFunction.returnValueVariable =
                 new TVariable(mSymbolTable, mReturnValueVariableName, returnValueVariableType,
                               SymbolType::AngleInternal);
+            changedFunction.func = new TFunction(mSymbolTable, node->getFunction()->name(),
+                                                 StaticType::GetBasic<EbtVoid>(),
+                                                 node->getFunction()->symbolType(), false);
+            mChangedFunctions[functionId.get()] = changedFunction;
         }
+        TIntermFunctionPrototype *replacement =
+            new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func);
+        CopyAggregateChildren(node, replacement);
         replacement->getSequence()->push_back(
-            new TIntermSymbol(mReturnValueVariables[functionId.get()]));
-        *replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo();
+            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable));
         replacement->setLine(node->getLine());
 
         queueReplacement(replacement, OriginalNode::IS_DROPPED);
@@ -161,7 +176,7 @@
 
             // f(s0);
             TIntermSymbol *returnValueSymbol = CreateTempSymbolNode(returnValue);
-            replacements.push_back(CreateReplacementCall(node, returnValueSymbol));
+            replacements.push_back(createReplacementCall(node, returnValueSymbol));
             mMultiReplacements.push_back(
                 NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
         }
@@ -180,10 +195,10 @@
         TIntermTyped *expression = node->getExpression();
         ASSERT(expression != nullptr);
         const TSymbolUniqueId &functionId =
-            mFunctionWithArrayReturnValue->getFunctionSymbolInfo()->getId();
-        ASSERT(mReturnValueVariables.find(functionId.get()) != mReturnValueVariables.end());
+            mFunctionWithArrayReturnValue->getFunction()->uniqueId();
+        ASSERT(mChangedFunctions.find(functionId.get()) != mChangedFunctions.end());
         TIntermSymbol *returnValueSymbol =
-            new TIntermSymbol(mReturnValueVariables[functionId.get()]);
+            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable);
         TIntermBinary *replacementAssignment =
             new TIntermBinary(EOpAssign, returnValueSymbol, expression);
         replacementAssignment->setLine(expression->getLine());
@@ -207,7 +222,7 @@
         ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction);
         if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST)
         {
-            TIntermAggregate *replacementCall = CreateReplacementCall(rightAgg, node->getLeft());
+            TIntermAggregate *replacementCall = createReplacementCall(rightAgg, node->getLeft());
             queueReplacement(replacementCall, OriginalNode::IS_DROPPED);
         }
     }
diff --git a/src/compiler/translator/CallDAG.cpp b/src/compiler/translator/CallDAG.cpp
index 5403a7f..c4c8e83 100644
--- a/src/compiler/translator/CallDAG.cpp
+++ b/src/compiler/translator/CallDAG.cpp
@@ -81,8 +81,7 @@
                 record.callees.push_back(static_cast<int>(callee->index));
             }
 
-            (*idToIndex)[data.node->getFunctionSymbolInfo()->getId().get()] =
-                static_cast<int>(data.index);
+            (*idToIndex)[data.node->getFunction()->uniqueId().get()] = static_cast<int>(data.index);
         }
     }
 
@@ -104,17 +103,17 @@
         // Create the record if need be and remember the node.
         if (visit == PreVisit)
         {
-            auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
+            auto it = mFunctions.find(node->getFunction()->uniqueId().get());
 
             if (it == mFunctions.end())
             {
-                mCurrentFunction       = &mFunctions[node->getFunctionSymbolInfo()->getId().get()];
-                mCurrentFunction->name = node->getFunctionSymbolInfo()->getName();
+                mCurrentFunction       = &mFunctions[node->getFunction()->uniqueId().get()];
+                mCurrentFunction->name = *node->getFunction()->name();
             }
             else
             {
                 mCurrentFunction = &it->second;
-                ASSERT(mCurrentFunction->name == node->getFunctionSymbolInfo()->getName());
+                ASSERT(mCurrentFunction->name == *node->getFunction()->name());
             }
 
             mCurrentFunction->node = node;
@@ -135,8 +134,8 @@
         }
 
         // Function declaration, create an empty record.
-        auto &record = mFunctions[node->getFunctionSymbolInfo()->getId().get()];
-        record.name  = node->getFunctionSymbolInfo()->getName();
+        auto &record = mFunctions[node->getFunction()->uniqueId().get()];
+        record.name  = *node->getFunction()->name();
 
         // No need to traverse the parameters.
         return false;
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 4ae8d7e..730f0c5 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -993,22 +993,22 @@
         const TIntermFunctionPrototype *asFunctionPrototype   = node->getAsFunctionPrototypeNode();
         const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
 
-        const TFunctionSymbolInfo *functionInfo = nullptr;
+        const TFunction *func = nullptr;
 
         if (asFunctionDefinition)
         {
-            functionInfo = asFunctionDefinition->getFunctionSymbolInfo();
+            func = asFunctionDefinition->getFunction();
         }
         else if (asFunctionPrototype)
         {
-            functionInfo = asFunctionPrototype->getFunctionSymbolInfo();
+            func = asFunctionPrototype->getFunction();
         }
-        if (functionInfo == nullptr)
+        if (func == nullptr)
         {
             return false;
         }
 
-        size_t callDagIndex = mCallDag->findIndex(functionInfo->getId());
+        size_t callDagIndex = mCallDag->findIndex(func->uniqueId());
         if (callDagIndex == CallDAG::InvalidIndex)
         {
             // This happens only for unimplemented prototypes which are thus unused
diff --git a/src/compiler/translator/FindMain.cpp b/src/compiler/translator/FindMain.cpp
index 7417fba..091e21a 100644
--- a/src/compiler/translator/FindMain.cpp
+++ b/src/compiler/translator/FindMain.cpp
@@ -9,6 +9,7 @@
 #include "compiler/translator/FindMain.h"
 
 #include "compiler/translator/IntermNode.h"
+#include "compiler/translator/Symbol.h"
 
 namespace sh
 {
@@ -18,7 +19,7 @@
     for (TIntermNode *node : *root->getSequence())
     {
         TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition();
-        if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->isMain())
+        if (nodeFunction != nullptr && nodeFunction->getFunction()->isMain())
         {
             return nodeFunction;
         }
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index a2fdf4d..6f63f0e 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -595,49 +595,10 @@
     mUnionArrayPointer = node.mUnionArrayPointer;
 }
 
-void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
+TIntermFunctionPrototype::TIntermFunctionPrototype(const TFunction *function)
+    : TIntermTyped(function->getReturnType()), mFunction(function)
 {
-    mName.setString(*function.name());
-    mName.setInternal(function.symbolType() == SymbolType::AngleInternal);
-    setId(TSymbolUniqueId(function));
-}
-
-TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id) : mId(new TSymbolUniqueId(id))
-{
-}
-
-TFunctionSymbolInfo::TFunctionSymbolInfo(const TFunctionSymbolInfo &info)
-    : mName(info.mName), mId(nullptr)
-{
-    if (info.mId)
-    {
-        mId = new TSymbolUniqueId(*info.mId);
-    }
-}
-
-TFunctionSymbolInfo &TFunctionSymbolInfo::operator=(const TFunctionSymbolInfo &info)
-{
-    mName = info.mName;
-    if (info.mId)
-    {
-        mId = new TSymbolUniqueId(*info.mId);
-    }
-    else
-    {
-        mId = nullptr;
-    }
-    return *this;
-}
-
-void TFunctionSymbolInfo::setId(const TSymbolUniqueId &id)
-{
-    mId = new TSymbolUniqueId(id);
-}
-
-const TSymbolUniqueId &TFunctionSymbolInfo::getId() const
-{
-    ASSERT(mId);
-    return *mId;
+    ASSERT(mFunction->symbolType() != SymbolType::Empty);
 }
 
 TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index e4de2f3..ab3df07 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -522,32 +522,6 @@
     TIntermUnary(const TIntermUnary &node);  // note: not deleted, just private!
 };
 
-class TFunctionSymbolInfo
-{
-  public:
-    POOL_ALLOCATOR_NEW_DELETE();
-    TFunctionSymbolInfo(const TSymbolUniqueId &id);
-    TFunctionSymbolInfo() : mId(nullptr) {}
-
-    TFunctionSymbolInfo(const TFunctionSymbolInfo &info);
-    TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info);
-
-    void setFromFunction(const TFunction &function);
-
-    void setNameObj(const TName &name) { mName = name; }
-    const TName &getNameObj() const { return mName; }
-
-    const TString &getName() const { return mName.getString(); }
-    bool isMain() const { return mName.getString() == "main"; }
-
-    void setId(const TSymbolUniqueId &functionId);
-    const TSymbolUniqueId &getId() const;
-
-  private:
-    TName mName;
-    TSymbolUniqueId *mId;
-};
-
 typedef TVector<TIntermNode *> TIntermSequence;
 typedef TVector<int> TQualifierList;
 
@@ -688,12 +662,7 @@
 class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
 {
   public:
-    // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
-    // parameters.
-    TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id)
-        : TIntermTyped(type), mFunctionInfo(id)
-    {
-    }
+    TIntermFunctionPrototype(const TFunction *function);
     ~TIntermFunctionPrototype() {}
 
     TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
@@ -717,13 +686,12 @@
     TIntermSequence *getSequence() override { return &mParameters; }
     const TIntermSequence *getSequence() const override { return &mParameters; }
 
-    TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
-    const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
+    const TFunction *getFunction() const { return mFunction; }
 
   protected:
     TIntermSequence mParameters;
 
-    TFunctionSymbolInfo mFunctionInfo;
+    const TFunction *const mFunction;
 };
 
 // Node for function definitions. The prototype child node stores the function header including
@@ -745,10 +713,7 @@
     TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
     TIntermBlock *getBody() const { return mBody; }
 
-    const TFunctionSymbolInfo *getFunctionSymbolInfo() const
-    {
-        return mPrototype->getFunctionSymbolInfo();
-    }
+    const TFunction *getFunction() const { return mPrototype->getFunction(); }
 
   private:
     TIntermFunctionPrototype *mPrototype;
diff --git a/src/compiler/translator/IntermNode_util.cpp b/src/compiler/translator/IntermNode_util.cpp
index a3291fc..7bbd578 100644
--- a/src/compiler/translator/IntermNode_util.cpp
+++ b/src/compiler/translator/IntermNode_util.cpp
@@ -35,16 +35,13 @@
 
 TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TFunction &func)
 {
-    TIntermFunctionPrototype *functionNode =
-        new TIntermFunctionPrototype(func.getReturnType(), func.uniqueId());
-    functionNode->getFunctionSymbolInfo()->setFromFunction(func);
-    return functionNode;
+    return new TIntermFunctionPrototype(&func);
 }
 
 TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TFunction &func,
                                                                 TIntermBlock *functionBody)
 {
-    return new TIntermFunctionDefinition(CreateInternalFunctionPrototypeNode(func), functionBody);
+    return new TIntermFunctionDefinition(new TIntermFunctionPrototype(&func), functionBody);
 }
 
 TIntermTyped *CreateZeroNode(const TType &type)
diff --git a/src/compiler/translator/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index 5c23e6d..8c45d75 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -675,7 +675,7 @@
 void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
 {
     TIntermSequence *sequence = node->getSequence();
-    addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence);
+    addToFunctionMap(node->getFunction()->uniqueId(), sequence);
 
     TIntermTraverser::traverseFunctionPrototype(node);
 }
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 4ffa5b2..db5519e 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -915,7 +915,7 @@
     if (type.isArray())
         out << ArrayString(type);
 
-    out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
+    out << " " << hashFunctionNameIfNeeded(node->getFunction());
 
     out << "(";
     writeFunctionParameters(*(node->getSequence()));
@@ -1155,18 +1155,6 @@
     }
 }
 
-TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
-{
-    if (info.isMain())
-    {
-        return info.getName();
-    }
-    else
-    {
-        return hashName(info.getNameObj());
-    }
-}
-
 bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
 {
     ASSERT(structure);
diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h
index 51f7242..1fff216 100644
--- a/src/compiler/translator/OutputGLSLBase.h
+++ b/src/compiler/translator/OutputGLSLBase.h
@@ -73,7 +73,6 @@
     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 40372c6..739f686 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()->getId());
+    size_t index = mCallDag.findIndex(node->getFunction()->uniqueId());
     ASSERT(index != CallDAG::InvalidIndex);
     mCurrentFunctionMetadata = &mASTMetadataList[index];
 
@@ -1731,14 +1731,14 @@
 
     TIntermSequence *parameters = node->getFunctionPrototype()->getSequence();
 
-    if (node->getFunctionSymbolInfo()->isMain())
+    if (node->getFunction()->isMain())
     {
         out << "gl_main(";
     }
     else
     {
-        out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj())
-            << DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "(");
+        out << DecorateFunctionIfNeeded(node->getFunction()) << DisambiguateFunctionName(parameters)
+            << (mOutputLod0Function ? "Lod0(" : "(");
     }
 
     for (unsigned int i = 0; i < parameters->size(); i++)
@@ -1772,7 +1772,7 @@
     bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
     if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
     {
-        ASSERT(!node->getFunctionSymbolInfo()->isMain());
+        ASSERT(!node->getFunction()->isMain());
         mOutputLod0Function = true;
         node->traverse(this);
         mOutputLod0Function = false;
@@ -1851,7 +1851,7 @@
     TInfoSinkBase &out = getInfoSink();
 
     ASSERT(visit == PreVisit);
-    size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()->getId());
+    size_t index = mCallDag.findIndex(node->getFunction()->uniqueId());
     // Skip the prototype if it is not implemented (and thus not used)
     if (index == CallDAG::InvalidIndex)
     {
@@ -1860,7 +1860,7 @@
 
     TIntermSequence *arguments = node->getSequence();
 
-    TString name = DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+    TString name = DecorateFunctionIfNeeded(node->getFunction());
     out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments)
         << (mOutputLod0Function ? "Lod0(" : "(");
 
@@ -1914,7 +1914,7 @@
                 ASSERT(index != CallDAG::InvalidIndex);
                 lod0 &= mASTMetadataList[index].mNeedsLod0;
 
-                out << DecorateFunctionIfNeeded(TName(node->getFunction()));
+                out << DecorateFunctionIfNeeded(node->getFunction());
                 out << DisambiguateFunctionName(node->getSequence());
                 out << (lod0 ? "Lod0(" : "(");
             }
@@ -1922,7 +1922,7 @@
             {
                 // This path is used for internal functions that don't have their definitions in the
                 // AST, such as precision emulation functions.
-                out << DecorateFunctionIfNeeded(TName(node->getFunction())) << "(";
+                out << DecorateFunctionIfNeeded(node->getFunction()) << "(";
             }
             else if (node->getFunction()->isImageFunction())
             {
diff --git a/src/compiler/translator/OutputTree.cpp b/src/compiler/translator/OutputTree.cpp
index 8bacce9..67efc0f 100644
--- a/src/compiler/translator/OutputTree.cpp
+++ b/src/compiler/translator/OutputTree.cpp
@@ -13,13 +13,6 @@
 namespace
 {
 
-void OutputFunction(TInfoSinkBase &out, const char *str, const TFunctionSymbolInfo *info)
-{
-    const char *internal = info->getNameObj().isInternal() ? " (internal function)" : "";
-    out << str << internal << ": " << info->getNameObj().getString() << " (symbol id "
-        << info->getId().get() << ")";
-}
-
 void OutputFunction(TInfoSinkBase &out, const char *str, const TFunction *func)
 {
     const char *internal =
@@ -364,7 +357,7 @@
 bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
 {
     OutputTreeText(mOut, node, mDepth);
-    OutputFunction(mOut, "Function Prototype", node->getFunctionSymbolInfo());
+    OutputFunction(mOut, "Function Prototype", node->getFunction());
     mOut << " (" << node->getCompleteString() << ")";
     mOut << "\n";
 
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 8ed358d..b502fe2 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -3156,11 +3156,7 @@
     ASSERT(function.name());
     checkIsNotReserved(location, *function.name());
 
-    TIntermFunctionPrototype *prototype =
-        new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
-    // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
-    // point to the data that already exists in the symbol table.
-    prototype->getFunctionSymbolInfo()->setFromFunction(function);
+    TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function);
     prototype->setLine(location);
 
     for (size_t i = 0; i < function.getParamCount(); i++)
@@ -3250,7 +3246,7 @@
     if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
     {
         error(location, "function does not return a value:",
-              functionPrototype->getFunctionSymbolInfo()->getName().c_str());
+              functionPrototype->getFunction()->name()->c_str());
     }
 
     if (functionBody == nullptr)
diff --git a/src/compiler/translator/RunAtTheEndOfShader.cpp b/src/compiler/translator/RunAtTheEndOfShader.cpp
index ab1bb3c..d0a2b82 100644
--- a/src/compiler/translator/RunAtTheEndOfShader.cpp
+++ b/src/compiler/translator/RunAtTheEndOfShader.cpp
@@ -77,9 +77,7 @@
     // void main()
     TFunction *newMain = new TFunction(symbolTable, NewPoolTString("main"), new TType(EbtVoid),
                                        SymbolType::UserDefined, false);
-    TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype(
-        TType(EbtVoid), main->getFunctionPrototype()->getFunctionSymbolInfo()->getId());
-    newMainProto->getFunctionSymbolInfo()->setFromFunction(*newMain);
+    TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype(newMain);
 
     // {
     //     main0();
diff --git a/src/compiler/translator/UtilsHLSL.cpp b/src/compiler/translator/UtilsHLSL.cpp
index 1569225..91934c7 100644
--- a/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/compiler/translator/UtilsHLSL.cpp
@@ -730,20 +730,20 @@
     }
 }
 
-TString DecorateFunctionIfNeeded(const TName &name)
+TString DecorateFunctionIfNeeded(const TFunction *func)
 {
-    if (name.isInternal())
+    if (func->symbolType() == SymbolType::AngleInternal)
     {
         // The name should not have a prefix reserved for user-defined variables or functions.
-        ASSERT(name.getString().compare(0, 2, "f_") != 0);
-        ASSERT(name.getString().compare(0, 1, "_") != 0);
-        return name.getString();
+        ASSERT(func->name()->compare(0, 2, "f_") != 0);
+        ASSERT(func->name()->compare(0, 1, "_") != 0);
+        return *func->name();
     }
-    ASSERT(name.getString().compare(0, 3, "gl_") != 0);
+    ASSERT(func->name()->compare(0, 3, "gl_") != 0);
     // Add an additional f prefix to functions so that they're always disambiguated from variables.
     // This is necessary in the corner case where a variable declaration hides a function that it
     // uses in its initializer.
-    return "f_" + name.getString();
+    return "f_" + (*func->name());
 }
 
 TString TypeString(const TType &type)
diff --git a/src/compiler/translator/UtilsHLSL.h b/src/compiler/translator/UtilsHLSL.h
index daeec8d..47ef78c 100644
--- a/src/compiler/translator/UtilsHLSL.h
+++ b/src/compiler/translator/UtilsHLSL.h
@@ -111,7 +111,7 @@
 // Adds a prefix to user-defined names to avoid naming clashes.
 TString Decorate(const TString &string);
 TString DecorateVariableIfNeeded(const TName &name);
-TString DecorateFunctionIfNeeded(const TName &name);
+TString DecorateFunctionIfNeeded(const TFunction *func);
 TString DecorateField(const TString &string, const TStructure &structure);
 TString DecoratePrivate(const TString &privateText);
 TString TypeString(const TType &type);