Commit 0f68463f by Olli Etuaho Committed by Commit Bot

Clean up inserting variables to symbol table

This makes the TSymbolTable interface cleaner and prepares for making unique id counting thread-safe. BUG=angleproject:624 TEST=angle_unittests Change-Id: Ief99c9fc777603de28ba1517e351bc8a00633590 Reviewed-on: https://chromium-review.googlesource.com/570418 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent daaff1cc
......@@ -690,15 +690,10 @@ void InsertBuiltInFunctions(sh::GLenum type,
fields->push_back(diff);
TStructure *depthRangeStruct =
new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
TVariable *depthRangeParameters =
new TVariable(&depthRangeStruct->name(), TType(depthRangeStruct), true);
symbolTable.insert(COMMON_BUILTINS, depthRangeParameters);
TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
depthRange->setQualifier(EvqUniform);
// Do lazy initialization for depth range, so we allocate to the current scope.
depthRangeParameters->getType().realize();
depthRange->getType().realize();
symbolTable.insert(COMMON_BUILTINS, depthRange);
symbolTable.insertStructType(COMMON_BUILTINS, depthRangeStruct);
TType depthRangeType(depthRangeStruct);
depthRangeType.setQualifier(EvqUniform);
symbolTable.insertVariable(COMMON_BUILTINS, "gl_DepthRange", depthRangeType);
//
// Implementation dependent built-in constants.
......@@ -796,34 +791,28 @@ void IdentifyBuiltIns(sh::GLenum type,
if (resources.OVR_multiview && type != GL_COMPUTE_SHADER)
{
symbolTable.insert(ESSL3_BUILTINS, "GL_OVR_multiview",
new TVariable(NewPoolTString("gl_ViewID_OVR"),
TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1)));
symbolTable.insertVariableExt(ESSL3_BUILTINS, "GL_OVR_multiview", "gl_ViewID_OVR",
TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1));
// ESSL 1.00 doesn't have unsigned integers, so gl_ViewID_OVR is a signed integer in ESSL
// 1.00. This is specified in the WEBGL_multiview spec.
symbolTable.insert(ESSL1_BUILTINS, "GL_OVR_multiview",
new TVariable(NewPoolTString("gl_ViewID_OVR"),
TType(EbtInt, EbpHigh, EvqViewIDOVR, 1)));
symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_OVR_multiview", "gl_ViewID_OVR",
TType(EbtInt, EbpHigh, EvqViewIDOVR, 1));
}
switch (type)
{
case GL_FRAGMENT_SHADER:
{
symbolTable.insert(COMMON_BUILTINS,
new TVariable(NewPoolTString("gl_FragCoord"),
TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
symbolTable.insert(COMMON_BUILTINS,
new TVariable(NewPoolTString("gl_FrontFacing"),
TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
symbolTable.insert(COMMON_BUILTINS,
new TVariable(NewPoolTString("gl_PointCoord"),
TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
symbolTable.insert(ESSL1_BUILTINS,
new TVariable(NewPoolTString("gl_FragColor"),
TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
symbolTable.insertVariable(COMMON_BUILTINS, "gl_FragCoord",
TType(EbtFloat, EbpMedium, EvqFragCoord, 4));
symbolTable.insertVariable(COMMON_BUILTINS, "gl_FrontFacing",
TType(EbtBool, EbpUndefined, EvqFrontFacing, 1));
symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointCoord",
TType(EbtFloat, EbpMedium, EvqPointCoord, 2));
symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragColor",
TType(EbtFloat, EbpMedium, EvqFragColor, 4));
TType fragData(EbtFloat, EbpMedium, EvqFragData, 4);
if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC)
{
......@@ -833,35 +822,29 @@ void IdentifyBuiltIns(sh::GLenum type,
{
fragData.setArraySize(1u);
}
symbolTable.insert(ESSL1_BUILTINS,
new TVariable(NewPoolTString("gl_FragData"), fragData));
symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragData", fragData);
if (resources.EXT_blend_func_extended)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"),
TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)));
symbolTable.insertVariableExt(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended", "gl_SecondaryFragColorEXT",
TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4));
TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true);
secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData));
symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
"gl_SecondaryFragDataEXT", secondaryFragData);
}
if (resources.EXT_frag_depth)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_frag_depth",
new TVariable(
NewPoolTString("gl_FragDepthEXT"),
TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
EvqFragDepthEXT, 1)));
symbolTable.insertVariableExt(
ESSL1_BUILTINS, "GL_EXT_frag_depth", "gl_FragDepthEXT",
TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
EvqFragDepthEXT, 1));
}
symbolTable.insert(ESSL3_BUILTINS,
new TVariable(NewPoolTString("gl_FragDepth"),
TType(EbtFloat, EbpHigh, EvqFragDepth, 1)));
symbolTable.insertVariable(ESSL3_BUILTINS, "gl_FragDepth",
TType(EbtFloat, EbpHigh, EvqFragDepth, 1));
if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
{
......@@ -870,68 +853,52 @@ void IdentifyBuiltIns(sh::GLenum type,
if (resources.EXT_shader_framebuffer_fetch)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
"gl_LastFragData", lastFragData);
}
else if (resources.NV_shader_framebuffer_fetch)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragColor"),
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
symbolTable.insert(
ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
"gl_LastFragColor",
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
"gl_LastFragData", lastFragData);
}
}
else if (resources.ARM_shader_framebuffer_fetch)
{
symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragColorARM"),
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
"gl_LastFragColorARM",
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
}
}
break;
case GL_VERTEX_SHADER:
symbolTable.insert(COMMON_BUILTINS,
new TVariable(NewPoolTString("gl_Position"),
TType(EbtFloat, EbpHigh, EvqPosition, 4)));
symbolTable.insert(COMMON_BUILTINS,
new TVariable(NewPoolTString("gl_PointSize"),
TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
symbolTable.insert(ESSL3_BUILTINS,
new TVariable(NewPoolTString("gl_InstanceID"),
TType(EbtInt, EbpHigh, EvqInstanceID, 1)));
symbolTable.insert(ESSL3_BUILTINS,
new TVariable(NewPoolTString("gl_VertexID"),
TType(EbtInt, EbpHigh, EvqVertexID, 1)));
symbolTable.insertVariable(COMMON_BUILTINS, "gl_Position",
TType(EbtFloat, EbpHigh, EvqPosition, 4));
symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointSize",
TType(EbtFloat, EbpMedium, EvqPointSize, 1));
symbolTable.insertVariable(ESSL3_BUILTINS, "gl_InstanceID",
TType(EbtInt, EbpHigh, EvqInstanceID, 1));
symbolTable.insertVariable(ESSL3_BUILTINS, "gl_VertexID",
TType(EbtInt, EbpHigh, EvqVertexID, 1));
break;
case GL_COMPUTE_SHADER:
{
symbolTable.insert(ESSL3_1_BUILTINS,
new TVariable(NewPoolTString("gl_NumWorkGroups"),
TType(EbtUInt, EbpUndefined, EvqNumWorkGroups, 3)));
symbolTable.insert(ESSL3_1_BUILTINS,
new TVariable(NewPoolTString("gl_WorkGroupSize"),
TType(EbtUInt, EbpUndefined, EvqWorkGroupSize, 3)));
symbolTable.insert(ESSL3_1_BUILTINS,
new TVariable(NewPoolTString("gl_WorkGroupID"),
TType(EbtUInt, EbpUndefined, EvqWorkGroupID, 3)));
symbolTable.insert(
ESSL3_1_BUILTINS,
new TVariable(NewPoolTString("gl_LocalInvocationID"),
TType(EbtUInt, EbpUndefined, EvqLocalInvocationID, 3)));
symbolTable.insert(
ESSL3_1_BUILTINS,
new TVariable(NewPoolTString("gl_GlobalInvocationID"),
TType(EbtUInt, EbpUndefined, EvqGlobalInvocationID, 3)));
symbolTable.insert(
ESSL3_1_BUILTINS,
new TVariable(NewPoolTString("gl_LocalInvocationIndex"),
TType(EbtUInt, EbpUndefined, EvqLocalInvocationIndex, 1)));
symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_NumWorkGroups",
TType(EbtUInt, EbpUndefined, EvqNumWorkGroups, 3));
symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupSize",
TType(EbtUInt, EbpUndefined, EvqWorkGroupSize, 3));
symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupID",
TType(EbtUInt, EbpUndefined, EvqWorkGroupID, 3));
symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationID",
TType(EbtUInt, EbpUndefined, EvqLocalInvocationID, 3));
symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_GlobalInvocationID",
TType(EbtUInt, EbpUndefined, EvqGlobalInvocationID, 3));
symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationIndex",
TType(EbtUInt, EbpUndefined, EvqLocalInvocationIndex, 1));
}
break;
......
......@@ -32,24 +32,32 @@ namespace
const int kWebGLMaxStructNesting = 4;
bool ContainsSampler(const TStructure *structType);
bool ContainsSampler(const TType &type)
{
if (IsSampler(type.getBasicType()))
{
return true;
}
if (type.getBasicType() == EbtStruct)
{
const TFieldList &fields = type.getStruct()->fields();
for (unsigned int i = 0; i < fields.size(); ++i)
{
if (ContainsSampler(*fields[i]->type()))
return true;
}
return ContainsSampler(type.getStruct());
}
return false;
}
bool ContainsSampler(const TStructure *structType)
{
for (const auto &field : structType->fields())
{
if (ContainsSampler(*field->type()))
return true;
}
return false;
}
// Get a token from an image argument to use as an error message token.
const char *GetImageArgumentToken(TIntermTyped *imageNode)
{
......@@ -802,7 +810,7 @@ bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
{
if (pType.type == EbtStruct)
{
if (ContainsSampler(*pType.userDef))
if (ContainsSampler(pType.userDef))
{
std::stringstream reasonStream;
reasonStream << reason << " (structure contains a sampler)";
......@@ -1036,11 +1044,10 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
if (needsReservedCheck && !checkIsNotReserved(line, identifier))
return false;
(*variable) = new TVariable(&identifier, type);
if (!symbolTable.declare(*variable))
(*variable) = symbolTable.declareVariable(&identifier, type);
if (!(*variable))
{
error(line, "redefinition", identifier.c_str());
*variable = nullptr;
return false;
}
......@@ -1626,75 +1633,65 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
const TString *name,
const TSymbol *symbol)
{
const TVariable *variable = nullptr;
if (!symbol)
{
error(location, "undeclared identifier", name->c_str());
return nullptr;
}
else if (!symbol->isVariable())
if (!symbol->isVariable())
{
error(location, "variable expected", name->c_str());
return nullptr;
}
else
{
variable = static_cast<const TVariable *>(symbol);
if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
!variable->getExtension().empty())
{
checkCanUseExtension(location, variable->getExtension());
}
const TVariable *variable = static_cast<const TVariable *>(symbol);
// Reject shaders using both gl_FragData and gl_FragColor
TQualifier qualifier = variable->getType().getQualifier();
if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
{
mUsesFragData = true;
}
else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
{
mUsesFragColor = true;
}
if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
{
mUsesSecondaryOutputs = true;
}
if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
!variable->getExtension().empty())
{
checkCanUseExtension(location, variable->getExtension());
}
// This validation is not quite correct - it's only an error to write to
// both FragData and FragColor. For simplicity, and because users shouldn't
// be rewarded for reading from undefined varaibles, return an error
// if they are both referenced, rather than assigned.
if (mUsesFragData && mUsesFragColor)
{
const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
if (mUsesSecondaryOutputs)
{
errorMessage =
"cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
" and (gl_FragColor, gl_SecondaryFragColorEXT)";
}
error(location, errorMessage, name->c_str());
}
// Reject shaders using both gl_FragData and gl_FragColor
TQualifier qualifier = variable->getType().getQualifier();
if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
{
mUsesFragData = true;
}
else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
{
mUsesFragColor = true;
}
if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
{
mUsesSecondaryOutputs = true;
}
// GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
qualifier == EvqWorkGroupSize)
// This validation is not quite correct - it's only an error to write to
// both FragData and FragColor. For simplicity, and because users shouldn't
// be rewarded for reading from undefined varaibles, return an error
// if they are both referenced, rather than assigned.
if (mUsesFragData && mUsesFragColor)
{
const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
if (mUsesSecondaryOutputs)
{
error(location,
"It is an error to use gl_WorkGroupSize before declaring the local group size",
"gl_WorkGroupSize");
errorMessage =
"cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
" and (gl_FragColor, gl_SecondaryFragColorEXT)";
}
error(location, errorMessage, name->c_str());
}
if (!variable)
// GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
qualifier == EvqWorkGroupSize)
{
TType type(EbtFloat, EbpUndefined);
TVariable *fakeVariable = new TVariable(name, type);
symbolTable.declare(fakeVariable);
variable = fakeVariable;
error(location,
"It is an error to use gl_WorkGroupSize before declaring the local group size",
"gl_WorkGroupSize");
}
return variable;
}
......@@ -1704,6 +1701,13 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
{
const TVariable *variable = getNamedVariable(location, name, symbol);
if (!variable)
{
TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
node->setLine(location);
return node;
}
if (variable->getType().getQualifier() == EvqViewIDOVR && IsWebGLBasedSpec(mShaderSpec) &&
mShaderType == GL_FRAGMENT_SHADER && !isExtensionEnabled("GL_OVR_multiview2"))
{
......@@ -2447,7 +2451,10 @@ TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
}
const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
ASSERT(variable);
if (!variable)
{
return nullptr;
}
const TType &type = variable->getType();
checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
......@@ -2827,12 +2834,11 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
// be used for unused args).
if (param.name != nullptr)
{
TVariable *variable = new TVariable(param.name, *param.type);
// Insert the parameter in the symbol table.
if (insertParametersToSymbolTable)
{
if (symbolTable.declare(variable))
TVariable *variable = symbolTable.declareVariable(param.name, *param.type);
if (variable)
{
symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(),
variable->getType());
......@@ -3259,8 +3265,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
if (!symbolTable.declare(blockNameSymbol))
if (!symbolTable.declareInterfaceBlockName(&blockName))
{
error(nameLine, "redefinition of an interface block name", blockName.c_str());
}
......@@ -3370,10 +3375,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
// set parent pointer of the field variable
fieldType->setInterfaceBlock(interfaceBlock);
TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
fieldVariable->setQualifier(typeQualifier.qualifier);
TVariable *fieldVariable = symbolTable.declareVariable(&field->name(), *fieldType);
if (!symbolTable.declare(fieldVariable))
if (fieldVariable)
{
fieldVariable->setQualifier(typeQualifier.qualifier);
}
else
{
error(field->line(), "redefinition of an interface block member name",
field->name().c_str());
......@@ -3385,17 +3393,18 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
checkIsNotReserved(instanceLine, *instanceName);
// add a symbol for this interface block
TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
instanceTypeDef->setQualifier(typeQualifier.qualifier);
if (!symbolTable.declare(instanceTypeDef))
TVariable *instanceTypeDef = symbolTable.declareVariable(instanceName, interfaceBlockType);
if (instanceTypeDef)
{
instanceTypeDef->setQualifier(typeQualifier.qualifier);
symbolId = instanceTypeDef->getUniqueId();
}
else
{
error(instanceLine, "redefinition of an interface block instance name",
instanceName->c_str());
}
symbolId = instanceTypeDef->getUniqueId();
symbolName = instanceTypeDef->getName();
symbolName = *instanceName;
}
TIntermSymbol *blockSymbol = new TIntermSymbol(symbolId, symbolName, interfaceBlockType);
......@@ -4120,7 +4129,7 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif
type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
if (typeSpecifier.getUserDef())
{
type->setStruct(typeSpecifier.getUserDef()->getStruct());
type->setStruct(typeSpecifier.getUserDef());
}
checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
......@@ -4135,7 +4144,6 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
TFieldList *fieldList)
{
TStructure *structure = new TStructure(structName, fieldList);
TType *structureType = new TType(structure);
// Store a bool in the struct if we're at global scope, to allow us to
// skip the local struct scoping workaround in HLSL.
......@@ -4144,8 +4152,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
if (!structName->empty())
{
checkIsNotReserved(nameLine, *structName);
TVariable *userTypeDef = new TVariable(structName, *structureType, true);
if (!symbolTable.declare(userTypeDef))
if (!symbolTable.declareStructType(structure))
{
error(nameLine, "redefinition of a struct", structName->c_str());
}
......@@ -4184,7 +4191,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
}
TTypeSpecifierNonArray typeSpecifierNonArray;
typeSpecifierNonArray.initializeStruct(structureType, true, structLine);
typeSpecifierNonArray.initializeStruct(structure, true, structLine);
exitStructDeclaration();
return typeSpecifierNonArray;
......
......@@ -3,10 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
// Symbol table for parsing. Most functionaliy and main ideas
// are documented in the header file.
// Symbol table for parsing. The design principles and most of the functionality are documented in
// the header file.
//
#if defined(_MSC_VER)
......@@ -271,6 +269,74 @@ const TType *VectorType(const TType *type, int size)
}
}
TVariable *TSymbolTable::declareVariable(const TString *name, const TType &type)
{
return insertVariable(currentLevel(), name, type);
}
TVariable *TSymbolTable::declareStructType(TStructure *str)
{
return insertStructType(currentLevel(), str);
}
TInterfaceBlockName *TSymbolTable::declareInterfaceBlockName(const TString *name)
{
TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(name);
if (insert(currentLevel(), blockNameSymbol))
{
return blockNameSymbol;
}
return nullptr;
}
TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type)
{
return insertVariable(level, NewPoolTString(name), type);
}
TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const TString *name, const TType &type)
{
TVariable *var = new TVariable(name, type);
if (insert(level, var))
{
// Do lazy initialization for struct types, so we allocate to the current scope.
if (var->getType().getBasicType() == EbtStruct)
{
var->getType().realize();
}
return var;
}
return nullptr;
}
TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level,
const char *ext,
const char *name,
const TType &type)
{
TVariable *var = new TVariable(NewPoolTString(name), type);
if (insert(level, ext, var))
{
if (var->getType().getBasicType() == EbtStruct)
{
var->getType().realize();
}
return var;
}
return nullptr;
}
TVariable *TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
{
TVariable *var = new TVariable(&str->name(), TType(str), true);
if (insert(level, var))
{
var->getType().realize();
return var;
}
return nullptr;
}
void TSymbolTable::insertBuiltIn(ESymbolLevel level,
TOperator op,
const char *ext,
......
......@@ -83,21 +83,12 @@ class TSymbol : angle::NonCopyable
TString extension;
};
// Variable class, meaning a symbol that's not a function.
// Variable, meaning a symbol that's not a function.
//
// There could be a separate class heirarchy for Constant variables;
// Only one of int, bool, or float, (or none) is correct for
// any particular use, but it's easy to do this way, and doesn't
// seem worth having separate classes, and "getConst" can't simply return
// different values for different types polymorphically, so this is
// just simple and pragmatic.
// May store the value of a constant variable of any type (float, int, bool or struct).
class TVariable : public TSymbol
{
public:
TVariable(const TString *name, const TType &t, bool uT = false)
: TSymbol(name), type(t), userType(uT), unionArray(0)
{
}
~TVariable() override {}
bool isVariable() const override { return true; }
TType &getType() { return type; }
......@@ -110,8 +101,18 @@ class TVariable : public TSymbol
void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
private:
friend class TSymbolTable;
TVariable(const TString *name, const TType &t, bool isUserTypeDefinition = false)
: TSymbol(name), type(t), userType(isUserTypeDefinition), unionArray(0)
{
}
TType type;
// Set to true if this represents a struct type, as opposed to a variable.
bool userType;
// we are assuming that Pool Allocator will free the memory
// allocated to unionArray when this object is destroyed.
const TConstantUnion *unionArray;
......@@ -224,9 +225,11 @@ class TFunction : public TSymbol
class TInterfaceBlockName : public TSymbol
{
public:
TInterfaceBlockName(const TString *name) : TSymbol(name) {}
virtual ~TInterfaceBlockName() {}
private:
friend class TSymbolTable;
TInterfaceBlockName(const TString *name) : TSymbol(name) {}
};
class TSymbolTableLevel
......@@ -319,15 +322,22 @@ class TSymbolTable : angle::NonCopyable
precisionStack.pop_back();
}
bool declare(TSymbol *symbol) { return insert(currentLevel(), symbol); }
bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); }
bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
{
symbol->relateToExtension(ext);
return table[level]->insert(symbol);
}
// The declare* entry points are used when parsing and declare symbols at the current scope.
// They return the created symbol in case the declaration was successful, and nullptr if the
// declaration failed due to redefinition.
TVariable *declareVariable(const TString *name, const TType &type);
TVariable *declareStructType(TStructure *str);
TInterfaceBlockName *declareInterfaceBlockName(const TString *name);
// The insert* entry points are used when initializing the symbol table with built-ins.
// They return the created symbol in case the declaration was successful, and nullptr if the
// declaration failed due to redefinition.
TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type);
TVariable *insertVariableExt(ESymbolLevel level,
const char *ext,
const char *name,
const TType &type);
TVariable *insertStructType(ESymbolLevel level, TStructure *str);
bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
{
......@@ -444,8 +454,6 @@ class TSymbolTable : angle::NonCopyable
return table[currentLevel() - 1];
}
void dump(TInfoSink &infoSink) const;
void setDefaultPrecision(TBasicType type, TPrecision prec)
{
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
......@@ -488,6 +496,16 @@ class TSymbolTable : angle::NonCopyable
private:
ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
TVariable *insertVariable(ESymbolLevel level, const TString *name, const TType &type);
bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); }
bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
{
symbol->relateToExtension(ext);
return table[level]->insert(symbol);
}
// Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
// above.
void insertUnmangledBuiltInName(const char *name, ESymbolLevel level);
......
......@@ -130,7 +130,7 @@ TType::TType(const TPublicType &p)
ASSERT(primarySize <= 4);
ASSERT(secondarySize <= 4);
if (p.getUserDef())
structure = p.getUserDef()->getStruct();
structure = p.getUserDef();
}
bool TStructure::equals(const TStructure &other) const
......
......@@ -517,7 +517,7 @@ struct TTypeSpecifierNonArray
TBasicType type;
unsigned char primarySize; // size of vector or cols of matrix
unsigned char secondarySize; // rows of matrix
TType *userDef;
TStructure *userDef;
TSourceLoc line;
// true if the type was defined by a struct specifier rather than a reference to a type name.
......@@ -534,7 +534,7 @@ struct TTypeSpecifierNonArray
isStructSpecifier = false;
}
void initializeStruct(TType *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine)
void initializeStruct(TStructure *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine)
{
type = EbtStruct;
primarySize = 1;
......@@ -610,7 +610,7 @@ struct TPublicType
unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
const TType *getUserDef() const { return typeSpecifierNonArray.userDef; }
TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; }
const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
......@@ -622,7 +622,7 @@ struct TPublicType
return false;
}
return typeSpecifierNonArray.userDef->isStructureContainingArrays();
return typeSpecifierNonArray.userDef->containsArrays();
}
bool isStructureContainingType(TBasicType t) const
......@@ -632,7 +632,7 @@ struct TPublicType
return false;
}
return typeSpecifierNonArray.userDef->isStructureContainingType(t);
return typeSpecifierNonArray.userDef->containsType(t);
}
bool isUnsizedArray() const { return array && arraySize == 0; }
......
......@@ -1175,7 +1175,7 @@ type_specifier_nonarray
| TYPE_NAME {
// This is for user defined type names. The lexical phase looked up the type.
TType& structure = static_cast<TVariable*>($1.symbol)->getType();
$$.initializeStruct(&structure, false, @1);
$$.initializeStruct(structure.getStruct(), false, @1);
}
;
......
......@@ -4395,7 +4395,7 @@ yyreduce:
{
// This is for user defined type names. The lexical phase looked up the type.
TType& structure = static_cast<TVariable*>((yyvsp[0].lex).symbol)->getType();
(yyval.interm.typeSpecifierNonArray).initializeStruct(&structure, false, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initializeStruct(structure.getStruct(), false, (yylsp[0]));
}
break;
......
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