Prefix internal names in GLSL output
Prefixing internal names will avoid clashes with user-defined names.
We use prefix webgl_angle_ so that the internal names are both
reserved in WebGL on one hand and clearly separated from hashed names
starting with just webgl_ on the other hand.
BUG=angleproject:1597
TEST=WebGL conformance tests
Change-Id: I7deef9c1a38105c8b57eda13c84eec13e515a91a
Reviewed-on: https://chromium-review.googlesource.com/406247
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 66d40ec..a81f154 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -237,9 +237,8 @@
const TType &type = arg->getType();
writeVariableType(type);
- const TString &name = arg->getSymbol();
- if (!name.empty())
- out << " " << hashName(name);
+ if (!arg->getName().getString().empty())
+ out << " " << hashName(arg->getName());
if (type.isArray())
out << arrayBrackets(type);
@@ -257,7 +256,7 @@
if (type.getBasicType() == EbtStruct)
{
const TStructure *structure = type.getStruct();
- out << hashName(structure->name()) << "(";
+ out << hashName(TName(structure->name())) << "(";
const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
@@ -331,7 +330,7 @@
if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node))
out << mLoopUnrollStack.getLoopIndexValue(node);
else
- out << hashVariableName(node->getSymbol());
+ out << hashVariableName(node->getName());
if (mDeclaringVariables && node->getType().isArray())
out << arrayBrackets(node->getType());
@@ -464,7 +463,7 @@
TString fieldName = field->name();
if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
- fieldName = hashName(fieldName);
+ fieldName = hashName(TName(fieldName));
out << fieldName;
visitChildren = false;
@@ -481,7 +480,7 @@
TString fieldName = field->name();
ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion));
- fieldName = hashName(fieldName);
+ fieldName = hashName(TName(fieldName));
out << fieldName;
visitChildren = false;
@@ -928,7 +927,7 @@
ASSERT(sequence && sequence->size() == 1);
const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
ASSERT(symbol);
- out << "invariant " << hashVariableName(symbol->getSymbol());
+ out << "invariant " << hashVariableName(symbol->getName());
}
visitChildren = false;
break;
@@ -1104,7 +1103,7 @@
TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermSymbol *indexSymbol =
(*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
- TString name = hashVariableName(indexSymbol->getSymbol());
+ TString name = hashVariableName(indexSymbol->getName());
out << "for (int " << name << " = 0; "
<< name << " < 1; "
<< "++" << name << ")\n";
@@ -1192,27 +1191,43 @@
TString TOutputGLSLBase::getTypeName(const TType &type)
{
if (type.getBasicType() == EbtStruct)
- return hashName(type.getStruct()->name());
+ return hashName(TName(type.getStruct()->name()));
else
return type.getBuiltInTypeNameString();
}
-TString TOutputGLSLBase::hashName(const TString &name)
+TString TOutputGLSLBase::hashName(const TName &name)
{
- if (mHashFunction == NULL || name.empty())
- return name;
- NameMap::const_iterator it = mNameMap.find(name.c_str());
+ if (name.getString().empty())
+ {
+ ASSERT(!name.isInternal());
+ return name.getString();
+ }
+ if (name.isInternal())
+ {
+ // TODO(oetuaho): Would be nicer to prefix non-internal names with "_" instead, like is
+ // done in the HLSL output, but that requires fairly complex changes elsewhere in the code
+ // as well.
+ // We need to use a prefix that is reserved in WebGL in order to guarantee that the internal
+ // names don't conflict with user-defined names from WebGL.
+ return "webgl_angle_" + name.getString();
+ }
+ if (mHashFunction == nullptr)
+ {
+ return name.getString();
+ }
+ NameMap::const_iterator it = mNameMap.find(name.getString().c_str());
if (it != mNameMap.end())
return it->second.c_str();
- TString hashedName = TIntermTraverser::hash(name, mHashFunction);
- mNameMap[name.c_str()] = hashedName.c_str();
+ TString hashedName = TIntermTraverser::hash(name.getString(), mHashFunction);
+ mNameMap[name.getString().c_str()] = hashedName.c_str();
return hashedName;
}
-TString TOutputGLSLBase::hashVariableName(const TString &name)
+TString TOutputGLSLBase::hashVariableName(const TName &name)
{
- if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL)
- return name;
+ if (mSymbolTable.findBuiltIn(name.getString(), mShaderVersion) != NULL)
+ return name.getString();
return hashName(name);
}
@@ -1223,9 +1238,16 @@
if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main")
return translateTextureFunction(name);
if (mangledName.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;
+ }
else
- return hashName(name);
+ {
+ TName nameObj(name);
+ return hashName(nameObj);
+ }
}
bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
@@ -1243,14 +1265,14 @@
{
TInfoSinkBase &out = objSink();
- out << "struct " << hashName(structure->name()) << "{\n";
+ out << "struct " << hashName(TName(structure->name())) << "{\n";
const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
- out << getTypeName(*field->type()) << " " << hashName(field->name());
+ out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
if (field->type()->isArray())
out << arrayBrackets(*field->type());
out << ";\n";
@@ -1311,14 +1333,14 @@
{
TInfoSinkBase &out = objSink();
- out << hashName(interfaceBlock->name()) << "{\n";
+ out << hashName(TName(interfaceBlock->name())) << "{\n";
const TFieldList &fields = interfaceBlock->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
- out << getTypeName(*field->type()) << " " << hashName(field->name());
+ out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
if (field->type()->isArray())
out << arrayBrackets(*field->type());
out << ";\n";