Always create TFunctions for function call nodes

This simplifies code and ensures that nodes get consistent data.

In the future function call nodes could have a pointer to the
TFunction instead of converting the same information into a different
data structure.

BUG=angleproject:2267
TEST=angle_unittests, angle_end2end_tests

Change-Id: Ic0c24bb86b44b9bcc4a5da7f6b03701081a3af5c
Reviewed-on: https://chromium-review.googlesource.com/824606
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index b68724c..335da38 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -287,29 +287,20 @@
 TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func,
                                                        TIntermSequence *arguments)
 {
-    TIntermAggregate *callNode =
-        new TIntermAggregate(func.getReturnType(), EOpCallFunctionInAST, arguments);
-    callNode->getFunctionSymbolInfo()->setFromFunction(func);
-    return callNode;
+    return new TIntermAggregate(&func, func.getReturnType(), EOpCallFunctionInAST, arguments);
 }
 
-TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TType &type,
-                                                       const TSymbolUniqueId &id,
-                                                       const TName &name,
-                                                       TIntermSequence *arguments)
+TIntermAggregate *TIntermAggregate::CreateRawFunctionCall(const TFunction &func,
+                                                          TIntermSequence *arguments)
 {
-    TIntermAggregate *callNode = new TIntermAggregate(type, EOpCallFunctionInAST, arguments);
-    callNode->getFunctionSymbolInfo()->setId(id);
-    callNode->getFunctionSymbolInfo()->setNameObj(name);
-    return callNode;
+    return new TIntermAggregate(&func, func.getReturnType(), EOpCallInternalRawFunction, arguments);
 }
 
 TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func,
                                                               TIntermSequence *arguments)
 {
     TIntermAggregate *callNode =
-        new TIntermAggregate(func.getReturnType(), EOpCallBuiltInFunction, arguments);
-    callNode->getFunctionSymbolInfo()->setFromFunction(func);
+        new TIntermAggregate(&func, func.getReturnType(), EOpCallBuiltInFunction, arguments);
     // Note that name needs to be set before texture function type is determined.
     callNode->setBuiltInFunctionPrecision();
     return callNode;
@@ -318,27 +309,37 @@
 TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type,
                                                       TIntermSequence *arguments)
 {
-    return new TIntermAggregate(type, EOpConstruct, arguments);
+    return new TIntermAggregate(nullptr, type, EOpConstruct, arguments);
 }
 
 TIntermAggregate *TIntermAggregate::Create(const TType &type,
                                            TOperator op,
                                            TIntermSequence *arguments)
 {
-    TIntermAggregate *node = new TIntermAggregate(type, op, arguments);
     ASSERT(op != EOpCallFunctionInAST);    // Should use CreateFunctionCall
+    ASSERT(op != EOpCallInternalRawFunction);  // Should use CreateRawFunctionCall
     ASSERT(op != EOpCallBuiltInFunction);  // Should use CreateBuiltInFunctionCall
-    ASSERT(!node->isConstructor());        // Should use CreateConstructor
-    return node;
+    ASSERT(op != EOpConstruct);            // Should use CreateConstructor
+    return new TIntermAggregate(nullptr, type, op, arguments);
 }
 
-TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments)
-    : TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false)
+TIntermAggregate::TIntermAggregate(const TFunction *func,
+                                   const TType &type,
+                                   TOperator op,
+                                   TIntermSequence *arguments)
+    : TIntermOperator(op),
+      mUseEmulatedFunction(false),
+      mGotPrecisionFromChildren(false),
+      mFunction(func)
 {
     if (arguments != nullptr)
     {
         mArguments.swap(*arguments);
     }
+    if (mFunction)
+    {
+        mFunctionInfo.setFromFunction(*mFunction);
+    }
     setTypePrecisionAndQualifier(type);
 }
 
@@ -474,9 +475,23 @@
     }
 }
 
+const char *TIntermAggregate::functionName() const
+{
+    ASSERT(!isConstructor());
+    switch (mOp)
+    {
+        case EOpCallInternalRawFunction:
+        case EOpCallBuiltInFunction:
+        case EOpCallFunctionInAST:
+            return mFunction->name()->c_str();
+        default:
+            return GetOperatorString(mOp);
+    }
+}
+
 bool TIntermAggregate::hasSideEffects() const
 {
-    if (isFunctionCall() && mFunctionInfo.isKnownToNotHaveSideEffects())
+    if (isFunctionCall() && mFunction != nullptr && mFunction->isKnownToNotHaveSideEffects())
     {
         for (TIntermNode *arg : mArguments)
         {
@@ -580,17 +595,17 @@
 
 void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
 {
-    setName(*function.name());
+    mName.setString(*function.name());
+    mName.setInternal(function.symbolType() == SymbolType::AngleInternal);
     setId(TSymbolUniqueId(function));
 }
 
-TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id)
-    : mId(new TSymbolUniqueId(id)), mKnownToNotHaveSideEffects(false)
+TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id) : mId(new TSymbolUniqueId(id))
 {
 }
 
 TFunctionSymbolInfo::TFunctionSymbolInfo(const TFunctionSymbolInfo &info)
-    : mName(info.mName), mId(nullptr), mKnownToNotHaveSideEffects(info.mKnownToNotHaveSideEffects)
+    : mName(info.mName), mId(nullptr)
 {
     if (info.mId)
     {
@@ -627,7 +642,8 @@
     : TIntermOperator(node),
       mUseEmulatedFunction(node.mUseEmulatedFunction),
       mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
-      mFunctionInfo(node.mFunctionInfo)
+      mFunctionInfo(node.mFunctionInfo),
+      mFunction(node.mFunction)
 {
     for (TIntermNode *arg : node.mArguments)
     {
@@ -642,8 +658,8 @@
 {
     TIntermSequence *copySeq = new TIntermSequence();
     copySeq->insert(copySeq->begin(), getSequence()->begin(), getSequence()->end());
-    TIntermAggregate *copyNode         = new TIntermAggregate(mType, mOp, copySeq);
-    *copyNode->getFunctionSymbolInfo() = mFunctionInfo;
+    TIntermAggregate *copyNode = new TIntermAggregate(mFunction, mType, mOp, copySeq);
+    copyNode->mFunctionInfo    = mFunctionInfo;
     copyNode->setLine(mLine);
     return copyNode;
 }