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/RemoveDynamicIndexing.cpp b/src/compiler/translator/RemoveDynamicIndexing.cpp
index 093f5e5..97fa96f 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -101,17 +101,17 @@
     return TIntermAggregate::CreateConstructor(TType(EbtInt), arguments);
 }
 
-TType GetFieldType(const TType &indexedType)
+TType *GetFieldType(const TType &indexedType)
 {
     if (indexedType.isMatrix())
     {
-        TType fieldType = TType(indexedType.getBasicType(), indexedType.getPrecision());
-        fieldType.setPrimarySize(static_cast<unsigned char>(indexedType.getRows()));
+        TType *fieldType = new TType(indexedType.getBasicType(), indexedType.getPrecision());
+        fieldType->setPrimarySize(static_cast<unsigned char>(indexedType.getRows()));
         return fieldType;
     }
     else
     {
-        return TType(indexedType.getBasicType(), indexedType.getPrecision());
+        return new TType(indexedType.getBasicType(), indexedType.getPrecision());
     }
 }
 
@@ -160,12 +160,12 @@
 // Note that else is not used in above functions to avoid the RewriteElseBlocks transformation.
 TIntermFunctionDefinition *GetIndexFunctionDefinition(const TType &type,
                                                       bool write,
-                                                      const TSymbolUniqueId &functionId,
+                                                      const TFunction &func,
                                                       TSymbolTable *symbolTable)
 {
     ASSERT(!type.isArray());
 
-    TType fieldType = GetFieldType(type);
+    const TType *fieldType = GetFieldType(type);
     int numCases    = 0;
     if (type.isMatrix())
     {
@@ -176,15 +176,8 @@
         numCases = type.getNominalSize();
     }
 
-    TType returnType(EbtVoid);
-    if (!write)
-    {
-        returnType = fieldType;
-    }
-
     std::string functionName                = GetIndexFunctionName(type, write);
-    TIntermFunctionPrototype *prototypeNode =
-        CreateInternalFunctionPrototypeNode(returnType, functionName.c_str(), functionId);
+    TIntermFunctionPrototype *prototypeNode = CreateInternalFunctionPrototypeNode(func);
 
     TType baseType(type);
     // Conservatively use highp here, even if the indexed type is not highp. That way the code can't
@@ -203,7 +196,7 @@
     TIntermSymbol *valueParam = nullptr;
     if (write)
     {
-        valueParam = CreateValueSymbol(fieldType, symbolTable);
+        valueParam = CreateValueSymbol(*fieldType, symbolTable);
         prototypeNode->getSequence()->push_back(valueParam);
     }
 
@@ -301,8 +294,8 @@
     // Maps of types that are indexed to the indexing function ids used for them. Note that these
     // can not store multiple variants of the same type with different precisions - only one
     // precision gets stored.
-    std::map<TType, TSymbolUniqueId *> mIndexedVecAndMatrixTypes;
-    std::map<TType, TSymbolUniqueId *> mWrittenVecAndMatrixTypes;
+    std::map<TType, TFunction *> mIndexedVecAndMatrixTypes;
+    std::map<TType, TFunction *> mWrittenVecAndMatrixTypes;
 
     bool mUsedTreeInsertion;
 
@@ -347,26 +340,23 @@
 // Create a call to dyn_index_*() based on an indirect indexing op node
 TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node,
                                           TIntermTyped *index,
-                                          const TSymbolUniqueId &functionId)
+                                          TFunction *indexingFunction)
 {
     ASSERT(node->getOp() == EOpIndexIndirect);
     TIntermSequence *arguments = new TIntermSequence();
     arguments->push_back(node->getLeft());
     arguments->push_back(index);
 
-    TType fieldType                = GetFieldType(node->getLeft()->getType());
-    std::string functionName       = GetIndexFunctionName(node->getLeft()->getType(), false);
     TIntermAggregate *indexingCall =
-        CreateInternalFunctionCallNode(fieldType, functionName.c_str(), functionId, arguments);
+        TIntermAggregate::CreateFunctionCall(*indexingFunction, arguments);
     indexingCall->setLine(node->getLine());
-    indexingCall->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true);
     return indexingCall;
 }
 
 TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node,
                                                  TVariable *index,
                                                  TVariable *writtenValue,
-                                                 const TSymbolUniqueId &functionId)
+                                                 TFunction *indexedWriteFunction)
 {
     ASSERT(node->getOp() == EOpIndexIndirect);
     TIntermSequence *arguments = new TIntermSequence();
@@ -375,9 +365,8 @@
     arguments->push_back(CreateTempSymbolNode(index));
     arguments->push_back(CreateTempSymbolNode(writtenValue));
 
-    std::string functionName           = GetIndexFunctionName(node->getLeft()->getType(), true);
     TIntermAggregate *indexedWriteCall =
-        CreateInternalFunctionCallNode(TType(EbtVoid), functionName.c_str(), functionId, arguments);
+        TIntermAggregate::CreateFunctionCall(*indexedWriteFunction, arguments);
     indexedWriteCall->setLine(node->getLine());
     return indexedWriteCall;
 }
@@ -424,14 +413,19 @@
 #endif
 
             const TType &type = node->getLeft()->getType();
-            TSymbolUniqueId *indexingFunctionId = new TSymbolUniqueId(mSymbolTable);
+            TString *indexingFunctionName =
+                NewPoolTString(GetIndexFunctionName(type, false).c_str());
+            TFunction *indexingFunction = nullptr;
             if (mIndexedVecAndMatrixTypes.find(type) == mIndexedVecAndMatrixTypes.end())
             {
-                mIndexedVecAndMatrixTypes[type] = indexingFunctionId;
+                indexingFunction =
+                    new TFunction(mSymbolTable, indexingFunctionName, GetFieldType(type),
+                                  SymbolType::AngleInternal, true);
+                mIndexedVecAndMatrixTypes[type] = indexingFunction;
             }
             else
             {
-                indexingFunctionId = mIndexedVecAndMatrixTypes[type];
+                indexingFunction = mIndexedVecAndMatrixTypes[type];
             }
 
             if (write)
@@ -466,14 +460,19 @@
                 // TODO(oetuaho@nvidia.com): This is not optimal if the expression using the value
                 // only writes it and doesn't need the previous value. http://anglebug.com/1116
 
-                TSymbolUniqueId *indexedWriteFunctionId = new TSymbolUniqueId(mSymbolTable);
+                TFunction *indexedWriteFunction = nullptr;
                 if (mWrittenVecAndMatrixTypes.find(type) == mWrittenVecAndMatrixTypes.end())
                 {
-                    mWrittenVecAndMatrixTypes[type] = indexedWriteFunctionId;
+                    TString *functionName = NewPoolTString(
+                        GetIndexFunctionName(node->getLeft()->getType(), true).c_str());
+                    indexedWriteFunction =
+                        new TFunction(mSymbolTable, functionName, new TType(EbtVoid),
+                                      SymbolType::AngleInternal, false);
+                    mWrittenVecAndMatrixTypes[type] = indexedWriteFunction;
                 }
                 else
                 {
-                    indexedWriteFunctionId = mWrittenVecAndMatrixTypes[type];
+                    indexedWriteFunction = mWrittenVecAndMatrixTypes[type];
                 }
 
                 TIntermSequence insertionsBefore;
@@ -489,7 +488,7 @@
 
                 // s1 = dyn_index(v_expr, s0);
                 TIntermAggregate *indexingCall = CreateIndexFunctionCall(
-                    node, CreateTempSymbolNode(indexVariable), *indexingFunctionId);
+                    node, CreateTempSymbolNode(indexVariable), indexingFunction);
                 TIntermDeclaration *fieldVariableDeclaration = nullptr;
                 TVariable *fieldVariable                     = DeclareTempVariable(
                     mSymbolTable, indexingCall, EvqTemporary, &fieldVariableDeclaration);
@@ -497,7 +496,7 @@
 
                 // dyn_index_write(v_expr, s0, s1);
                 TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall(
-                    node, indexVariable, fieldVariable, *indexedWriteFunctionId);
+                    node, indexVariable, fieldVariable, indexedWriteFunction);
                 insertionsAfter.push_back(indexedWriteCall);
                 insertStatementsInParentBlock(insertionsBefore, insertionsAfter);
 
@@ -514,7 +513,7 @@
                 // If the index_expr is unsigned, we'll convert it to signed.
                 ASSERT(!mRemoveIndexSideEffectsInSubtree);
                 TIntermAggregate *indexingCall = CreateIndexFunctionCall(
-                    node, EnsureSignedInt(node->getRight()), *indexingFunctionId);
+                    node, EnsureSignedInt(node->getRight()), indexingFunction);
                 queueReplacement(indexingCall, OriginalNode::IS_DROPPED);
             }
         }