Commit 8b5e8fdb by Olli Etuaho Committed by Commit Bot

Replace remaining usage of TName with TSymbol

TName used to contain just a subset of the information stored in TSymbol. It makes more sense to use TSymbol directly instead of converting it to TName. This also improves type safety a bit by making some functions only take in TVariable or TFunction instead of the more generic TName. BUG=angleproject:2267 TEST=angle_unittests Change-Id: Icb46923c25d33ebbbbc06ddc487da25957dda771 Reviewed-on: https://chromium-review.googlesource.com/829143 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 93b059db
......@@ -25,23 +25,24 @@ namespace
class ReplaceVariableTraverser : public TIntermTraverser
{
public:
ReplaceVariableTraverser(const TString &symbolName, TIntermSymbol *newSymbol)
: TIntermTraverser(true, false, false), mSymbolName(symbolName), mNewSymbol(newSymbol)
ReplaceVariableTraverser(const TVariable *toBeReplaced, const TVariable *replacement)
: TIntermTraverser(true, false, false),
mToBeReplaced(toBeReplaced),
mReplacement(replacement)
{
}
void visitSymbol(TIntermSymbol *node) override
{
const TName &name = node->getName();
if (name.getString() == mSymbolName)
if (&node->variable() == mToBeReplaced)
{
queueReplacement(mNewSymbol->deepCopy(), OriginalNode::IS_DROPPED);
queueReplacement(new TIntermSymbol(mReplacement), OriginalNode::IS_DROPPED);
}
}
private:
TString mSymbolName;
TIntermSymbol *mNewSymbol;
const TVariable *const mToBeReplaced;
const TVariable *const mReplacement;
};
TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
......@@ -50,8 +51,8 @@ TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
}
// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
TIntermTyped *instanceIDSymbol,
void InitializeViewIDAndInstanceID(const TVariable *viewID,
const TVariable *instanceID,
unsigned numberOfViews,
const TSymbolTable &symbolTable,
TIntermSequence *initializers)
......@@ -80,7 +81,7 @@ void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
// Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node.
TIntermBinary *instanceIDInitializer =
new TIntermBinary(EOpAssign, instanceIDSymbol->deepCopy(), normalizedInstanceIDAsInt);
new TIntermBinary(EOpAssign, new TIntermSymbol(instanceID), normalizedInstanceIDAsInt);
initializers->push_back(instanceIDInitializer);
// Create a uint(gl_InstanceID) % numberOfViews node.
......@@ -89,36 +90,37 @@ void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
// Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node.
TIntermBinary *viewIDInitializer =
new TIntermBinary(EOpAssign, viewIDSymbol->deepCopy(), normalizedViewID);
new TIntermBinary(EOpAssign, new TIntermSymbol(viewID), normalizedViewID);
initializers->push_back(viewIDInitializer);
}
// Replaces every occurrence of a symbol with the name specified in symbolName with newSymbolNode.
void ReplaceSymbol(TIntermBlock *root, const TString &symbolName, TIntermSymbol *newSymbolNode)
// Replaces every occurrence of a variable with another variable.
void ReplaceSymbol(TIntermBlock *root, const TVariable *toBeReplaced, const TVariable *replacement)
{
ReplaceVariableTraverser traverser(symbolName, newSymbolNode);
ReplaceVariableTraverser traverser(toBeReplaced, replacement);
root->traverse(&traverser);
traverser.updateTree();
}
void DeclareGlobalVariable(TIntermBlock *root, TIntermTyped *typedNode)
void DeclareGlobalVariable(TIntermBlock *root, const TVariable *variable)
{
TIntermSequence *globalSequence = root->getSequence();
TIntermDeclaration *declaration = new TIntermDeclaration();
declaration->appendDeclarator(typedNode->deepCopy());
declaration->appendDeclarator(new TIntermSymbol(variable));
TIntermSequence *globalSequence = root->getSequence();
globalSequence->insert(globalSequence->begin(), declaration);
}
// Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is
// added to the end of the initializers' sequence.
void SelectViewIndexInVertexShader(TIntermTyped *viewIDSymbol,
TIntermTyped *multiviewBaseViewLayerIndexSymbol,
void SelectViewIndexInVertexShader(const TVariable *viewID,
const TVariable *multiviewBaseViewLayerIndex,
TIntermSequence *initializers,
const TSymbolTable &symbolTable)
{
// Create an int(ViewID_OVR) node.
TIntermSequence *viewIDSymbolCastArguments = new TIntermSequence();
viewIDSymbolCastArguments->push_back(viewIDSymbol);
viewIDSymbolCastArguments->push_back(new TIntermSymbol(viewID));
TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor(
TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments);
......@@ -135,8 +137,8 @@ void SelectViewIndexInVertexShader(TIntermTyped *viewIDSymbol,
TIntermSymbol *layerSymbol = ReferenceBuiltInVariable("gl_Layer", symbolTable, 0);
// Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
TIntermBinary *sumOfViewIDAndBaseViewIndex =
new TIntermBinary(EOpAdd, viewIDAsInt->deepCopy(), multiviewBaseViewLayerIndexSymbol);
TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary(
EOpAdd, viewIDAsInt->deepCopy(), new TIntermSymbol(multiviewBaseViewLayerIndex));
// Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node.
TIntermBlock *layerInitializerInBlock = new TIntermBlock();
......@@ -145,7 +147,7 @@ void SelectViewIndexInVertexShader(TIntermTyped *viewIDSymbol,
// Create a node to compare whether the base view index uniform is less than zero.
TIntermBinary *multiviewBaseViewLayerIndexZeroComparison =
new TIntermBinary(EOpLessThan, multiviewBaseViewLayerIndexSymbol->deepCopy(),
new TIntermBinary(EOpLessThan, new TIntermSymbol(multiviewBaseViewLayerIndex),
CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst)));
// Create an if-else statement to select the code path.
......@@ -169,27 +171,29 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
const TString *viewIDVariableName = NewPoolTString("ViewID_OVR");
const TVariable *viewIDVariable =
const TVariable *viewID =
new TVariable(symbolTable, viewIDVariableName, TType(EbtUInt, EbpHigh, viewIDQualifier),
SymbolType::AngleInternal);
TIntermSymbol *viewIDSymbol = new TIntermSymbol(viewIDVariable);
DeclareGlobalVariable(root, viewIDSymbol);
ReplaceSymbol(root, "gl_ViewID_OVR", viewIDSymbol);
DeclareGlobalVariable(root, viewID);
ReplaceSymbol(root,
static_cast<TVariable *>(symbolTable->findBuiltIn("gl_ViewID_OVR", 300, true)),
viewID);
if (shaderType == GL_VERTEX_SHADER)
{
// Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
// InstanceID and ViewID.
const TString *instanceIDVariableName = NewPoolTString("InstanceID");
const TVariable *instanceIDVariable =
const TVariable *instanceID =
new TVariable(symbolTable, instanceIDVariableName, TType(EbtInt, EbpHigh, EvqGlobal),
SymbolType::AngleInternal);
TIntermSymbol *instanceIDSymbol = new TIntermSymbol(instanceIDVariable);
DeclareGlobalVariable(root, instanceIDSymbol);
ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol);
DeclareGlobalVariable(root, instanceID);
ReplaceSymbol(
root, static_cast<TVariable *>(symbolTable->findBuiltIn("gl_InstanceID", 300, true)),
instanceID);
TIntermSequence *initializers = new TIntermSequence();
InitializeViewIDAndInstanceID(viewIDSymbol, instanceIDSymbol, numberOfViews, *symbolTable,
InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable,
initializers);
// The AST transformation which adds the expression to select the viewport index should
......@@ -203,18 +207,15 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
// Add a uniform to switch between side-by-side and layered rendering.
const TString *multiviewBaseViewLayerIndexVariableName =
NewPoolTString("multiviewBaseViewLayerIndex");
const TVariable *multiviewBaseViewLayerIndexVariable =
const TVariable *multiviewBaseViewLayerIndex =
new TVariable(symbolTable, multiviewBaseViewLayerIndexVariableName,
TType(EbtInt, EbpHigh, EvqUniform), SymbolType::AngleInternal);
TIntermSymbol *multiviewBaseViewLayerIndexSymbol =
new TIntermSymbol(multiviewBaseViewLayerIndexVariable);
DeclareGlobalVariable(root, multiviewBaseViewLayerIndexSymbol);
DeclareGlobalVariable(root, multiviewBaseViewLayerIndex);
// Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's
// initialization.
SelectViewIndexInVertexShader(viewIDSymbol->deepCopy(),
multiviewBaseViewLayerIndexSymbol->deepCopy(),
initializers, *symbolTable);
SelectViewIndexInVertexShader(viewID, multiviewBaseViewLayerIndex, initializers,
*symbolTable);
}
// Insert initializers at the beginning of main().
......
......@@ -78,11 +78,12 @@ void GetDeferredInitializers(TIntermDeclaration *declaration,
TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
ASSERT(symbolNode);
// Ignore ANGLE internal variables.
if (symbolNode->getName().isInternal())
// Ignore ANGLE internal variables and nameless declarations.
if (symbolNode->variable().symbolType() == SymbolType::AngleInternal ||
symbolNode->variable().symbolType() == SymbolType::Empty)
return;
if (symbolNode->getQualifier() == EvqGlobal && symbolNode->getSymbol() != "")
if (symbolNode->getQualifier() == EvqGlobal)
{
TIntermSequence *initCode = CreateInitCode(symbolNode, canUseLoopsToInitialize,
highPrecisionSupported, symbolTable);
......
......@@ -16,6 +16,7 @@
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/RunAtTheEndOfShader.h"
#include "compiler/translator/Symbol.h"
namespace sh
{
......@@ -70,7 +71,7 @@ TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int
void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
{
if (node->getSymbol() == "gl_FragColor")
if (node->variable().symbolType() == SymbolType::BuiltIn && node->getName() == "gl_FragColor")
{
queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED);
mGLFragColorUsed = true;
......
......@@ -9,6 +9,7 @@
#include "compiler/translator/FindSymbolNode.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/Symbol.h"
namespace sh
{
......@@ -26,7 +27,7 @@ class SymbolFinder : public TIntermTraverser
void visitSymbol(TIntermSymbol *node)
{
if (node->getSymbol() == mSymbolName)
if (node->variable().symbolType() != SymbolType::Empty && node->getName() == mSymbolName)
{
mNodeFound = node;
}
......
......@@ -7,6 +7,7 @@
#include "compiler/translator/HashNames.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/Symbol.h"
namespace sh
{
......@@ -38,35 +39,45 @@ TString HashName(const TString &name, ShHashFunction64 hashFunction)
} // anonymous namespace
TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap)
TString HashName(const TString &name, ShHashFunction64 hashFunction, NameMap *nameMap)
{
if (name.getString().empty() || name.isInternal())
{
return name.getString();
}
if (hashFunction == nullptr)
{
if (name.getString().length() + kUnhashedNamePrefixLength > kESSLMaxIdentifierLength)
if (name.length() + kUnhashedNamePrefixLength > kESSLMaxIdentifierLength)
{
// If the identifier length is already close to the limit, we can't prefix it. This is
// not a problem since there are no builtins or ANGLE's internal variables that would
// have as long names and could conflict.
return name.getString();
return name;
}
return kUnhashedNamePrefix + name.getString();
return kUnhashedNamePrefix + name;
}
if (nameMap)
{
NameMap::const_iterator it = nameMap->find(name.getString().c_str());
NameMap::const_iterator it = nameMap->find(name.c_str());
if (it != nameMap->end())
return it->second.c_str();
}
TString hashedName = HashName(name.getString(), hashFunction);
TString hashedName = HashName(name, hashFunction);
if (nameMap)
{
(*nameMap)[name.getString().c_str()] = hashedName.c_str();
(*nameMap)[name.c_str()] = hashedName.c_str();
}
return hashedName;
}
TString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, NameMap *nameMap)
{
if (symbol->symbolType() == SymbolType::Empty)
{
return TString();
}
if (symbol->symbolType() == SymbolType::AngleInternal ||
symbol->symbolType() == SymbolType::BuiltIn)
{
return symbol->name();
}
return HashName(symbol->name(), hashFunction, nameMap);
}
} // namespace sh
......@@ -17,11 +17,13 @@ namespace sh
typedef std::map<TPersistString, TPersistString> NameMap;
class TName;
class TSymbol;
TString HashName(const TString &name, ShHashFunction64 hashFunction, NameMap *nameMap);
// Hash user-defined name for GLSL output, with special handling for internal names.
// The nameMap parameter is optional and is used to cache hashed names if set.
TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap);
TString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, NameMap *nameMap);
} // namespace sh
......
......@@ -224,7 +224,7 @@ class InitializeLocalsTraverser : public TIntermTraverser
{
TIntermSymbol *symbol = declarator->getAsSymbolNode();
ASSERT(symbol);
if (symbol->getSymbol() == "")
if (symbol->variable().symbolType() == SymbolType::Empty)
{
continue;
}
......
......@@ -140,16 +140,6 @@ void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resu
} // namespace anonymous
TName::TName(const TString &name) : mName(name), mIsInternal(false)
{
}
TName::TName(const TSymbol *symbol)
: mName(symbol->symbolType() == SymbolType::Empty ? "" : symbol->name()),
mIsInternal(symbol->symbolType() == SymbolType::AngleInternal)
{
}
////////////////////////////////////////////////////////////////
//
// Member functions of the nodes used for building the tree.
......@@ -278,7 +268,7 @@ bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
}
TIntermSymbol::TIntermSymbol(const TVariable *variable)
: TIntermTyped(variable->getType()), mVariable(variable), mSymbol(variable)
: TIntermTyped(variable->getType()), mVariable(variable)
{
}
......@@ -287,6 +277,11 @@ const TSymbolUniqueId &TIntermSymbol::uniqueId() const
return mVariable->uniqueId();
}
const TString &TIntermSymbol::getName() const
{
return mVariable->name();
}
TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func,
TIntermSequence *arguments)
{
......
......@@ -60,28 +60,6 @@ class TSymbolTable;
class TFunction;
class TVariable;
// Encapsulate an identifier string and track whether it is coming from the original shader code
// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
class TName
{
public:
POOL_ALLOCATOR_NEW_DELETE();
explicit TName(const TString &name);
explicit TName(const TSymbol *symbol);
TName() : mName(), mIsInternal(false) {}
TName(const TName &) = default;
TName &operator=(const TName &) = default;
const TString &getString() const { return mName; }
void setString(const TString &string) { mName = string; }
bool isInternal() const { return mIsInternal; }
void setInternal(bool isInternal) { mIsInternal = isInternal; }
private:
TString mName;
bool mIsInternal;
};
//
// Base class for the tree nodes
//
......@@ -267,8 +245,7 @@ class TIntermSymbol : public TIntermTyped
bool hasSideEffects() const override { return false; }
const TSymbolUniqueId &uniqueId() const;
const TString &getSymbol() const { return mSymbol.getString(); }
const TName &getName() const { return mSymbol; }
const TString &getName() const;
const TVariable &variable() const { return *mVariable; }
void traverse(TIntermTraverser *it) override;
......@@ -279,7 +256,6 @@ class TIntermSymbol : public TIntermTyped
TIntermSymbol(const TIntermSymbol &) = default; // Note: not deleted, just private!
const TVariable *const mVariable; // Guaranteed to be non-null
TName mSymbol;
};
// A Raw node stores raw code, that the translator will insert verbatim
......
......@@ -41,24 +41,32 @@ void TOutputGLSL::visitSymbol(TIntermSymbol *node)
{
TInfoSinkBase &out = objSink();
const TString &symbol = node->getSymbol();
if (symbol == "gl_FragDepthEXT")
// All the special cases are built-ins, so if it's not a built-in we can return early.
if (node->variable().symbolType() != SymbolType::BuiltIn)
{
TOutputGLSLBase::visitSymbol(node);
return;
}
// Some built-ins get a special translation.
const TString &name = node->getName();
if (name == "gl_FragDepthEXT")
{
out << "gl_FragDepth";
}
else if (symbol == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput()))
else if (name == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput()))
{
out << "webgl_FragColor";
}
else if (symbol == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput()))
else if (name == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput()))
{
out << "webgl_FragData";
}
else if (symbol == "gl_SecondaryFragColorEXT")
else if (name == "gl_SecondaryFragColorEXT")
{
out << "angle_SecondaryFragColor";
}
else if (symbol == "gl_SecondaryFragDataEXT")
else if (name == "gl_SecondaryFragDataEXT")
{
out << "angle_SecondaryFragData";
}
......
......@@ -339,8 +339,8 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
const TType &type = arg->getType();
writeVariableType(type);
if (!arg->getName().getString().empty())
out << " " << hashName(arg->getName());
if (arg->variable().symbolType() != SymbolType::Empty)
out << " " << hashName(&arg->variable());
if (type.isArray())
out << ArrayString(type);
......@@ -358,7 +358,7 @@ const TConstantUnion *TOutputGLSLBase::writeConstantUnion(const TType &type,
if (type.getBasicType() == EbtStruct)
{
const TStructure *structure = type.getStruct();
out << hashName(TName(structure->name())) << "(";
out << hashName(structure) << "(";
const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
......@@ -433,7 +433,7 @@ void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type)
void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
{
TInfoSinkBase &out = objSink();
out << hashVariableName(node->getName());
out << hashName(&node->variable());
if (mDeclaringVariable && node->getType().isArray())
out << ArrayString(node->getType());
......@@ -582,12 +582,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField *field = structure->fields()[index->getIConst(0)];
TString fieldName = field->name();
if (structure->symbolType() == SymbolType::UserDefined ||
structure->symbolType() == SymbolType::Empty)
fieldName = hashName(TName(fieldName));
out << fieldName;
out << hashFieldName(structure, field->name());
visitChildren = false;
}
break;
......@@ -599,19 +594,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
node->getLeft()->getType().getInterfaceBlock();
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField *field = interfaceBlock->fields()[index->getIConst(0)];
TString fieldName = field->name();
ASSERT(interfaceBlock->symbolType() != SymbolType::Empty);
if (interfaceBlock->symbolType() == SymbolType::UserDefined)
{
fieldName = hashName(TName(fieldName));
}
else
{
ASSERT(interfaceBlock->name() == "gl_PerVertex");
}
out << fieldName;
ASSERT(interfaceBlock->symbolType() == SymbolType::UserDefined ||
interfaceBlock->name() == "gl_PerVertex");
out << hashFieldName(interfaceBlock, field->name());
visitChildren = false;
}
break;
......@@ -901,7 +886,7 @@ bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDec
TInfoSinkBase &out = objSink();
ASSERT(visit == PreVisit);
const TIntermSymbol *symbol = node->getSymbol();
out << "invariant " << hashVariableName(symbol->getName());
out << "invariant " << hashName(&symbol->variable());
return false;
}
......@@ -1016,7 +1001,7 @@ bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
writeLayoutQualifier(variable);
writeVariableType(variable->getType());
if (variable->getAsSymbolNode() == nullptr ||
!variable->getAsSymbolNode()->getSymbol().empty())
variable->getAsSymbolNode()->variable().symbolType() != SymbolType::Empty)
{
out << " ";
}
......@@ -1128,19 +1113,22 @@ TString TOutputGLSLBase::getTypeName(const TType &type)
return GetTypeName(type, mHashFunction, &mNameMap);
}
TString TOutputGLSLBase::hashName(const TName &name)
TString TOutputGLSLBase::hashName(const TSymbol *symbol)
{
return HashName(name, mHashFunction, &mNameMap);
return HashName(symbol, mHashFunction, &mNameMap);
}
TString TOutputGLSLBase::hashVariableName(const TName &name)
TString TOutputGLSLBase::hashFieldName(const TSymbol *containingStruct, const TString &fieldName)
{
if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr ||
name.getString().substr(0, 3) == "gl_")
if (containingStruct->symbolType() == SymbolType::UserDefined ||
containingStruct->symbolType() == SymbolType::Empty)
{
return HashName(fieldName, mHashFunction, &mNameMap);
}
else
{
return name.getString();
return fieldName;
}
return hashName(name);
}
TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunction *func)
......@@ -1151,7 +1139,7 @@ TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunction *func)
}
else
{
return hashName(TName(func));
return hashName(func);
}
}
......@@ -1174,7 +1162,7 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure)
if (structure->symbolType() != SymbolType::Empty)
{
out << hashName(TName(structure->name())) << " ";
out << hashName(structure) << " ";
}
out << "{\n";
const TFieldList &fields = structure->fields();
......@@ -1183,7 +1171,7 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure)
const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
out << getTypeName(*field->type()) << " " << hashFieldName(structure, field->name());
if (field->type()->isArray())
out << ArrayString(*field->type());
out << ";\n";
......@@ -1235,7 +1223,7 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc
{
TInfoSinkBase &out = objSink();
out << hashName(TName(interfaceBlock->name())) << "{\n";
out << hashName(interfaceBlock) << "{\n";
const TFieldList &fields = interfaceBlock->fields();
for (const TField *field : fields)
{
......@@ -1263,7 +1251,7 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
out << getTypeName(*field->type()) << " " << hashFieldName(interfaceBlock, field->name());
if (field->type()->isArray())
out << ArrayString(*field->type());
out << ";\n";
......
......@@ -32,9 +32,9 @@ class TOutputGLSLBase : public TIntermTraverser
ShShaderOutput getShaderOutput() const { return mOutput; }
// Return the original name if hash function pointer is NULL;
// otherwise return the hashed name. Has special handling for internal names, which are not
// hashed.
TString hashName(const TName &name);
// otherwise return the hashed name. Has special handling for internal names and built-ins,
// which are not hashed.
TString hashName(const TSymbol *symbol);
protected:
TInfoSinkBase &objSink() { return mObjSink; }
......@@ -69,9 +69,8 @@ class TOutputGLSLBase : public TIntermTraverser
void visitCodeBlock(TIntermBlock *node);
// Same as hashName(), but without hashing built-in variables.
TString hashVariableName(const TName &name);
// Same as hashName(), but without hashing internal functions or "main".
TString hashFieldName(const TSymbol *containingStruct, const TString &fieldName);
// Same as hashName(), but without hashing "main".
TString hashFunctionNameIfNeeded(const TFunction *func);
// Used to translate function names for differences between ESSL and GLSL
virtual TString translateTextureFunction(const TString &name) { return name; }
......
......@@ -81,7 +81,14 @@ void TOutputTraverser::visitSymbol(TIntermSymbol *node)
{
OutputTreeText(mOut, node, mDepth);
mOut << "'" << node->getSymbol() << "' ";
if (node->variable().symbolType() == SymbolType::Empty)
{
mOut << "''";
}
else
{
mOut << "'" << node->getName() << "' ";
}
mOut << "(symbol id " << node->uniqueId().get() << ") ";
mOut << "(" << node->getCompleteString() << ")";
mOut << "\n";
......
......@@ -65,7 +65,7 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
if (needsCustomLayout)
{
out << "@@ LAYOUT-" << symbol->getName().getString() << " @@";
out << "@@ LAYOUT-" << symbol->getName() << " @@";
}
if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
......
......@@ -88,7 +88,7 @@ const char *GetImageArgumentToken(TIntermTyped *imageNode)
TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
if (imageSymbol)
{
return imageSymbol->getSymbol().c_str();
return imageSymbol->getName().c_str();
}
return "image";
}
......@@ -606,7 +606,10 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn
//
if (symNode)
{
const char *symbol = symNode->getSymbol().c_str();
// Symbol inside an expression can't be nameless.
ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
const char *symbol = symNode->getName().c_str();
std::stringstream reasonStream;
reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
std::string reason = reasonStream.str();
......@@ -3928,7 +3931,7 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
if (baseExpression->getAsSymbolNode())
{
error(location, " left of '[' is not of type array, matrix, or vector ",
baseExpression->getAsSymbolNode()->getSymbol().c_str());
baseExpression->getAsSymbolNode()->getName().c_str());
}
else
{
......
......@@ -14,6 +14,7 @@
#include "compiler/translator/PruneNoOps.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/Symbol.h"
namespace sh
{
......@@ -66,7 +67,8 @@ bool PruneNoOpsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
{
TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
// Prune declarations without a variable name, unless it's an interface block declaration.
if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
if (sym != nullptr && sym->variable().symbolType() == SymbolType::Empty &&
!sym->isInterfaceBlock())
{
if (sequence->size() > 1)
{
......
......@@ -187,7 +187,8 @@ void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDecl
// count will end up being one less than the correct refcount. But since the struct
// declaration is kept, the incorrect refcount can't cause any other problems.
if (declarator->getAsSymbolNode() && declarator->getAsSymbolNode()->getSymbol().empty())
if (declarator->getAsSymbolNode() &&
declarator->getAsSymbolNode()->variable().symbolType() == SymbolType::Empty)
{
// Already an empty declaration - nothing to do.
return;
......@@ -235,7 +236,7 @@ bool RemoveUnreferencedVariablesTraverser::visitDeclaration(Visit visit, TInterm
if (symbolNode != nullptr)
{
canRemoveVariable = (*mSymbolIdRefCounts)[symbolNode->uniqueId().get()] == 1u ||
symbolNode->getSymbol().empty();
symbolNode->variable().symbolType() == SymbolType::Empty;
}
TIntermBinary *initNode = declarator->getAsBinaryNode();
if (initNode != nullptr)
......
......@@ -36,6 +36,7 @@ TSymbol::TSymbol(TSymbolTable *symbolTable,
ASSERT(mSymbolType == SymbolType::BuiltIn || mExtension == TExtension::UNDEFINED);
ASSERT(mName != nullptr || mSymbolType == SymbolType::AngleInternal ||
mSymbolType == SymbolType::NotResolved || mSymbolType == SymbolType::Empty);
ASSERT(mName == nullptr || *mName != "");
}
const TString &TSymbol::name() const
......
......@@ -77,8 +77,8 @@ class DeclareDefaultUniformsTraverser : public TIntermTraverser
{
if (mInDefaultUniform)
{
const TName &name = symbol->getName();
ASSERT(name.getString().substr(0, 3) != "gl_");
const TString &name = symbol->variable().name();
ASSERT(name.substr(0, 3) != "gl_");
(*mSink) << HashName(name, mHashFunction, mNameMap);
}
}
......
......@@ -210,7 +210,7 @@ void UniformHLSL::outputHLSLSamplerUniformGroup(
for (const TIntermSymbol *uniform : group)
{
const TType &type = uniform->getType();
const TString &name = uniform->getSymbol();
const TString &name = uniform->getName();
unsigned int registerCount;
// The uniform might be just a regular sampler or one extracted from a struct.
......@@ -231,14 +231,14 @@ void UniformHLSL::outputHLSLSamplerUniformGroup(
if (type.isArray())
{
out << "static const uint " << DecorateVariableIfNeeded(uniform->getName())
out << "static const uint " << DecorateVariableIfNeeded(uniform->variable())
<< ArrayString(type) << " = ";
OutputSamplerIndexArrayInitializer(out, type, samplerArrayIndex);
out << ";\n";
}
else
{
out << "static const uint " << DecorateVariableIfNeeded(uniform->getName()) << " = "
out << "static const uint " << DecorateVariableIfNeeded(uniform->variable()) << " = "
<< samplerArrayIndex << ";\n";
}
}
......@@ -262,20 +262,20 @@ void UniformHLSL::outputHLSLSamplerUniformGroup(
void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex)
{
out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
<< DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(s"
<< DecorateVariableIfNeeded(variable) << ArrayString(type) << " : register(s"
<< str(registerIndex) << ");\n";
out << "uniform " << TextureString(type.getBasicType()) << " texture_"
<< DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t"
<< DecorateVariableIfNeeded(variable) << ArrayString(type) << " : register(t"
<< str(registerIndex) << ");\n";
}
void UniformHLSL::outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex)
{
// TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
......@@ -284,14 +284,14 @@ void UniformHLSL::outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
// temporary Texture2D to image2D variable.
out << "uniform "
<< TextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) << " "
<< DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t"
<< DecorateVariableIfNeeded(variable) << ArrayString(type) << " : register(t"
<< str(registerIndex) << ");\n";
return;
}
void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex)
{
// TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
......@@ -302,7 +302,7 @@ void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
{
out << "uniform "
<< RWTextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat)
<< " " << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(u"
<< " " << DecorateVariableIfNeeded(variable) << ArrayString(type) << " : register(u"
<< str(registerIndex) << ");\n";
}
else
......@@ -315,7 +315,7 @@ void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
void UniformHLSL::outputUniform(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex)
{
const TStructure *structure = type.getStruct();
......@@ -333,7 +333,7 @@ void UniformHLSL::outputUniform(TInfoSinkBase &out,
out << "uniform " << typeName << " ";
out << DecorateVariableIfNeeded(name);
out << DecorateVariableIfNeeded(variable);
out << ArrayString(type) << " : " << registerString << ";\n";
}
......@@ -358,7 +358,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
// Output regular uniforms. Group sampler uniforms by type.
const TIntermSymbol &uniform = *uniformIt.second;
const TType &type = uniform.getType();
const TName &name = uniform.getName();
const TVariable &variable = uniform.variable();
if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
{
......@@ -367,8 +367,8 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
}
else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
{
unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex);
unsigned int registerIndex = assignUniformRegister(type, variable.name(), nullptr);
outputHLSL4_0_FL9_3Sampler(out, type, variable, registerIndex);
}
else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType()))
{
......@@ -380,12 +380,12 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
{
TVector<TIntermSymbol *> samplerSymbols;
TMap<TIntermSymbol *, TString> symbolsToAPINames;
type.createSamplerSymbols("angle_" + name.getString(), name.getString(),
type.createSamplerSymbols("angle_" + uniform.getName(), uniform.getName(),
&samplerSymbols, &symbolsToAPINames, symbolTable);
for (TIntermSymbol *sampler : samplerSymbols)
{
const TType &samplerType = sampler->getType();
const TName &samplerName = sampler->getName();
const TVariable &samplerVariable = sampler->variable();
if (outputType == SH_HLSL_4_1_OUTPUT)
{
......@@ -397,19 +397,20 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
{
unsigned int registerIndex = assignSamplerInStructUniformRegister(
samplerType, symbolsToAPINames[sampler], nullptr);
outputHLSL4_0_FL9_3Sampler(out, samplerType, samplerName, registerIndex);
outputHLSL4_0_FL9_3Sampler(out, samplerType, samplerVariable,
registerIndex);
}
else
{
ASSERT(outputType == SH_HLSL_3_0_OUTPUT);
unsigned int registerIndex = assignSamplerInStructUniformRegister(
samplerType, symbolsToAPINames[sampler], nullptr);
outputUniform(out, samplerType, samplerName, registerIndex);
outputUniform(out, samplerType, samplerVariable, registerIndex);
}
}
}
unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
outputUniform(out, type, name, registerIndex);
unsigned int registerIndex = assignUniformRegister(type, uniform.getName(), nullptr);
outputUniform(out, type, variable, registerIndex);
}
}
......@@ -429,15 +430,15 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
for (const TIntermSymbol *image : imageUniformsHLSL41Output)
{
const TType &type = image->getType();
const TName &name = image->getName();
unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
const TVariable &variable = image->variable();
unsigned int registerIndex = assignUniformRegister(type, image->getName(), nullptr);
if (type.getMemoryQualifier().readonly)
{
outputHLSL4_1_FL11Texture(out, type, name, registerIndex);
outputHLSL4_1_FL11Texture(out, type, variable, registerIndex);
}
else
{
outputHLSL4_1_FL11RWTexture(out, type, name, registerIndex);
outputHLSL4_1_FL11RWTexture(out, type, variable, registerIndex);
}
}
}
......@@ -472,7 +473,7 @@ TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInte
// nodeType.isInterfaceBlock() == false means the node is a field of a uniform block which
// doesn't have instance name.
const TString &instanceName =
nodeType.isInterfaceBlock() ? interfaceBlockReference.second->getSymbol() : "";
nodeType.isInterfaceBlock() ? interfaceBlockReference.second->getName() : "";
if (instanceName != "")
{
......
......@@ -63,19 +63,19 @@ class UniformHLSL : angle::NonCopyable
void outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex);
void outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex);
void outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex);
void outputUniform(TInfoSinkBase &out,
const TType &type,
const TName &name,
const TVariable &variable,
const unsigned int registerIndex);
// Returns the uniform's register index
......
......@@ -715,18 +715,19 @@ TString Decorate(const TString &string)
return string;
}
TString DecorateVariableIfNeeded(const TName &name)
TString DecorateVariableIfNeeded(const TVariable &variable)
{
if (name.isInternal())
if (variable.symbolType() == SymbolType::AngleInternal)
{
const TString &name = variable.name();
// The name should not have a prefix reserved for user-defined variables or functions.
ASSERT(name.getString().compare(0, 2, "f_") != 0);
ASSERT(name.getString().compare(0, 1, "_") != 0);
return name.getString();
ASSERT(name.compare(0, 2, "f_") != 0);
ASSERT(name.compare(0, 1, "_") != 0);
return name;
}
else
{
return Decorate(name.getString());
return Decorate(variable.name());
}
}
......
......@@ -16,8 +16,6 @@
#include "angle_gl.h"
class TName;
namespace sh
{
......@@ -110,7 +108,7 @@ TString SamplerString(HLSLTextureGroup type);
// Adds a prefix to user-defined names to avoid naming clashes.
TString Decorate(const TString &string);
TString DecorateVariableIfNeeded(const TName &name);
TString DecorateVariableIfNeeded(const TVariable &variable);
TString DecorateFunctionIfNeeded(const TFunction *func);
TString DecorateField(const TString &string, const TStructure &structure);
TString DecoratePrivate(const TString &privateText);
......
......@@ -119,7 +119,7 @@ void ValidateLimitationsTraverser::visitSymbol(TIntermSymbol *node)
{
error(node->getLine(),
"Loop index cannot be statically assigned to within the body of the loop",
node->getSymbol().c_str());
node->getName().c_str());
}
}
......@@ -248,7 +248,7 @@ int ValidateLimitationsTraverser::validateForLoopInit(TIntermLoop *node)
if (!isConstExpr(declInit->getRight()))
{
error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression",
symbol->getSymbol().c_str());
symbol->getName().c_str());
return -1;
}
......@@ -282,7 +282,7 @@ bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int in
}
if (symbol->uniqueId().get() != indexSymbolId)
{
error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
error(symbol->getLine(), "Expected loop index", symbol->getName().c_str());
return false;
}
// Relational operator is one of: > >= < <= == or !=.
......@@ -304,7 +304,7 @@ bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int in
if (!isConstExpr(binOp->getRight()))
{
error(binOp->getLine(), "Loop index cannot be compared with non-constant expression",
symbol->getSymbol().c_str());
symbol->getName().c_str());
return false;
}
......@@ -353,7 +353,7 @@ bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int in
}
if (symbol->uniqueId().get() != indexSymbolId)
{
error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
error(symbol->getLine(), "Expected loop index", symbol->getName().c_str());
return false;
}
......@@ -381,7 +381,7 @@ bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int in
if (!isConstExpr(binOp->getRight()))
{
error(binOp->getLine(), "Loop index cannot be modified by non-constant expression",
symbol->getSymbol().c_str());
symbol->getName().c_str());
return false;
}
}
......
......@@ -20,9 +20,10 @@ namespace sh
namespace
{
void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
{
diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
diagnostics->error(symbol.getLine(), reason, symbol.getName().c_str());
}
class ValidateOutputsTraverser : public TIntermTraverser
......@@ -112,7 +113,7 @@ void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const
{
std::stringstream strstr;
strstr << "conflicting output locations with previously defined output '"
<< validOutputs[offsetLocation]->getSymbol() << "'";
<< validOutputs[offsetLocation]->getName() << "'";
error(*symbol, strstr.str().c_str(), diagnostics);
}
else
......
......@@ -22,7 +22,7 @@ namespace
void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
{
diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
diagnostics->error(symbol.getLine(), reason, symbol.getName().c_str());
}
int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
......@@ -84,9 +84,9 @@ void ValidateShaderInterface(TDiagnostics *diagnostics,
if (locationMap.find(offsetLocation) != locationMap.end())
{
std::stringstream strstr;
strstr << "'" << varying->getSymbol()
strstr << "'" << varying->getName()
<< "' conflicting location with previously defined '"
<< locationMap[offsetLocation]->getSymbol() << "'";
<< locationMap[offsetLocation]->getName() << "'";
error(*varying, strstr.str().c_str(), diagnostics);
}
else
......@@ -128,6 +128,11 @@ bool ValidateVaryingLocationsTraverser::visitDeclaration(Visit visit, TIntermDec
return false;
}
if (symbol->variable().symbolType() == SymbolType::Empty)
{
return false;
}
// Collect varyings that have explicit 'location' qualifiers.
const TQualifier qualifier = symbol->getQualifier();
if (symbol->getType().getLayoutQualifier().location != -1)
......
......@@ -7,6 +7,7 @@
#include "compiler/translator/VersionGLSL.h"
#include "angle_gl.h"
#include "compiler/translator/Symbol.h"
namespace sh
{
......@@ -76,7 +77,7 @@ TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutpu
void TVersionGLSL::visitSymbol(TIntermSymbol *node)
{
if (node->getSymbol() == "gl_PointCoord")
if (node->variable().symbolType() == SymbolType::BuiltIn && node->getName() == "gl_PointCoord")
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
}
......
......@@ -476,7 +476,7 @@ TString ArrayString(const TType &type)
TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap)
{
if (type.getBasicType() == EbtStruct)
return HashName(TName(type.getStruct()->name()), hashFunction, nameMap);
return HashName(type.getStruct(), hashFunction, nameMap);
else
return type.getBuiltInTypeNameString();
}
......
......@@ -36,7 +36,9 @@ bool AreSymbolsTheSame(const TIntermSymbol *expected, const TIntermSymbol *candi
const bool sameTypes = expectedType == candidateType &&
expectedType.getPrecision() == candidateType.getPrecision() &&
expectedType.getQualifier() == candidateType.getQualifier();
const bool sameSymbols = expected->getSymbol() == candidate->getSymbol();
const bool sameSymbols = (expected->variable().symbolType() == SymbolType::Empty &&
candidate->variable().symbolType() == SymbolType::Empty) ||
expected->getName() == candidate->getName();
return sameSymbols && sameTypes;
}
......
......@@ -76,8 +76,7 @@ class IntermNodeTest : public testing::Test
ASSERT_NE(original, copy);
ASSERT_EQ(&original->variable(), &copy->variable());
ASSERT_EQ(original->uniqueId(), copy->uniqueId());
ASSERT_EQ(original->getName().getString(), copy->getName().getString());
ASSERT_EQ(original->getName().isInternal(), copy->getName().isInternal());
ASSERT_EQ(original->getName(), copy->getName());
checkTypeEqualWithQualifiers(original->getType(), copy->getType());
ASSERT_EQ(original->getLine().first_file, copy->getLine().first_file);
ASSERT_EQ(original->getLine().first_line, copy->getLine().first_line);
......
......@@ -62,7 +62,7 @@ class SymbolOccurrenceCounterByName : public SymbolOccurrenceCounter
bool shouldCountSymbol(const TIntermSymbol *node) const override
{
return node->getName().getString() == mSymbolName;
return node->variable().symbolType() != SymbolType::Empty && node->getName() == mSymbolName;
}
private:
......@@ -79,8 +79,8 @@ class SymbolOccurrenceCounterByNameAndQualifier : public SymbolOccurrenceCounter
bool shouldCountSymbol(const TIntermSymbol *node) const override
{
return node->getName().getString() == mSymbolName &&
node->getQualifier() == mSymbolQualifier;
return node->variable().symbolType() != SymbolType::Empty &&
node->getName() == mSymbolName && node->getQualifier() == mSymbolQualifier;
}
private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment