Store unmangled function names in the AST
This makes the code simpler across the board. There are a few cases
where mangled names still need to be generated in AST traversers, but
they are outweighed by much leaner output code for all function nodes.
BUG=angleproject:1490
TEST=angle_unittests, angle_end2end_tests
Change-Id: Id3638e0fca6019bbbe6fc5e1b7763870591da2d8
Reviewed-on: https://chromium-review.googlesource.com/461077
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/ASTMetadataHLSL.cpp b/src/compiler/translator/ASTMetadataHLSL.cpp
index e0de596..80a8ab6 100644
--- a/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -128,9 +128,8 @@
}
else if (node->getOp() == EOpCallBuiltInFunction)
{
- TString name = TFunction::unmangleName(node->getFunctionSymbolInfo()->getName());
-
- if (mGradientBuiltinFunctions.find(name) != mGradientBuiltinFunctions.end())
+ if (mGradientBuiltinFunctions.find(node->getFunctionSymbolInfo()->getName()) !=
+ mGradientBuiltinFunctions.end())
{
onGradient();
}
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 8ebd231..9cedfab 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -760,7 +760,7 @@
// Search from main, starting from the end of the DAG as it usually is the root.
for (size_t i = mCallDag.size(); i-- > 0;)
{
- if (mCallDag.getRecordFromIndex(i).name == "main(")
+ if (mCallDag.getRecordFromIndex(i).name == "main")
{
internalTagUsedFunction(i);
return true;
diff --git a/src/compiler/translator/EmulatePrecision.cpp b/src/compiler/translator/EmulatePrecision.cpp
index 888d336..80d5c1e 100644
--- a/src/compiler/translator/EmulatePrecision.cpp
+++ b/src/compiler/translator/EmulatePrecision.cpp
@@ -431,7 +431,7 @@
TString name,
TIntermSequence *arguments)
{
- TName nameObj(TFunction::GetMangledNameFromCall(name, *arguments));
+ TName nameObj(name);
nameObj.setInternal(true);
TIntermAggregate *callNode =
TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments);
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 3a8fdc0..dd80396 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -630,7 +630,7 @@
void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
{
- setName(function.getMangledName());
+ setName(function.getName());
setId(TSymbolUniqueId(function));
}
@@ -3379,7 +3379,6 @@
TName TIntermTraverser::GetInternalFunctionName(const char *name)
{
TString nameStr(name);
- nameStr = TFunction::mangleName(nameStr);
TName nameObj(nameStr);
nameObj.setInternal(true);
return nameObj;
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 513c111..93729d5 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -550,7 +550,7 @@
const TString &getName() const { return mName.getString(); }
void setName(const TString &name) { mName.setString(name); }
- bool isMain() const { return mName.getString() == "main("; }
+ bool isMain() const { return mName.getString() == "main"; }
void setId(const TSymbolUniqueId &functionId);
const TSymbolUniqueId &getId() const;
diff --git a/src/compiler/translator/OutputGLSL.cpp b/src/compiler/translator/OutputGLSL.cpp
index 7084872..af1b77c 100644
--- a/src/compiler/translator/OutputGLSL.cpp
+++ b/src/compiler/translator/OutputGLSL.cpp
@@ -66,7 +66,7 @@
}
}
-TString TOutputGLSL::translateTextureFunction(TString &name)
+TString TOutputGLSL::translateTextureFunction(const TString &name)
{
static const char *simpleRename[] = {"texture2DLodEXT",
"texture2DLod",
diff --git a/src/compiler/translator/OutputGLSL.h b/src/compiler/translator/OutputGLSL.h
index d910c00..17682ff 100644
--- a/src/compiler/translator/OutputGLSL.h
+++ b/src/compiler/translator/OutputGLSL.h
@@ -28,7 +28,7 @@
protected:
bool writeVariablePrecision(TPrecision) override;
void visitSymbol(TIntermSymbol *node) override;
- TString translateTextureFunction(TString &name) override;
+ TString translateTextureFunction(const TString &name) override;
};
} // namespace sh
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index b5a8b1e..fee3836 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -926,7 +926,7 @@
if (type.isArray())
out << arrayBrackets(type);
- out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+ out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
out << "(";
writeFunctionParameters(*(node->getSequence()));
@@ -946,7 +946,17 @@
case EOpCallBuiltInFunction:
// Function call.
if (visit == PreVisit)
- out << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
+ {
+ if (node->getOp() == EOpCallBuiltInFunction)
+ {
+ out << translateTextureFunction(node->getFunctionSymbolInfo()->getName());
+ }
+ else
+ {
+ out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
+ }
+ out << "(";
+ }
else if (visit == InVisit)
out << ", ";
else
@@ -1196,22 +1206,17 @@
return hashName(name);
}
-TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TName &mangledName)
+TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
{
- TString mangledStr = mangledName.getString();
- TString name = TFunction::unmangleName(mangledStr);
- if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main")
- return translateTextureFunction(name);
- if (mangledName.isInternal())
+ if (info.isMain() || info.getNameObj().isInternal())
{
// Internal function names are outputted as-is - they may refer to functions manually added
// to the output shader source that are not included in the AST at all.
- return name;
+ return info.getName();
}
else
{
- TName nameObj(name);
- return hashName(nameObj);
+ return hashName(info.getNameObj());
}
}
diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h
index 4c26c73..af3019c 100644
--- a/src/compiler/translator/OutputGLSLBase.h
+++ b/src/compiler/translator/OutputGLSLBase.h
@@ -70,10 +70,10 @@
// Same as hashName(), but without hashing built-in variables.
TString hashVariableName(const TName &name);
- // Same as hashName(), but without hashing built-in functions and with unmangling.
- TString hashFunctionNameIfNeeded(const TName &mangledName);
+ // Same as hashName(), but without hashing internal functions or "main".
+ TString hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info);
// Used to translate function names for differences between ESSL and GLSL
- virtual TString translateTextureFunction(TString &name) { return name; }
+ virtual TString translateTextureFunction(const TString &name) { return name; }
private:
bool structDeclared(const TStructure *structure) const;
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 87a7767..c0129da 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1590,7 +1590,7 @@
}
else
{
- out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj())
+ out << DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj())
<< DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "(");
}
@@ -1722,7 +1722,7 @@
TIntermSequence *arguments = node->getSequence();
- TString name = DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+ TString name = DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments)
<< (mOutputLod0Function ? "Lod0(" : "(");
@@ -1776,7 +1776,7 @@
ASSERT(index != CallDAG::InvalidIndex);
lod0 &= mASTMetadataList[index].mNeedsLod0;
- out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+ out << DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
out << DisambiguateFunctionName(node->getSequence());
out << (lod0 ? "Lod0(" : "(");
}
@@ -1784,11 +1784,11 @@
{
// This path is used for internal functions that don't have their definitions in the
// AST, such as precision emulation functions.
- out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
+ out << DecorateIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
}
else
{
- TString name = TFunction::unmangleName(node->getFunctionSymbolInfo()->getName());
+ const TString &name = node->getFunctionSymbolInfo()->getName();
TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType();
int coords = 0; // textureSize(gsampler2DMS) doesn't have a second argument.
if (arguments->size() > 1)
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index bdd68f3..f469746 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1443,11 +1443,9 @@
TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
if (!checkCanBeLValue(argument->getLine(), "assign", argument))
{
- TString unmangledName =
- TFunction::unmangleName(fnCall->getFunctionSymbolInfo()->getName());
error(argument->getLine(),
"Constant value cannot be passed for 'out' or 'inout' parameters.",
- unmangledName.c_str());
+ fnCall->getFunctionSymbolInfo()->getName().c_str());
return;
}
}
@@ -4277,16 +4275,13 @@
const TString &name = functionCall->getFunctionSymbolInfo()->getName();
TIntermNode *offset = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
- if (name.compare(0, 16, "texelFetchOffset") == 0 ||
- name.compare(0, 16, "textureLodOffset") == 0 ||
- name.compare(0, 20, "textureProjLodOffset") == 0 ||
- name.compare(0, 17, "textureGradOffset") == 0 ||
- name.compare(0, 21, "textureProjGradOffset") == 0)
+ if (name == "texelFetchOffset" || name == "textureLodOffset" ||
+ name == "textureProjLodOffset" || name == "textureGradOffset" ||
+ name == "textureProjGradOffset")
{
offset = arguments->back();
}
- else if (name.compare(0, 13, "textureOffset") == 0 ||
- name.compare(0, 17, "textureProjOffset") == 0)
+ else if (name == "textureOffset" || name == "textureProjOffset")
{
// A bias parameter might follow the offset parameter.
ASSERT(arguments->size() >= 3);
@@ -4297,9 +4292,8 @@
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
{
- TString unmangledName = TFunction::unmangleName(name);
error(functionCall->getLine(), "Texture offset must be a constant expression",
- unmangledName.c_str());
+ name.c_str());
}
else
{
diff --git a/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/compiler/translator/RewriteTexelFetchOffset.cpp
index 3be83df..554b044 100644
--- a/src/compiler/translator/RewriteTexelFetchOffset.cpp
+++ b/src/compiler/translator/RewriteTexelFetchOffset.cpp
@@ -71,7 +71,7 @@
return true;
}
- if (node->getFunctionSymbolInfo()->getName().compare(0, 16, "texelFetchOffset") != 0)
+ if (node->getFunctionSymbolInfo()->getName() != "texelFetchOffset")
{
return true;
}
@@ -80,16 +80,10 @@
const TIntermSequence *sequence = node->getSequence();
ASSERT(sequence->size() == 4u);
- // Decide if there is a 2DArray sampler.
- bool is2DArray = node->getFunctionSymbolInfo()->getName().find("s2a1") != TString::npos;
-
- // Create new argument list from node->getName().
- // e.g. Get "(is2a1;vi3;i1;" from "texelFetchOffset(is2a1;vi3;i1;vi2;"
- TString newArgs = node->getFunctionSymbolInfo()->getName().substr(
- 16, node->getFunctionSymbolInfo()->getName().length() - 20);
- TString newName = "texelFetch" + newArgs;
- TSymbol *texelFetchSymbol = symbolTable->findBuiltIn(newName, shaderVersion);
- ASSERT(texelFetchSymbol && texelFetchSymbol->isFunction());
+ // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is
+ // ivec2.
+ bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 &&
+ sequence->at(3)->getAsTyped()->getNominalSize() == 2;
// Create new node that represents the call of function texelFetch.
// Its argument list will be: texelFetch(sampler, Position+offset, lod).
@@ -135,6 +129,11 @@
ASSERT(texelFetchArguments->size() == 3u);
+ // Get the symbol of the texel fetch function to use.
+ TString mangledName = TFunction::GetMangledNameFromCall("texelFetch", *texelFetchArguments);
+ TSymbol *texelFetchSymbol = symbolTable->findBuiltIn(mangledName, shaderVersion);
+ ASSERT(texelFetchSymbol && texelFetchSymbol->isFunction());
+
TIntermAggregate *texelFetchNode = TIntermAggregate::CreateBuiltInFunctionCall(
*static_cast<const TFunction *>(texelFetchSymbol), texelFetchArguments);
texelFetchNode->setLine(node->getLine());
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 5f3e5d3..4ab958a 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -175,10 +175,6 @@
bool isFunction() const override { return true; }
static TString mangleName(const TString &name) { return name + '('; }
- static TString unmangleName(const TString &mangledName)
- {
- return TString(mangledName.c_str(), mangledName.find_first_of('('));
- }
void addParameter(const TConstParameter &p)
{
diff --git a/src/compiler/translator/UtilsHLSL.cpp b/src/compiler/translator/UtilsHLSL.cpp
index e3be724..accb3b5 100644
--- a/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/compiler/translator/UtilsHLSL.cpp
@@ -241,18 +241,6 @@
}
}
-TString DecorateFunctionIfNeeded(const TName &name)
-{
- if (name.isInternal())
- {
- return TFunction::unmangleName(name.getString());
- }
- else
- {
- return Decorate(TFunction::unmangleName(name.getString()));
- }
-}
-
TString TypeString(const TType &type)
{
const TStructure *structure = type.getStruct();
diff --git a/src/compiler/translator/UtilsHLSL.h b/src/compiler/translator/UtilsHLSL.h
index 61fd1ef..37edce4 100644
--- a/src/compiler/translator/UtilsHLSL.h
+++ b/src/compiler/translator/UtilsHLSL.h
@@ -65,8 +65,6 @@
// Prepends an underscore to avoid naming clashes
TString Decorate(const TString &string);
TString DecorateIfNeeded(const TName &name);
-// Decorates and also unmangles the function name
-TString DecorateFunctionIfNeeded(const TName &name);
TString DecorateUniform(const TName &name, const TType &type);
TString DecorateField(const TString &string, const TStructure &structure);
TString DecoratePrivate(const TString &privateText);
diff --git a/src/compiler/translator/ValidateLimitations.cpp b/src/compiler/translator/ValidateLimitations.cpp
index 0369eaa..e647e4c 100644
--- a/src/compiler/translator/ValidateLimitations.cpp
+++ b/src/compiler/translator/ValidateLimitations.cpp
@@ -402,8 +402,11 @@
bool valid = true;
TSymbolTable &symbolTable = GetGlobalParseContext()->symbolTable;
- TSymbol *symbol = symbolTable.find(node->getFunctionSymbolInfo()->getName(),
- GetGlobalParseContext()->getShaderVersion());
+ // TODO(oetuaho@nvidia.com): It would be neater to leverage TIntermLValueTrackingTraverser to
+ // keep track of out parameters, rather than doing a symbol table lookup here.
+ TString mangledName = TFunction::GetMangledNameFromCall(
+ node->getFunctionSymbolInfo()->getName(), *node->getSequence());
+ TSymbol *symbol = symbolTable.find(mangledName, GetGlobalParseContext()->getShaderVersion());
ASSERT(symbol && symbol->isFunction());
TFunction *function = static_cast<TFunction *>(symbol);
for (ParamIndex::const_iterator i = pIndex.begin(); i != pIndex.end(); ++i)
diff --git a/src/compiler/translator/ValidateMultiviewWebGL.cpp b/src/compiler/translator/ValidateMultiviewWebGL.cpp
index fa6cf02..79524fc 100644
--- a/src/compiler/translator/ValidateMultiviewWebGL.cpp
+++ b/src/compiler/translator/ValidateMultiviewWebGL.cpp
@@ -363,7 +363,7 @@
mValid = false;
}
else if (node->getOp() == EOpCallBuiltInFunction &&
- TFunction::unmangleName(node->getFunctionSymbolInfo()->getName()) == "imageStore")
+ node->getFunctionSymbolInfo()->getName() == "imageStore")
{
// TODO(oetuaho@nvidia.com): Record which built-in functions have side effects in
// the symbol info instead.
diff --git a/src/tests/compiler_tests/TypeTracking_test.cpp b/src/tests/compiler_tests/TypeTracking_test.cpp
index a2e20ed..0b71e9c 100644
--- a/src/tests/compiler_tests/TypeTracking_test.cpp
+++ b/src/tests/compiler_tests/TypeTracking_test.cpp
@@ -75,7 +75,7 @@
std::string mInfoLog;
};
-TEST_F(TypeTrackingTest, FunctionPrototypeMangling)
+TEST_F(TypeTrackingTest, FunctionPrototype)
{
const std::string &shaderString =
"precision mediump float;\n"
@@ -90,7 +90,7 @@
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
- ASSERT_TRUE(foundInIntermediateTree("Function Prototype: fun(f1;"));
+ ASSERT_TRUE(foundInIntermediateTree("Function Prototype: fun"));
}
TEST_F(TypeTrackingTest, BuiltInFunctionResultPrecision)
@@ -233,7 +233,7 @@
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
- ASSERT_TRUE(foundInIntermediateTree("texture2D(s21;vf2; (lowp 4-component vector of float)"));
+ ASSERT_TRUE(foundInIntermediateTree("texture2D (lowp 4-component vector of float)"));
}
TEST_F(TypeTrackingTest, TextureCubeResultTypeAndPrecision)
@@ -250,7 +250,7 @@
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
- ASSERT_TRUE(foundInIntermediateTree("textureCube(sC1;vf3; (lowp 4-component vector of float)"));
+ ASSERT_TRUE(foundInIntermediateTree("textureCube (lowp 4-component vector of float)"));
}
TEST_F(TypeTrackingTest, TextureSizeResultTypeAndPrecision)
@@ -271,7 +271,7 @@
"}\n";
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
- ASSERT_TRUE(foundInIntermediateTree("textureSize(s21;i1; (highp 2-component vector of int)"));
+ ASSERT_TRUE(foundInIntermediateTree("textureSize (highp 2-component vector of int)"));
}
TEST_F(TypeTrackingTest, BuiltInConstructorResultTypeAndPrecision)
diff --git a/src/tests/test_utils/compiler_test.cpp b/src/tests/test_utils/compiler_test.cpp
index 93d47d8..600e747 100644
--- a/src/tests/test_utils/compiler_test.cpp
+++ b/src/tests/test_utils/compiler_test.cpp
@@ -20,14 +20,18 @@
class FunctionCallFinder : public TIntermTraverser
{
public:
- FunctionCallFinder(const TString &functionName)
- : TIntermTraverser(true, false, false), mFunctionName(functionName), mNodeFound(nullptr)
+ FunctionCallFinder(const TString &functionMangledName)
+ : TIntermTraverser(true, false, false),
+ mFunctionMangledName(functionMangledName),
+ mNodeFound(nullptr)
{
}
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
- if (node->isFunctionCall() && node->getFunctionSymbolInfo()->getName() == mFunctionName)
+ if (node->isFunctionCall() &&
+ TFunction::GetMangledNameFromCall(node->getFunctionSymbolInfo()->getName(),
+ *node->getSequence()) == mFunctionMangledName)
{
mNodeFound = node;
return false;
@@ -39,7 +43,7 @@
const TIntermAggregate *getNode() const { return mNodeFound; }
private:
- TString mFunctionName;
+ TString mFunctionMangledName;
TIntermAggregate *mNodeFound;
};
@@ -208,9 +212,9 @@
return true;
}
-const TIntermAggregate *FindFunctionCallNode(TIntermNode *root, const TString &functionName)
+const TIntermAggregate *FindFunctionCallNode(TIntermNode *root, const TString &functionMangledName)
{
- FunctionCallFinder finder(functionName);
+ FunctionCallFinder finder(functionMangledName);
root->traverse(&finder);
return finder.getNode();
}