Commit 035419fa by Olli Etuaho Committed by Commit Bot

Clean up storing struct types in the symbol table

Instead of storing struct symbols as TVariable objects, store them as TStructure objects. This way struct type symbols don't need to store bogus data that's associated with arbitrary types, and on the other hand the name and unique id of struct types are only stored in a single place. This change is a refactoring with no effect on generated output. BUG=angleproject:2267 TEST=angle_unittests Change-Id: I173793e0cc77a890cdac6868d72d9f275ac9461a Reviewed-on: https://chromium-review.googlesource.com/793814 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 5d69db12
......@@ -11,6 +11,7 @@
#include "compiler/translator/IntermNodePatternMatcher.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
......
......@@ -30,10 +30,46 @@ static const char kFunctionMangledNameSeparator = '(';
} // anonymous namespace
TSymbol::TSymbol(TSymbolTable *symbolTable, const TString *name)
: mUniqueId(symbolTable->nextUniqueId()), mName(name), mExtension(TExtension::UNDEFINED)
: mName(name), mUniqueId(symbolTable->nextUniqueId()), mExtension(TExtension::UNDEFINED)
{
}
TVariable::TVariable(TSymbolTable *symbolTable, const TString *name, const TType &t)
: TSymbol(symbolTable, name), type(t), unionArray(nullptr)
{
}
TStructure::TStructure(TSymbolTable *symbolTable, const TString *name, const TFieldList *fields)
: TSymbol(symbolTable, name), TFieldListCollection(fields)
{
}
void TStructure::createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const
{
ASSERT(containsSamplers());
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
{
TString fieldName = namePrefix + "_" + field->name();
TString fieldApiName = apiNamePrefix + "." + field->name();
fieldType->createSamplerSymbols(fieldName, fieldApiName, outputSymbols,
outputSymbolsToAPINames, symbolTable);
}
}
}
void TStructure::setName(const TString &name)
{
TString *mutableName = const_cast<TString *>(mName);
*mutableName = name;
}
//
// Functions have buried pointers to delete.
//
......@@ -271,7 +307,7 @@ TVariable *TSymbolTable::declareVariable(const TString *name, const TType &type)
return insertVariable(currentLevel(), name, type);
}
TVariable *TSymbolTable::declareStructType(TStructure *str)
bool TSymbolTable::declareStructType(TStructure *str)
{
return insertStructType(currentLevel(), str);
}
......@@ -337,15 +373,14 @@ TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level,
return nullptr;
}
TVariable *TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
bool TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
{
TVariable *var = new TVariable(this, &str->name(), TType(str), true);
if (insert(level, var))
ASSERT(str);
if (insert(level, str))
{
var->getType().realize();
return var;
return true;
}
return nullptr;
return false;
}
void TSymbolTable::insertBuiltIn(ESymbolLevel level,
......
......@@ -59,18 +59,20 @@ class TSymbol : angle::NonCopyable
virtual const TString &getMangledName() const { return name(); }
virtual bool isFunction() const { return false; }
virtual bool isVariable() const { return false; }
virtual bool isStruct() const { return false; }
const TSymbolUniqueId &uniqueId() const { return mUniqueId; }
void relateToExtension(TExtension ext) { mExtension = ext; }
TExtension extension() const { return mExtension; }
protected:
const TString *mName;
private:
const TSymbolUniqueId mUniqueId;
const TString *mName;
TExtension mExtension;
};
// Variable, meaning a symbol that's not a function.
//
// Variable.
// May store the value of a constant variable of any type (float, int, bool or struct).
class TVariable : public TSymbol
{
......@@ -79,7 +81,6 @@ class TVariable : public TSymbol
bool isVariable() const override { return true; }
TType &getType() { return type; }
const TType &getType() const { return type; }
bool isUserType() const { return userType; }
void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
const TConstantUnion *getConstPointer() const { return unionArray; }
......@@ -88,23 +89,37 @@ class TVariable : public TSymbol
private:
friend class TSymbolTable;
TVariable(TSymbolTable *symbolTable,
const TString *name,
const TType &t,
bool isUserTypeDefinition = false)
: TSymbol(symbolTable, name), type(t), userType(isUserTypeDefinition), unionArray(0)
{
}
TVariable(TSymbolTable *symbolTable, const TString *name, const TType &t);
TType type;
const TConstantUnion *unionArray;
};
// Set to true if this represents a struct type, as opposed to a variable.
bool userType;
// Struct type.
class TStructure : public TSymbol, public TFieldListCollection
{
public:
TStructure(TSymbolTable *symbolTable, const TString *name, const TFieldList *fields);
// we are assuming that Pool Allocator will free the memory
// allocated to unionArray when this object is destroyed.
const TConstantUnion *unionArray;
bool isStruct() const override { return true; }
void createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const;
void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
bool atGlobalScope() const { return mAtGlobalScope; }
private:
// TODO(zmo): Find a way to get rid of the const_cast in function
// setName(). At the moment keep this function private so only
// friend class RegenerateStructNames may call it.
friend class RegenerateStructNames;
void setName(const TString &name);
bool mAtGlobalScope;
};
// Immutable version of TParameter.
......@@ -211,7 +226,8 @@ class TFunction : public TSymbol
bool mHasPrototypeDeclaration;
};
// Interface block name sub-symbol
// Reserved interface block name. Note that this simply reserves the block name, not the instance
// name. Interface block instances are stored as TVariable.
class TInterfaceBlockName : public TSymbol
{
public:
......@@ -318,21 +334,21 @@ class TSymbolTable : angle::NonCopyable
}
// 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.
// They return the created symbol / true in case the declaration was successful, and nullptr /
// false if the declaration failed due to redefinition.
TVariable *declareVariable(const TString *name, const TType &type);
TVariable *declareStructType(TStructure *str);
bool 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.
// They return the created symbol / true in case the declaration was successful, and nullptr /
// false if the declaration failed due to redefinition.
TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type);
TVariable *insertVariableExt(ESymbolLevel level,
TExtension ext,
const char *name,
const TType &type);
TVariable *insertStructType(ESymbolLevel level, TStructure *str);
bool insertStructType(ESymbolLevel level, TStructure *str);
TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level,
TExtension ext,
const TString *name);
......
......@@ -874,47 +874,6 @@ void TType::invalidateMangledName()
mMangledName = nullptr;
}
// TStructure implementation.
TStructure::TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields)
: TFieldListCollection(name, fields),
mUniqueId(symbolTable->nextUniqueId()),
mAtGlobalScope(false)
{
}
bool TFieldListCollection::containsArrays() const
{
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
return false;
}
bool TFieldListCollection::containsType(TBasicType type) const
{
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
return true;
}
return false;
}
bool TFieldListCollection::containsSamplers() const
{
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
return true;
}
return false;
}
void TType::createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
......@@ -955,33 +914,51 @@ void TType::createSamplerSymbols(const TString &namePrefix,
}
}
void TStructure::createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const
TFieldListCollection::TFieldListCollection(const TFieldList *fields)
: mFields(fields), mObjectSize(0), mDeepestNesting(0)
{
ASSERT(containsSamplers());
for (auto &field : *mFields)
}
bool TFieldListCollection::containsArrays() const
{
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
return false;
}
bool TFieldListCollection::containsType(TBasicType type) const
{
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
return true;
}
return false;
}
bool TFieldListCollection::containsSamplers() const
{
for (const auto *field : *mFields)
{
const TType *fieldType = field->type();
if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
{
TString fieldName = namePrefix + "_" + field->name();
TString fieldApiName = apiNamePrefix + "." + field->name();
fieldType->createSamplerSymbols(fieldName, fieldApiName, outputSymbols,
outputSymbolsToAPINames, symbolTable);
}
return true;
}
return false;
}
TString TFieldListCollection::buildMangledFieldList() const
{
TString mangledName;
for (size_t i = 0; i < mFields->size(); ++i)
for (const auto *field : *mFields)
{
mangledName += '-';
mangledName += (*mFields)[i]->type()->getMangledName();
mangledName += field->type()->getMangledName();
}
return mangledName;
}
......@@ -1047,6 +1024,19 @@ int TFieldListCollection::calculateDeepestNesting() const
return 1 + maxNesting;
}
TInterfaceBlock::TInterfaceBlock(const TString *name,
const TFieldList *fields,
const TString *instanceName,
const TLayoutQualifier &layoutQualifier)
: TFieldListCollection(fields),
mName(name),
mInstanceName(instanceName),
mBlockStorage(layoutQualifier.blockStorage),
mMatrixPacking(layoutQualifier.matrixPacking),
mBinding(layoutQualifier.binding)
{
}
// TPublicType implementation.
void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
{
......
......@@ -19,6 +19,7 @@ namespace sh
struct TPublicType;
class TType;
class TStructure;
class TSymbol;
class TIntermSymbol;
class TSymbolTable;
......@@ -56,7 +57,6 @@ inline TFieldList *NewPoolTFieldList()
class TFieldListCollection : angle::NonCopyable
{
public:
const TString &name() const { return *mName; }
const TFieldList &fields() const { return *mFields; }
bool containsArrays() const;
......@@ -70,14 +70,9 @@ class TFieldListCollection : angle::NonCopyable
const TString &mangledFieldList() const;
protected:
TFieldListCollection(const TString *name, TFieldList *fields)
: mName(name), mFields(fields), mObjectSize(0), mDeepestNesting(0)
{
}
TFieldListCollection(const TFieldList *fields);
const TString *mName;
TFieldList *mFields;
const TFieldList *mFields;
private:
size_t calculateObjectSize() const;
......@@ -89,55 +84,16 @@ class TFieldListCollection : angle::NonCopyable
mutable TString mMangledFieldList;
};
// May also represent interface blocks
class TStructure : public TFieldListCollection
{
public:
POOL_ALLOCATOR_NEW_DELETE();
TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields);
void createSamplerSymbols(const TString &namePrefix,
const TString &apiNamePrefix,
TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
TSymbolTable *symbolTable) const;
const TSymbolUniqueId &uniqueId() const { return mUniqueId; }
void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
bool atGlobalScope() const { return mAtGlobalScope; }
private:
// TODO(zmo): Find a way to get rid of the const_cast in function
// setName(). At the moment keep this function private so only
// friend class RegenerateStructNames may call it.
friend class RegenerateStructNames;
void setName(const TString &name)
{
TString *mutableName = const_cast<TString *>(mName);
*mutableName = name;
}
const TSymbolUniqueId mUniqueId;
bool mAtGlobalScope;
};
class TInterfaceBlock : public TFieldListCollection
{
public:
POOL_ALLOCATOR_NEW_DELETE();
TInterfaceBlock(const TString *name,
TFieldList *fields,
const TFieldList *fields,
const TString *instanceName,
const TLayoutQualifier &layoutQualifier)
: TFieldListCollection(name, fields),
mInstanceName(instanceName),
mBlockStorage(layoutQualifier.blockStorage),
mMatrixPacking(layoutQualifier.matrixPacking),
mBinding(layoutQualifier.binding)
{
}
const TLayoutQualifier &layoutQualifier);
const TString &name() const { return *mName; }
const TString &instanceName() const { return *mInstanceName; }
bool hasInstanceName() const { return mInstanceName != nullptr; }
TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
......@@ -145,6 +101,7 @@ class TInterfaceBlock : public TFieldListCollection
int blockBinding() const { return mBinding; }
private:
const TString *mName;
const TString *mInstanceName; // for interface block instance names
TLayoutBlockStorage mBlockStorage;
TLayoutMatrixPacking mMatrixPacking;
......
......@@ -11,6 +11,7 @@
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/util.h"
namespace sh
......
......@@ -439,14 +439,12 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
int check_type(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion());
if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
token = TYPE_NAME;
}
if (symbol && symbol->isStruct())
{
token = TYPE_NAME;
}
yylval->lex.symbol = symbol;
return token;
......
......@@ -1150,9 +1150,6 @@ type_specifier_nonarray
}
$$.initialize(EbtSampler2DRect, @1);
}
| struct_specifier {
$$ = $1;
}
| IMAGE2D {
$$.initialize(EbtImage2D, @1);
}
......@@ -1192,10 +1189,13 @@ type_specifier_nonarray
| ATOMICUINT {
$$.initialize(EbtAtomicCounter, @1);
}
| struct_specifier {
$$ = $1;
}
| 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.getStruct(), false, @1);
TStructure *structure = static_cast<TStructure*>($1.symbol);
$$.initializeStruct(structure, false, @1);
}
;
......
......@@ -3795,14 +3795,12 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
int check_type(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion());
if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
token = TYPE_NAME;
}
if (symbol && symbol->isStruct())
{
token = TYPE_NAME;
}
yylval->lex.symbol = symbol;
return token;
......
......@@ -939,10 +939,10 @@ static const yytype_uint16 yydefact[] =
123, 122, 141, 142, 143, 144, 145, 146, 0, 164,
191, 193, 209, 211, 194, 196, 197, 198, 199, 201,
202, 203, 204, 195, 200, 205, 192, 206, 207, 208,
210, 213, 214, 215, 216, 217, 218, 219, 220, 221,
222, 223, 224, 225, 0, 190, 226, 295, 296, 0,
210, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 0, 190, 226, 295, 296, 0,
99, 98, 0, 110, 115, 130, 0, 131, 124, 127,
120, 129, 128, 147, 158, 212, 0, 292, 294, 0,
120, 129, 128, 147, 158, 225, 0, 292, 294, 0,
2, 3, 229, 0, 0, 89, 0, 97, 0, 106,
100, 108, 0, 109, 0, 90, 2, 116, 0, 95,
0, 125, 121, 0, 159, 1, 293, 0, 0, 227,
......@@ -4269,7 +4269,7 @@ yyreduce:
case 212:
{
(yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray);
(yyval.interm.typeSpecifierNonArray).initialize(EbtImage2D, (yylsp[0]));
}
break;
......@@ -4277,7 +4277,7 @@ yyreduce:
case 213:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtImage2D, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2D, (yylsp[0]));
}
break;
......@@ -4285,7 +4285,7 @@ yyreduce:
case 214:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2D, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2D, (yylsp[0]));
}
break;
......@@ -4293,7 +4293,7 @@ yyreduce:
case 215:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2D, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtImage3D, (yylsp[0]));
}
break;
......@@ -4301,7 +4301,7 @@ yyreduce:
case 216:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtImage3D, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImage3D, (yylsp[0]));
}
break;
......@@ -4309,7 +4309,7 @@ yyreduce:
case 217:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImage3D, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImage3D, (yylsp[0]));
}
break;
......@@ -4317,7 +4317,7 @@ yyreduce:
case 218:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImage3D, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtImage2DArray, (yylsp[0]));
}
break;
......@@ -4325,7 +4325,7 @@ yyreduce:
case 219:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtImage2DArray, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2DArray, (yylsp[0]));
}
break;
......@@ -4333,7 +4333,7 @@ yyreduce:
case 220:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2DArray, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2DArray, (yylsp[0]));
}
break;
......@@ -4341,7 +4341,7 @@ yyreduce:
case 221:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2DArray, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtImageCube, (yylsp[0]));
}
break;
......@@ -4349,7 +4349,7 @@ yyreduce:
case 222:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtImageCube, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCube, (yylsp[0]));
}
break;
......@@ -4357,7 +4357,7 @@ yyreduce:
case 223:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCube, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCube, (yylsp[0]));
}
break;
......@@ -4365,7 +4365,7 @@ yyreduce:
case 224:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCube, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray).initialize(EbtAtomicCounter, (yylsp[0]));
}
break;
......@@ -4373,7 +4373,7 @@ yyreduce:
case 225:
{
(yyval.interm.typeSpecifierNonArray).initialize(EbtAtomicCounter, (yylsp[0]));
(yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray);
}
break;
......@@ -4382,8 +4382,8 @@ 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.getStruct(), false, (yylsp[0]));
TStructure *structure = static_cast<TStructure*>((yyvsp[0].lex).symbol);
(yyval.interm.typeSpecifierNonArray).initializeStruct(structure, 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