Prefer identifying functions by using symbol ids
The shader translator code is now structured in a way that ensures
that all function definition, function prototype and function call
nodes store the integer symbol id for the function. This is guaranteed
regardless of whether the function node is added while parsing or as a
result of an AST transformation. TIntermAggregate nodes, which include
function calls and constructors can now only be created by calling one
of the TIntermAggregate::Create*() functions to ensure they have all
the necessary properties.
This makes it possible to keep track of functions using integer ids
instead of their mangled name strings when generating the call graph
and when using TLValueTrackingTraverser.
This commit includes a few other small cleanups to the CallDAG class
as well.
BUG=angleproject:1490
TEST=angle_unittests, angle_end2end_tests
Change-Id: Idd1013506cbe4c3380e20d90524a9cd09b890259
Reviewed-on: https://chromium-review.googlesource.com/459603
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/CallDAG.cpp b/src/compiler/translator/CallDAG.cpp
index 6daa778..8557fdf 100644
--- a/src/compiler/translator/CallDAG.cpp
+++ b/src/compiler/translator/CallDAG.cpp
@@ -9,7 +9,9 @@
// order.
#include "compiler/translator/CallDAG.h"
+
#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/SymbolTable.h"
namespace sh
{
@@ -78,7 +80,7 @@
record.callees.push_back(static_cast<int>(callee->index));
}
- (*idToIndex)[data.node->getFunctionSymbolInfo()->getId()] =
+ (*idToIndex)[data.node->getFunctionSymbolInfo()->getId().get()] =
static_cast<int>(data.index);
}
}
@@ -101,19 +103,20 @@
// Create the record if need be and remember the node.
if (visit == PreVisit)
{
- auto it = mFunctions.find(node->getFunctionSymbolInfo()->getName());
+ auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
if (it == mFunctions.end())
{
- mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getName()];
+ mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getId().get()];
+ mCurrentFunction->name = node->getFunctionSymbolInfo()->getName();
}
else
{
mCurrentFunction = &it->second;
+ ASSERT(mCurrentFunction->name == node->getFunctionSymbolInfo()->getName());
}
mCurrentFunction->node = node;
- mCurrentFunction->name = node->getFunctionSymbolInfo()->getName();
}
else if (visit == PostVisit)
{
@@ -125,8 +128,13 @@
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
{
ASSERT(visit == PreVisit);
+ if (mCurrentFunction != nullptr)
+ {
+ return false;
+ }
+
// Function declaration, create an empty record.
- auto &record = mFunctions[node->getFunctionSymbolInfo()->getName()];
+ auto &record = mFunctions[node->getFunctionSymbolInfo()->getId().get()];
record.name = node->getFunctionSymbolInfo()->getName();
// No need to traverse the parameters.
@@ -139,10 +147,12 @@
if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
{
// Function call, add the callees
- auto it = mFunctions.find(node->getFunctionSymbolInfo()->getName());
+ auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
ASSERT(it != mFunctions.end());
- // We might be in a top-level function call to set a global variable
+ // We might be traversing the initializer of a global variable. Even though function
+ // calls in global scope are forbidden by the parser, some subsequent AST
+ // transformations can add them to emulate particular features.
if (mCurrentFunction)
{
mCurrentFunction->callees.insert(&it->second);
@@ -259,7 +269,7 @@
TDiagnostics *mDiagnostics;
- std::map<TString, CreatorFunctionData> mFunctions;
+ std::map<int, CreatorFunctionData> mFunctions;
CreatorFunctionData *mCurrentFunction;
size_t mCurrentIndex;
};
@@ -278,7 +288,7 @@
size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const
{
- auto it = mFunctionIdToIndex.find(functionInfo->getId());
+ auto it = mFunctionIdToIndex.find(functionInfo->getId().get());
if (it == mFunctionIdToIndex.end())
{