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/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index b58b27c..8980e69 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -235,7 +235,7 @@
bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
{
- ASSERT(callNode->getOp() == EOpFunctionCall);
+ ASSERT(callNode->getOp() == EOpCallFunctionInAST);
return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) !=
mFunctionMap.end());
}
@@ -641,36 +641,43 @@
if (visit)
{
- bool inFunctionMap = false;
- if (node->getOp() == EOpFunctionCall)
+ if (node->getOp() == EOpCallFunctionInAST)
{
- inFunctionMap = isInFunctionMap(node);
- if (!inFunctionMap)
+ if (isInFunctionMap(node))
{
- // The function is not user-defined - it is likely built-in texture function.
- // Assume that those do not have out parameters.
- setInFunctionCallOutParameter(false);
- }
- }
-
- if (inFunctionMap)
- {
- TIntermSequence *params = getFunctionParameters(node);
- TIntermSequence::iterator paramIter = params->begin();
- for (auto *child : *sequence)
- {
- ASSERT(paramIter != params->end());
- TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
- setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
-
- child->traverse(this);
- if (visit && inVisit)
+ TIntermSequence *params = getFunctionParameters(node);
+ TIntermSequence::iterator paramIter = params->begin();
+ for (auto *child : *sequence)
{
- if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
- }
+ ASSERT(paramIter != params->end());
+ TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
+ setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
- ++paramIter;
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
+ }
+
+ ++paramIter;
+ }
+ }
+ else
+ {
+ // The node might not be in the function map in case we're in the middle of
+ // transforming the AST, and have inserted function call nodes without inserting the
+ // function definitions yet.
+ setInFunctionCallOutParameter(false);
+ for (auto *child : *sequence)
+ {
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
+ }
+ }
}
setInFunctionCallOutParameter(false);
@@ -680,7 +687,7 @@
// Find the built-in function corresponding to this op so that we can determine the
// in/out qualifiers of its parameters.
TFunction *builtInFunc = nullptr;
- if (!node->isConstructor() && node->getOp() != EOpFunctionCall)
+ if (!node->isFunctionCall() && !node->isConstructor())
{
builtInFunc = mSymbolTable.findBuiltInOp(node, mShaderVersion);
}
@@ -689,6 +696,8 @@
for (auto *child : *sequence)
{
+ // This assumes that raw functions called with
+ // EOpCallInternalRawFunction don't have out parameters.
TQualifier qualifier = EvqIn;
if (builtInFunc != nullptr)
qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();