Add const qualification to symbol accesses
All accesses to built-in symbols now happen through const-qualified
pointers.
This also encapsulates TSymbolTableLevel inside TSymbolTable.
This prepares for statically allocating built-in symbols.
BUG=angleproject:2267
TEST=angle_unittests
Change-Id: I473014d978daa765b4a733d761d6c08b28288776
Reviewed-on: https://chromium-review.googlesource.com/859959
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 39dd6cc..7d841b6 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -21,16 +21,57 @@
namespace sh
{
+class TSymbolTable::TSymbolTableLevel
+{
+ public:
+ TSymbolTableLevel() : mGlobalInvariant(false) {}
+ ~TSymbolTableLevel();
+
+ bool insert(TSymbol *symbol);
+
+ // Insert a function using its unmangled name as the key.
+ bool insertUnmangled(TFunction *function);
+
+ TSymbol *find(const TString &name) const;
+
+ void addInvariantVarying(const std::string &name) { mInvariantVaryings.insert(name); }
+
+ bool isVaryingInvariant(const std::string &name)
+ {
+ return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
+ }
+
+ void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
+
+ void insertUnmangledBuiltInName(const char *name);
+ bool hasUnmangledBuiltIn(const char *name) const;
+
+ private:
+ using tLevel = TUnorderedMap<TString, TSymbol *>;
+ using tLevelPair = const tLevel::value_type;
+ using tInsertResult = std::pair<tLevel::iterator, bool>;
+
+ tLevel level;
+ std::set<std::string> mInvariantVaryings;
+ bool mGlobalInvariant;
+
+ struct CharArrayComparator
+ {
+ bool operator()(const char *a, const char *b) const { return strcmp(a, b) < 0; }
+ };
+ std::set<const char *, CharArrayComparator> mUnmangledBuiltInNames;
+};
+
//
// Symbol table levels are a map of pointers to symbols that have to be deleted.
//
-TSymbolTableLevel::~TSymbolTableLevel()
+TSymbolTable::TSymbolTableLevel::~TSymbolTableLevel()
{
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
delete (*it).second;
}
-bool TSymbolTableLevel::insert(TSymbol *symbol)
+bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
{
// returning true means symbol was added to the table
tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
@@ -38,7 +79,7 @@
return result.second;
}
-bool TSymbolTableLevel::insertUnmangled(TFunction *function)
+bool TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
{
// returning true means symbol was added to the table
tInsertResult result = level.insert(tLevelPair(function->name(), function));
@@ -46,7 +87,7 @@
return result.second;
}
-TSymbol *TSymbolTableLevel::find(const TString &name) const
+TSymbol *TSymbolTable::TSymbolTableLevel::find(const TString &name) const
{
tLevel::const_iterator it = level.find(name);
if (it == level.end())
@@ -55,24 +96,69 @@
return (*it).second;
}
-void TSymbolTableLevel::insertUnmangledBuiltInName(const char *name)
+void TSymbolTable::TSymbolTableLevel::insertUnmangledBuiltInName(const char *name)
{
mUnmangledBuiltInNames.insert(name);
}
-bool TSymbolTableLevel::hasUnmangledBuiltIn(const char *name) const
+bool TSymbolTable::TSymbolTableLevel::hasUnmangledBuiltIn(const char *name) const
{
return mUnmangledBuiltInNames.count(name) > 0;
}
-TSymbol *TSymbolTable::find(const TString &name,
- int shaderVersion,
- bool *builtIn,
- bool *sameScope) const
+void TSymbolTable::push()
{
- int level = currentLevel();
- TSymbol *symbol;
+ table.push_back(new TSymbolTableLevel);
+ precisionStack.push_back(new PrecisionStackLevel);
+}
+void TSymbolTable::pop()
+{
+ delete table.back();
+ table.pop_back();
+
+ delete precisionStack.back();
+ precisionStack.pop_back();
+}
+
+const TFunction *TSymbolTable::markUserDefinedFunctionHasPrototypeDeclaration(
+ const TString &mangledName,
+ bool *hadPrototypeDeclarationOut)
+{
+ TFunction *function = findUserDefinedFunction(mangledName);
+ *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
+ function->setHasPrototypeDeclaration();
+ return function;
+}
+
+const TFunction *TSymbolTable::setUserDefinedFunctionParameterNamesFromDefinition(
+ const TFunction *function,
+ bool *wasDefinedOut)
+{
+ TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
+ ASSERT(firstDeclaration);
+ // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
+ // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
+ // occurance.
+ if (function != firstDeclaration)
+ {
+ // Swap the parameters of the previous declaration to the parameters of the function
+ // definition (parameter names may differ).
+ firstDeclaration->swapParameters(*function);
+ }
+
+ *wasDefinedOut = firstDeclaration->isDefined();
+ firstDeclaration->setDefined();
+ return firstDeclaration;
+}
+
+const TSymbol *TSymbolTable::find(const TString &name,
+ int shaderVersion,
+ bool *builtIn,
+ bool *sameScope) const
+{
+ int level = currentLevel();
+ TSymbol *symbol = nullptr;
do
{
if (level == GLSL_BUILTINS)
@@ -85,7 +171,7 @@
level--;
symbol = table[level]->find(name);
- } while (symbol == 0 && --level >= 0);
+ } while (symbol == nullptr && --level >= 0);
if (builtIn)
*builtIn = (level <= LAST_BUILTIN_LEVEL);
@@ -95,20 +181,27 @@
return symbol;
}
-TSymbol *TSymbolTable::findGlobal(const TString &name) const
+TFunction *TSymbolTable::findUserDefinedFunction(const TString &name) const
+{
+ // User-defined functions are always declared at the global level.
+ ASSERT(currentLevel() >= GLOBAL_LEVEL);
+ return static_cast<TFunction *>(table[GLOBAL_LEVEL]->find(name));
+}
+
+const TSymbol *TSymbolTable::findGlobal(const TString &name) const
{
ASSERT(table.size() > GLOBAL_LEVEL);
return table[GLOBAL_LEVEL]->find(name);
}
-TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
+const TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
{
return findBuiltIn(name, shaderVersion, false);
}
-TSymbol *TSymbolTable::findBuiltIn(const TString &name,
- int shaderVersion,
- bool includeGLSLBuiltins) const
+const TSymbol *TSymbolTable::findBuiltIn(const TString &name,
+ int shaderVersion,
+ bool includeGLSLBuiltins) const
{
for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
{
@@ -232,6 +325,17 @@
return insert(currentLevel(), interfaceBlock);
}
+void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
+{
+ ASSERT(currentLevel() >= GLOBAL_LEVEL);
+ if (insertUnmangledName)
+ {
+ // Insert the unmangled name to detect potential future redefinition as a variable.
+ table[GLOBAL_LEVEL]->insertUnmangled(function);
+ }
+ table[GLOBAL_LEVEL]->insert(function);
+}
+
TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType *type)
{
ASSERT(level <= LAST_BUILTIN_LEVEL);
@@ -275,6 +379,12 @@
return insert(level, variable);
}
+bool TSymbolTable::insert(ESymbolLevel level, TSymbol *symbol)
+{
+ ASSERT(level > LAST_BUILTIN_LEVEL || mUserDefinedUniqueIdsStart == -1);
+ return table[level]->insert(symbol);
+}
+
bool TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
{
ASSERT(str);
@@ -525,6 +635,24 @@
return prec;
}
+void TSymbolTable::addInvariantVarying(const std::string &originalName)
+{
+ ASSERT(atGlobalLevel());
+ table[currentLevel()]->addInvariantVarying(originalName);
+}
+
+bool TSymbolTable::isVaryingInvariant(const std::string &originalName) const
+{
+ ASSERT(atGlobalLevel());
+ return table[currentLevel()]->isVaryingInvariant(originalName);
+}
+
+void TSymbolTable::setGlobalInvariant(bool invariant)
+{
+ ASSERT(atGlobalLevel());
+ table[currentLevel()]->setGlobalInvariant(invariant);
+}
+
void TSymbolTable::insertUnmangledBuiltInName(const char *name, ESymbolLevel level)
{
ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));