Fold user-definedness of function nodes into TOperator

Whether a function call is user-defined is not orthogonal to TOperator
associated with the call node - other ops than function calls can't be
user-defined. Because of this it makes sense to store the user-
definedness by having different TOperator enums for different types of
calls.

This patch also tags internal helper functions that have a raw
definition outside the AST with a separate TOperator enum. This way
they can be handled with logic that is easy to understand. Before this,
function calls like this left the user-defined bit unset, despite not
really being built-ins either. The EmulatePrecision traverser uses
this. This is also something that could be used to clean up built-in
emulation in the future.

BUG=angleproject:1490
TEST=angle_unittests

Change-Id: I597fcd9789d0cc22b689ef3ce5a0cc3f621d4859
Reviewed-on: https://chromium-review.googlesource.com/433443
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/compiler/translator/RemoveDynamicIndexing.cpp
index 41aaced..fbe0264 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -55,6 +55,8 @@
     }
     TString nameString = TFunction::mangleName(nameSink.c_str());
     TName name(nameString);
+    // TODO(oetuaho@nvidia.com): would be better to have the parameter types in the mangled name as
+    // well.
     name.setInternal(true);
     return name;
 }
@@ -349,9 +351,8 @@
                                           TIntermTyped *index)
 {
     ASSERT(node->getOp() == EOpIndexIndirect);
-    TIntermAggregate *indexingCall = new TIntermAggregate(EOpFunctionCall);
+    TIntermAggregate *indexingCall = new TIntermAggregate(EOpCallFunctionInAST);
     indexingCall->setLine(node->getLine());
-    indexingCall->setUserDefined();
     indexingCall->getFunctionSymbolInfo()->setNameObj(
         GetIndexFunctionName(indexedNode->getType(), false));
     indexingCall->getSequence()->push_back(indexedNode);
@@ -520,6 +521,11 @@
         root->traverse(&traverser);
         traverser.updateTree();
     } while (traverser.usedTreeInsertion());
+    // TOOD(oetuaho@nvidia.com): It might be nicer to add the helper definitions also in the middle
+    // of traversal. Now the tree ends up in an inconsistent state in the middle, since there are
+    // function call nodes with no corresponding definition nodes. This needs special handling in
+    // TIntermLValueTrackingTraverser, and creates intricacies that are not easily apparent from a
+    // superficial reading of the code.
     traverser.insertHelperDefinitions(root);
     traverser.updateTree();
 }