Commit ae4dbf32 by Olli Etuaho Committed by Commit Bot

Don't allocate name strings for empty symbols

This removes unnecessary memory allocations. BUG=angleproject:2267 TEST=angle_unittests Change-Id: Ide575ea19ab2f8e9fc93092490f1352efa6024a3 Reviewed-on: https://chromium-review.googlesource.com/817415 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent f2afccca
...@@ -91,7 +91,8 @@ ShaderVariable *FindVariableInInterfaceBlock(const TString &name, ...@@ -91,7 +91,8 @@ ShaderVariable *FindVariableInInterfaceBlock(const TString &name,
std::vector<InterfaceBlock> *infoList) std::vector<InterfaceBlock> *infoList)
{ {
ASSERT(interfaceBlock); ASSERT(interfaceBlock);
InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList); ASSERT(interfaceBlock->name());
InterfaceBlock *namedBlock = FindVariable(*interfaceBlock->name(), infoList);
ASSERT(namedBlock); ASSERT(namedBlock);
// Set static use on the parent interface block here // Set static use on the parent interface block here
...@@ -569,7 +570,10 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, ...@@ -569,7 +570,10 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
{ {
// Structures use a NONE type that isn't exposed outside ANGLE. // Structures use a NONE type that isn't exposed outside ANGLE.
variableOut->type = GL_NONE; variableOut->type = GL_NONE;
variableOut->structName = structure->name().c_str(); if (structure->symbolType() != SymbolType::Empty)
{
variableOut->structName = structure->name()->c_str();
}
const TFieldList &fields = structure->fields(); const TFieldList &fields = structure->fields();
...@@ -578,7 +582,7 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, ...@@ -578,7 +582,7 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
// Regardless of the variable type (uniform, in/out etc.) its fields are always plain // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
// ShaderVariable objects. // ShaderVariable objects.
ShaderVariable fieldVariable; ShaderVariable fieldVariable;
setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable); setCommonVariableProperties(*field->type(), TName(&field->name()), &fieldVariable);
variableOut->fields.push_back(fieldVariable); variableOut->fields.push_back(fieldVariable);
} }
} }
...@@ -657,7 +661,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TString &instanceName ...@@ -657,7 +661,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TString &instanceName
const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock(); const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
ASSERT(blockType); ASSERT(blockType);
interfaceBlock->name = blockType->name().c_str(); interfaceBlock->name = blockType->name()->c_str();
interfaceBlock->mappedName = getMappedName(TName(blockType->name())); interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
interfaceBlock->instanceName = instanceName.c_str(); interfaceBlock->instanceName = instanceName.c_str();
ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
...@@ -679,7 +683,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TString &instanceName ...@@ -679,7 +683,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TString &instanceName
const TType &fieldType = *field->type(); const TType &fieldType = *field->type();
InterfaceBlockField fieldVariable; InterfaceBlockField fieldVariable;
setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable); setCommonVariableProperties(fieldType, TName(&field->name()), &fieldVariable);
fieldVariable.isRowMajorLayout = fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
interfaceBlock->fields.push_back(fieldVariable); interfaceBlock->fields.push_back(fieldVariable);
...@@ -825,7 +829,7 @@ bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode) ...@@ -825,7 +829,7 @@ bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock(); const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
if (!namedBlock) if (!namedBlock)
{ {
namedBlock = findNamedInterfaceBlock(interfaceBlock->name()); namedBlock = findNamedInterfaceBlock(*interfaceBlock->name());
} }
ASSERT(namedBlock); ASSERT(namedBlock);
namedBlock->staticUse = true; namedBlock->staticUse = true;
......
...@@ -431,7 +431,7 @@ TIntermAggregate *createInternalFunctionCallNode(const TType &type, ...@@ -431,7 +431,7 @@ TIntermAggregate *createInternalFunctionCallNode(const TType &type,
TString name, TString name,
TIntermSequence *arguments) TIntermSequence *arguments)
{ {
TName nameObj(name); TName nameObj(&name);
nameObj.setInternal(true); nameObj.setInternal(true);
TIntermAggregate *callNode = TIntermAggregate *callNode =
TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments); TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments);
......
...@@ -144,6 +144,10 @@ void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resu ...@@ -144,6 +144,10 @@ void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resu
} // namespace anonymous } // namespace anonymous
TName::TName(const TString *name) : mName(name ? (*name) : ""), mIsInternal(false)
{
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// //
// Member functions of the nodes used for building the tree. // Member functions of the nodes used for building the tree.
...@@ -576,7 +580,7 @@ TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : T ...@@ -576,7 +580,7 @@ TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : T
void TFunctionSymbolInfo::setFromFunction(const TFunction &function) void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
{ {
setName(function.name()); setName(*function.name());
setId(TSymbolUniqueId(function)); setId(TSymbolUniqueId(function));
} }
......
...@@ -66,7 +66,7 @@ class TName ...@@ -66,7 +66,7 @@ class TName
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
explicit TName(const TString &name) : mName(name), mIsInternal(false) {} explicit TName(const TString *name);
TName() : mName(), mIsInternal(false) {} TName() : mName(), mIsInternal(false) {}
TName(const TName &) = default; TName(const TName &) = default;
TName &operator=(const TName &) = default; TName &operator=(const TName &) = default;
......
...@@ -19,7 +19,7 @@ namespace ...@@ -19,7 +19,7 @@ namespace
TName GetInternalFunctionName(const char *name) TName GetInternalFunctionName(const char *name)
{ {
TString nameStr(name); TString nameStr(name);
TName nameObj(nameStr); TName nameObj(&nameStr);
nameObj.setInternal(true); nameObj.setInternal(true);
return nameObj; return nameObj;
} }
......
...@@ -585,7 +585,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) ...@@ -585,7 +585,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
TString fieldName = field->name(); TString fieldName = field->name();
if (structure->symbolType() == SymbolType::UserDefined || if (structure->symbolType() == SymbolType::UserDefined ||
structure->symbolType() == SymbolType::Empty) structure->symbolType() == SymbolType::Empty)
fieldName = hashName(TName(fieldName)); fieldName = hashName(TName(&fieldName));
out << fieldName; out << fieldName;
visitChildren = false; visitChildren = false;
...@@ -604,11 +604,11 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) ...@@ -604,11 +604,11 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
ASSERT(interfaceBlock->symbolType() != SymbolType::Empty); ASSERT(interfaceBlock->symbolType() != SymbolType::Empty);
if (interfaceBlock->symbolType() == SymbolType::UserDefined) if (interfaceBlock->symbolType() == SymbolType::UserDefined)
{ {
fieldName = hashName(TName(fieldName)); fieldName = hashName(TName(&fieldName));
} }
else else
{ {
ASSERT(interfaceBlock->name() == "gl_PerVertex"); ASSERT(*interfaceBlock->name() == "gl_PerVertex");
} }
out << fieldName; out << fieldName;
...@@ -1177,7 +1177,7 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure) ...@@ -1177,7 +1177,7 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure)
const TField *field = fields[i]; const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision())) if (writeVariablePrecision(field->type()->getPrecision()))
out << " "; out << " ";
out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); out << getTypeName(*field->type()) << " " << hashName(TName(&field->name()));
if (field->type()->isArray()) if (field->type()->isArray())
out << ArrayString(*field->type()); out << ArrayString(*field->type());
out << ";\n"; out << ";\n";
...@@ -1257,7 +1257,7 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc ...@@ -1257,7 +1257,7 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc
if (writeVariablePrecision(field->type()->getPrecision())) if (writeVariablePrecision(field->type()->getPrecision()))
out << " "; out << " ";
out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); out << getTypeName(*field->type()) << " " << hashName(TName(&field->name()));
if (field->type()->isArray()) if (field->type()->isArray())
out << ArrayString(*field->type()); out << ArrayString(*field->type());
out << ";\n"; out << ";\n";
......
...@@ -341,7 +341,7 @@ TString OutputHLSL::generateStructMapping(const std::vector<MappedStruct> &std14 ...@@ -341,7 +341,7 @@ TString OutputHLSL::generateStructMapping(const std::vector<MappedStruct> &std14
{ {
TInterfaceBlock *interfaceBlock = TInterfaceBlock *interfaceBlock =
mappedStruct.blockDeclarator->getType().getInterfaceBlock(); mappedStruct.blockDeclarator->getType().getInterfaceBlock();
const TString &interfaceBlockName = interfaceBlock->name(); const TString &interfaceBlockName = *interfaceBlock->name();
const TName &instanceName = mappedStruct.blockDeclarator->getName(); const TName &instanceName = mappedStruct.blockDeclarator->getName();
if (mReferencedUniformBlocks.count(interfaceBlockName) == 0) if (mReferencedUniformBlocks.count(interfaceBlockName) == 0)
{ {
...@@ -380,7 +380,7 @@ TString OutputHLSL::generateStructMapping(const std::vector<MappedStruct> &std14 ...@@ -380,7 +380,7 @@ TString OutputHLSL::generateStructMapping(const std::vector<MappedStruct> &std14
TType *structType = mappedStruct.field->type(); TType *structType = mappedStruct.field->type();
mappedStructs += mappedStructs +=
"static " + Decorate(structType->getStruct()->name()) + " " + mappedName; "static " + Decorate(*structType->getStruct()->name()) + " " + mappedName;
if (structType->isArray()) if (structType->isArray())
{ {
...@@ -890,7 +890,7 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) ...@@ -890,7 +890,7 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
if (interfaceBlock) if (interfaceBlock)
{ {
mReferencedUniformBlocks[interfaceBlock->name()] = node; mReferencedUniformBlocks[*interfaceBlock->name()] = node;
} }
else else
{ {
...@@ -1238,7 +1238,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1238,7 +1238,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
{ {
TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock(); TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock();
TIntermSymbol *instanceArraySymbol = node->getLeft()->getAsSymbolNode(); TIntermSymbol *instanceArraySymbol = node->getLeft()->getAsSymbolNode();
mReferencedUniformBlocks[interfaceBlock->name()] = instanceArraySymbol; mReferencedUniformBlocks[*interfaceBlock->name()] = instanceArraySymbol;
const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0); const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
out << mUniformHLSL->UniformBlockInstanceString( out << mUniformHLSL->UniformBlockInstanceString(
instanceArraySymbol->getSymbol(), arrayIndex); instanceArraySymbol->getSymbol(), arrayIndex);
......
...@@ -2445,7 +2445,7 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration( ...@@ -2445,7 +2445,7 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration(
if (type.getBasicType() == EbtStruct) if (type.getBasicType() == EbtStruct)
{ {
TVariable *emptyVariable = TVariable *emptyVariable =
new TVariable(&symbolTable, NewPoolTString(""), type, SymbolType::Empty); new TVariable(&symbolTable, nullptr, type, SymbolType::Empty);
symbol = new TIntermSymbol(emptyVariable); symbol = new TIntermSymbol(emptyVariable);
} }
else if (IsAtomicCounter(publicType.getBasicType())) else if (IsAtomicCounter(publicType.getBasicType()))
...@@ -3153,7 +3153,8 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction( ...@@ -3153,7 +3153,8 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
const TSourceLoc &location, const TSourceLoc &location,
bool insertParametersToSymbolTable) bool insertParametersToSymbolTable)
{ {
checkIsNotReserved(location, function.name()); ASSERT(function.name());
checkIsNotReserved(location, *function.name());
TIntermFunctionPrototype *prototype = TIntermFunctionPrototype *prototype =
new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function)); new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
...@@ -3200,7 +3201,7 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction( ...@@ -3200,7 +3201,7 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
// The parameter had no name or declaring the symbol failed - either way, add a nameless // The parameter had no name or declaring the symbol failed - either way, add a nameless
// symbol. // symbol.
TVariable *emptyVariable = TVariable *emptyVariable =
new TVariable(&symbolTable, NewPoolTString(""), *param.type, SymbolType::Empty); new TVariable(&symbolTable, nullptr, *param.type, SymbolType::Empty);
symbol = new TIntermSymbol(emptyVariable); symbol = new TIntermSymbol(emptyVariable);
} }
symbol->setLine(location); symbol->setLine(location);
...@@ -3271,12 +3272,13 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, ...@@ -3271,12 +3272,13 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
{ {
ASSERT(function); ASSERT(function);
ASSERT(*function); ASSERT(*function);
ASSERT((*function)->name());
const TSymbol *builtIn = const TSymbol *builtIn =
symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion()); symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
if (builtIn) if (builtIn)
{ {
error(location, "built-in functions cannot be redefined", (*function)->name().c_str()); error(location, "built-in functions cannot be redefined", (*function)->name()->c_str());
} }
else else
{ {
...@@ -3298,7 +3300,7 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, ...@@ -3298,7 +3300,7 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
if ((*function)->isDefined()) if ((*function)->isDefined())
{ {
error(location, "function already has a body", (*function)->name().c_str()); error(location, "function already has a body", (*function)->name()->c_str());
} }
(*function)->setDefined(); (*function)->setDefined();
...@@ -3325,6 +3327,8 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF ...@@ -3325,6 +3327,8 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
TFunction *prevDec = TFunction *prevDec =
static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion())); static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
ASSERT(function->name() != nullptr);
for (size_t i = 0u; i < function->getParamCount(); ++i) for (size_t i = 0u; i < function->getParamCount(); ++i)
{ {
auto &param = function->getParam(i); auto &param = function->getParam(i);
...@@ -3332,17 +3336,17 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF ...@@ -3332,17 +3336,17 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
{ {
// ESSL 3.00.6 section 12.10. // ESSL 3.00.6 section 12.10.
error(location, "Function parameter type cannot be a structure definition", error(location, "Function parameter type cannot be a structure definition",
function->name().c_str()); function->name()->c_str());
} }
} }
if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltInForShaderVersion( if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltInForShaderVersion(
function->name().c_str(), getShaderVersion())) function->name()->c_str(), getShaderVersion()))
{ {
// With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions. // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
// Therefore overloading or redefining builtin functions is an error. // Therefore overloading or redefining builtin functions is an error.
error(location, "Name of a built-in function cannot be redeclared as function", error(location, "Name of a built-in function cannot be redeclared as function",
function->name().c_str()); function->name()->c_str());
} }
else if (prevDec) else if (prevDec)
{ {
...@@ -3366,12 +3370,12 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF ...@@ -3366,12 +3370,12 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
// //
// Check for previously declared variables using the same name. // Check for previously declared variables using the same name.
// //
TSymbol *prevSym = symbolTable.find(function->name(), getShaderVersion()); TSymbol *prevSym = symbolTable.find(*function->name(), getShaderVersion());
if (prevSym) if (prevSym)
{ {
if (!prevSym->isFunction()) if (!prevSym->isFunction())
{ {
error(location, "redefinition of a function", function->name().c_str()); error(location, "redefinition of a function", function->name()->c_str());
} }
} }
else else
...@@ -3385,7 +3389,7 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF ...@@ -3385,7 +3389,7 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
symbolTable.getOuterLevel()->insert(function); symbolTable.getOuterLevel()->insert(function);
// Raise error message if main function takes any parameters or return anything other than void // Raise error message if main function takes any parameters or return anything other than void
if (function->name() == "main") if (*function->name() == "main")
{ {
if (function->getParamCount() > 0) if (function->getParamCount() > 0)
{ {
...@@ -3814,16 +3818,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( ...@@ -3814,16 +3818,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
} }
// The instance variable gets created to refer to the interface block type from the AST // The instance variable gets created to refer to the interface block type from the AST
// regardless of if there's an instance name. It just has an empty name if there's no instance // regardless of if there's an instance name. It's created as an empty symbol if there is no
// name. // instance name.
if (!instanceName)
{
instanceName = NewPoolTString("");
}
TVariable *instanceVariable = TVariable *instanceVariable =
new TVariable(&symbolTable, instanceName, interfaceBlockType, SymbolType::UserDefined); new TVariable(&symbolTable, instanceName, interfaceBlockType,
instanceName ? SymbolType::UserDefined : SymbolType::Empty);
if (instanceName->empty()) if (instanceVariable->symbolType() == SymbolType::Empty)
{ {
// define symbols for the members of the interface block // define symbols for the members of the interface block
for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
...@@ -3902,8 +3903,9 @@ void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const ...@@ -3902,8 +3903,9 @@ void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const
// one to the field's struct nesting. // one to the field's struct nesting.
if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
{ {
ASSERT(field.type()->getStruct()->name() != nullptr);
std::stringstream reasonStream; std::stringstream reasonStream;
reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str() reasonStream << "Reference of struct type " << field.type()->getStruct()->name()->c_str()
<< " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting; << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
std::string reason = reasonStream.str(); std::string reason = reasonStream.str();
error(line, reason.c_str(), field.name().c_str()); error(line, reason.c_str(), field.name().c_str());
...@@ -4770,7 +4772,6 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, ...@@ -4770,7 +4772,6 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
SymbolType structSymbolType = SymbolType::UserDefined; SymbolType structSymbolType = SymbolType::UserDefined;
if (structName == nullptr) if (structName == nullptr)
{ {
structName = NewPoolTString("");
structSymbolType = SymbolType::Empty; structSymbolType = SymbolType::Empty;
} }
TStructure *structure = new TStructure(&symbolTable, structName, fieldList, structSymbolType); TStructure *structure = new TStructure(&symbolTable, structName, fieldList, structSymbolType);
...@@ -5780,10 +5781,10 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall, ...@@ -5780,10 +5781,10 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
// It's possible for the name pointer in the TFunction to be null in case it gets parsed as // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
// a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
// mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead. // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
// So accessing fnCall->getName() below is safe. // So accessing fnCall->name() below is safe.
if (fnCall->name() != "length") if (*fnCall->name() != "length")
{ {
error(loc, "invalid method", fnCall->name().c_str()); error(loc, "invalid method", fnCall->name()->c_str());
} }
else if (!arguments->empty()) else if (!arguments->empty())
{ {
...@@ -5816,18 +5817,18 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall, ...@@ -5816,18 +5817,18 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
// hidden by a variable name or struct typename. // hidden by a variable name or struct typename.
// If a function is found, check for one with a matching argument list. // If a function is found, check for one with a matching argument list.
bool builtIn; bool builtIn;
const TSymbol *symbol = symbolTable.find(fnCall->name(), mShaderVersion, &builtIn); const TSymbol *symbol = symbolTable.find(*fnCall->name(), mShaderVersion, &builtIn);
if (symbol != nullptr && !symbol->isFunction()) if (symbol != nullptr && !symbol->isFunction())
{ {
error(loc, "function name expected", fnCall->name().c_str()); error(loc, "function name expected", fnCall->name()->c_str());
} }
else else
{ {
symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->name(), *arguments), symbol = symbolTable.find(TFunction::GetMangledNameFromCall(*fnCall->name(), *arguments),
mShaderVersion, &builtIn); mShaderVersion, &builtIn);
if (symbol == nullptr) if (symbol == nullptr)
{ {
error(loc, "no matching overloaded function found", fnCall->name().c_str()); error(loc, "no matching overloaded function found", fnCall->name()->c_str());
} }
else else
{ {
......
...@@ -19,12 +19,15 @@ void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) ...@@ -19,12 +19,15 @@ void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
if (!userType) if (!userType)
return; return;
if (userType->symbolType() == SymbolType::BuiltIn) if (userType->symbolType() == SymbolType::BuiltIn ||
userType->symbolType() == SymbolType::Empty)
{ {
// Built-in struct, do not touch it. // Built-in struct or nameless struct, do not touch it.
return; return;
} }
ASSERT(userType->name() != nullptr);
int uniqueId = userType->uniqueId().get(); int uniqueId = userType->uniqueId().get();
ASSERT(mScopeDepth > 0); ASSERT(mScopeDepth > 0);
...@@ -50,14 +53,14 @@ void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) ...@@ -50,14 +53,14 @@ void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
return; return;
// Map {name} to _webgl_struct_{uniqueId}_{name}. // Map {name} to _webgl_struct_{uniqueId}_{name}.
const char kPrefix[] = "_webgl_struct_"; const char kPrefix[] = "_webgl_struct_";
if (userType->name().find(kPrefix) == 0) if (userType->name()->find(kPrefix) == 0)
{ {
// The name has already been regenerated. // The name has already been regenerated.
return; return;
} }
std::string id = Str(uniqueId); std::string id = Str(uniqueId);
TString tmp = kPrefix + TString(id.c_str()); TString tmp = kPrefix + TString(id.c_str());
tmp += "_" + userType->name(); tmp += "_" + *userType->name();
userType->setName(tmp); userType->setName(tmp);
} }
......
...@@ -192,8 +192,8 @@ void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDecl ...@@ -192,8 +192,8 @@ void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDecl
// Already an empty declaration - nothing to do. // Already an empty declaration - nothing to do.
return; return;
} }
TVariable *emptyVariable = new TVariable(mSymbolTable, NewPoolTString(""), TVariable *emptyVariable =
declarator->getType(), SymbolType::Empty); new TVariable(mSymbolTable, nullptr, declarator->getType(), SymbolType::Empty);
queueReplacementWithParent(node, declarator, new TIntermSymbol(emptyVariable), queueReplacementWithParent(node, declarator, new TIntermSymbol(emptyVariable),
OriginalNode::IS_DROPPED); OriginalNode::IS_DROPPED);
return; return;
......
...@@ -40,19 +40,25 @@ TSymbol::TSymbol(TSymbolTable *symbolTable, ...@@ -40,19 +40,25 @@ TSymbol::TSymbol(TSymbolTable *symbolTable,
{ {
ASSERT(mSymbolType == SymbolType::BuiltIn || mExtension == TExtension::UNDEFINED); ASSERT(mSymbolType == SymbolType::BuiltIn || mExtension == TExtension::UNDEFINED);
ASSERT(mName != nullptr || mSymbolType == SymbolType::AngleInternal || ASSERT(mName != nullptr || mSymbolType == SymbolType::AngleInternal ||
mSymbolType == SymbolType::NotResolved); mSymbolType == SymbolType::NotResolved || mSymbolType == SymbolType::Empty);
} }
const TString &TSymbol::name() const const TString *TSymbol::name() const
{ {
if (mName != nullptr) if (mName != nullptr || mSymbolType == SymbolType::Empty)
{ {
return *mName; return mName;
} }
ASSERT(mSymbolType == SymbolType::AngleInternal); ASSERT(mSymbolType == SymbolType::AngleInternal);
TInfoSinkBase symbolNameOut; TInfoSinkBase symbolNameOut;
symbolNameOut << "s" << mUniqueId.get(); symbolNameOut << "s" << mUniqueId.get();
return *NewPoolTString(symbolNameOut.c_str()); return NewPoolTString(symbolNameOut.c_str());
}
const TString &TSymbol::getMangledName() const
{
ASSERT(mSymbolType != SymbolType::Empty);
return *name();
} }
TVariable::TVariable(TSymbolTable *symbolTable, TVariable::TVariable(TSymbolTable *symbolTable,
...@@ -109,6 +115,7 @@ TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable, ...@@ -109,6 +115,7 @@ TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
mBlockStorage(layoutQualifier.blockStorage), mBlockStorage(layoutQualifier.blockStorage),
mBinding(layoutQualifier.binding) mBinding(layoutQualifier.binding)
{ {
ASSERT(name != nullptr);
} }
// //
...@@ -138,7 +145,7 @@ void TFunction::swapParameters(const TFunction &parametersSource) ...@@ -138,7 +145,7 @@ void TFunction::swapParameters(const TFunction &parametersSource)
const TString *TFunction::buildMangledName() const const TString *TFunction::buildMangledName() const
{ {
std::string newName = name().c_str(); std::string newName = name()->c_str();
newName += kFunctionMangledNameSeparator; newName += kFunctionMangledNameSeparator;
for (const auto &p : parameters) for (const auto &p : parameters)
...@@ -181,7 +188,8 @@ bool TSymbolTableLevel::insert(TSymbol *symbol) ...@@ -181,7 +188,8 @@ bool TSymbolTableLevel::insert(TSymbol *symbol)
bool TSymbolTableLevel::insertUnmangled(TFunction *function) bool TSymbolTableLevel::insertUnmangled(TFunction *function)
{ {
// returning true means symbol was added to the table // returning true means symbol was added to the table
tInsertResult result = level.insert(tLevelPair(function->name(), function)); ASSERT(function->name() != nullptr);
tInsertResult result = level.insert(tLevelPair(*function->name(), function));
return result.second; return result.second;
} }
......
...@@ -67,8 +67,8 @@ class TSymbol : angle::NonCopyable ...@@ -67,8 +67,8 @@ class TSymbol : angle::NonCopyable
// don't delete name, it's from the pool // don't delete name, it's from the pool
} }
const TString &name() const; const TString *name() const;
virtual const TString &getMangledName() const { return name(); } virtual const TString &getMangledName() const;
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
virtual bool isVariable() const { return false; } virtual bool isVariable() const { return false; }
virtual bool isStruct() const { return false; } virtual bool isStruct() const { return false; }
......
...@@ -475,12 +475,16 @@ const char *TType::buildMangledName() const ...@@ -475,12 +475,16 @@ const char *TType::buildMangledName() const
{ {
case EbtStruct: case EbtStruct:
mangledName += "struct-"; mangledName += "struct-";
mangledName += mStructure->name(); if (mStructure->name() != nullptr)
{
mangledName += *mStructure->name();
}
mangledName += mStructure->mangledFieldList(); mangledName += mStructure->mangledFieldList();
break; break;
case EbtInterfaceBlock: case EbtInterfaceBlock:
mangledName += "iblock-"; mangledName += "iblock-";
mangledName += mInterfaceBlock->name(); ASSERT(mInterfaceBlock->name() != nullptr);
mangledName += *mInterfaceBlock->name();
mangledName += mInterfaceBlock->mangledFieldList(); mangledName += mInterfaceBlock->mangledFieldList();
break; break;
default: default:
......
...@@ -61,7 +61,8 @@ static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockSt ...@@ -61,7 +61,8 @@ static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockSt
static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
{ {
return DecoratePrivate(interfaceBlock.name()) + "_type"; ASSERT(interfaceBlock.name() != nullptr);
return DecoratePrivate(*interfaceBlock.name()) + "_type";
} }
void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out, void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out,
...@@ -479,7 +480,8 @@ TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInte ...@@ -479,7 +480,8 @@ TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInte
} }
unsigned int activeRegister = mUniformBlockRegister; unsigned int activeRegister = mUniformBlockRegister;
mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister; ASSERT(interfaceBlock.name() != nullptr);
mUniformBlockRegisterMap[interfaceBlock.name()->c_str()] = activeRegister;
if (instanceName != "" && nodeType.isArray()) if (instanceName != "" && nodeType.isArray())
{ {
...@@ -510,7 +512,8 @@ TString UniformHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock, ...@@ -510,7 +512,8 @@ TString UniformHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock,
{ {
const TString &arrayIndexString = const TString &arrayIndexString =
(arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : ""); (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
const TString &blockName = interfaceBlock.name() + arrayIndexString; ASSERT(interfaceBlock.name() != nullptr);
const TString &blockName = *interfaceBlock.name() + arrayIndexString;
TString hlsl; TString hlsl;
hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) +
......
...@@ -855,10 +855,10 @@ TString StructNameString(const TStructure &structure) ...@@ -855,10 +855,10 @@ TString StructNameString(const TStructure &structure)
// translation so that we can link between shader stages. // translation so that we can link between shader stages.
if (structure.atGlobalScope()) if (structure.atGlobalScope())
{ {
return Decorate(structure.name()); return Decorate(*structure.name());
} }
return "ss" + str(structure.uniqueId().get()) + "_" + structure.name(); return "ss" + str(structure.uniqueId().get()) + "_" + *structure.name();
} }
TString QualifiedStructNameString(const TStructure &structure, TString QualifiedStructNameString(const TStructure &structure,
......
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
'<(angle_path)/src/tests/compiler_tests/QualificationOrderESSL31_test.cpp', '<(angle_path)/src/tests/compiler_tests/QualificationOrderESSL31_test.cpp',
'<(angle_path)/src/tests/compiler_tests/QualificationOrder_test.cpp', '<(angle_path)/src/tests/compiler_tests/QualificationOrder_test.cpp',
'<(angle_path)/src/tests/compiler_tests/RecordConstantPrecision_test.cpp', '<(angle_path)/src/tests/compiler_tests/RecordConstantPrecision_test.cpp',
'<(angle_path)/src/tests/compiler_tests/RegenerateStructNames_test.cpp',
'<(angle_path)/src/tests/compiler_tests/RemovePow_test.cpp', '<(angle_path)/src/tests/compiler_tests/RemovePow_test.cpp',
'<(angle_path)/src/tests/compiler_tests/RemoveUnreferencedVariables_test.cpp', '<(angle_path)/src/tests/compiler_tests/RemoveUnreferencedVariables_test.cpp',
'<(angle_path)/src/tests/compiler_tests/RewriteDoWhile_test.cpp', '<(angle_path)/src/tests/compiler_tests/RewriteDoWhile_test.cpp',
......
...@@ -809,17 +809,61 @@ TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock) ...@@ -809,17 +809,61 @@ TEST_F(CollectHashedVertexVariablesTest, InstancedInterfaceBlock)
EXPECT_TRUE(field.fields.empty()); EXPECT_TRUE(field.fields.empty());
} }
// Test a struct uniform where the struct does have a name.
TEST_F(CollectHashedVertexVariablesTest, StructUniform) TEST_F(CollectHashedVertexVariablesTest, StructUniform)
{ {
const std::string &shaderString = const std::string &shaderString =
"#version 300 es\n" R"(#version 300 es
"struct sType {\n" struct sType
" float field;\n" {
"};" float field;
"uniform sType u;" };
"void main() {\n" uniform sType u;
" gl_Position = vec4(u.field, 0.0, 0.0, 1.0);\n"
"}\n"; void main()
{
gl_Position = vec4(u.field, 0.0, 0.0, 1.0);
})";
compile(shaderString);
const auto &uniforms = mTranslator->getUniforms();
ASSERT_EQ(1u, uniforms.size());
const Uniform &uniform = uniforms[0];
EXPECT_FALSE(uniform.isArray());
EXPECT_EQ("u", uniform.name);
EXPECT_EQ("webgl_1", uniform.mappedName);
EXPECT_EQ("sType", uniform.structName);
EXPECT_TRUE(uniform.staticUse);
ASSERT_EQ(1u, uniform.fields.size());
const ShaderVariable &field = uniform.fields[0];
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision);
// EXPECT_TRUE(field.staticUse); // we don't yet support struct static use
EXPECT_GLENUM_EQ(GL_FLOAT, field.type);
EXPECT_EQ("field", field.name);
EXPECT_EQ("webgl_5", field.mappedName);
EXPECT_TRUE(field.fields.empty());
}
// Test a struct uniform where the struct doesn't have a name.
TEST_F(CollectHashedVertexVariablesTest, NamelessStructUniform)
{
const std::string &shaderString =
R"(#version 300 es
uniform struct
{
float field;
} u;
void main()
{
gl_Position = vec4(u.field, 0.0, 0.0, 1.0);
})";
compile(shaderString); compile(shaderString);
...@@ -831,6 +875,7 @@ TEST_F(CollectHashedVertexVariablesTest, StructUniform) ...@@ -831,6 +875,7 @@ TEST_F(CollectHashedVertexVariablesTest, StructUniform)
EXPECT_FALSE(uniform.isArray()); EXPECT_FALSE(uniform.isArray());
EXPECT_EQ("u", uniform.name); EXPECT_EQ("u", uniform.name);
EXPECT_EQ("webgl_1", uniform.mappedName); EXPECT_EQ("webgl_1", uniform.mappedName);
EXPECT_EQ("", uniform.structName);
EXPECT_TRUE(uniform.staticUse); EXPECT_TRUE(uniform.staticUse);
ASSERT_EQ(1u, uniform.fields.size()); ASSERT_EQ(1u, uniform.fields.size());
......
...@@ -167,7 +167,8 @@ class FindStructByName final : public TIntermTraverser ...@@ -167,7 +167,8 @@ class FindStructByName final : public TIntermTraverser
TStructure *structure = symbol->getTypePointer()->getStruct(); TStructure *structure = symbol->getTypePointer()->getStruct();
if (structure != nullptr && structure->name() == mStructName) if (structure != nullptr && structure->name() != nullptr &&
*structure->name() == mStructName)
{ {
mStructure = structure; mStructure = structure;
} }
......
//
// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// RegenerateStructNames_test.cpp:
// Tests for regenerating struct names.
//
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "tests/test_utils/compiler_test.h"
using namespace sh;
class RegenerateStructNamesTest : public MatchOutputCodeTest
{
public:
RegenerateStructNamesTest()
: MatchOutputCodeTest(GL_FRAGMENT_SHADER, SH_REGENERATE_STRUCT_NAMES, SH_ESSL_OUTPUT)
{
}
};
// Test that a struct defined in a function scope is renamed. The global struct that's used as a
// type of a uniform cannot be renamed.
TEST_F(RegenerateStructNamesTest, GlobalStructAndLocalStructWithTheSameName)
{
const std::string &shaderString =
R"(precision mediump float;
struct myStruct
{
float foo;
};
uniform myStruct us;
void main()
{
struct myStruct
{
vec2 bar;
};
myStruct scoped;
scoped.bar = vec2(1.0, 2.0) * us.foo;
gl_FragColor = vec4(scoped.bar, 0.0, 1.0);
})";
compile(shaderString);
EXPECT_TRUE(foundInCode("struct _umyStruct"));
EXPECT_TRUE(foundInCode("struct _u_webgl_struct_"));
}
// Test that a nameless struct is handled gracefully.
TEST_F(RegenerateStructNamesTest, NamelessStruct)
{
const std::string &shaderString =
R"(precision mediump float;
uniform float u;
void main()
{
struct
{
vec2 bar;
} scoped;
scoped.bar = vec2(1.0, 2.0) * u;
gl_FragColor = vec4(scoped.bar, 0.0, 1.0);
})";
compile(shaderString);
EXPECT_TRUE(foundInCode("struct"));
}
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