Identify functions by unique id in BuiltInFunctionEmulator

Now that unique ids of all builtins are compile-time constants, we can
use them to look up functions in BuiltInFunctionEmulator. This is
simpler than using a custom struct with the name and parameters for
identifying functions.

This requires that we store a reference to a TFunction in those
TIntermUnary nodes that were created based on a function.

This decreases shader_translator binary size by about 6 KB on Windows.

BUG=angleproject:2267
BUG=chromium:823856
TEST=angle_unittests

Change-Id: Idd5a00c772c6f26dd36fdbbfbe161d22ab27c2fe
Reviewed-on: https://chromium-review.googlesource.com/995372
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index a4d28f0..6cf0eb9 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -4859,7 +4859,8 @@
 
 TIntermTyped *TParseContext::createUnaryMath(TOperator op,
                                              TIntermTyped *child,
-                                             const TSourceLoc &loc)
+                                             const TSourceLoc &loc,
+                                             const TFunction *func)
 {
     ASSERT(child != nullptr);
 
@@ -4907,7 +4908,7 @@
     }
 
     markStaticReadIfSymbol(child);
-    TIntermUnary *node = new TIntermUnary(op, child);
+    TIntermUnary *node = new TIntermUnary(op, child, func);
     node->setLine(loc);
 
     return node->fold(mDiagnostics);
@@ -4916,7 +4917,7 @@
 TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
 {
     ASSERT(op != EOpNull);
-    TIntermTyped *node = createUnaryMath(op, child, loc);
+    TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
     if (node == nullptr)
     {
         return child;
@@ -5779,7 +5780,7 @@
     }
     else
     {
-        TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode);
+        TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
         node->setLine(loc);
         return node->fold(mDiagnostics);
     }
@@ -5837,7 +5838,8 @@
                 {
                     // Treat it like a built-in unary operator.
                     TIntermNode *unaryParamNode = fnCall->arguments().front();
-                    TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
+                    TIntermTyped *callNode =
+                        createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
                     ASSERT(callNode != nullptr);
                     return callNode;
                 }