Commit e5fe7aad by Olli Etuaho Committed by Commit Bot

Store builtin symbols as const pointers

To do this we need two types of symbol table levels: A level for built-ins and a level for user-defined symbols. User-defined symbols are non-const because function symbols created based on function prototypes are changed when the function definition is parsed. On the other hand, we want to make built-in symbols constexpr, so we should only handle them through const pointers. This also gets rid of extra empty precision stack levels. Only one level is needed to store predefined precisions. BUG=angleproject:2267 TEST=angle_unittests Change-Id: I9f14b24c2cfce272f22c16e7a8dfb653b849cbeb Reviewed-on: https://chromium-review.googlesource.com/892879 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 8f27b050
......@@ -336,7 +336,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
// We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level.
TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
TScopedSymbolTableLevel globalLevel(&symbolTable);
ASSERT(symbolTable.atGlobalLevel());
// Parse shader.
if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
......
......@@ -13,12 +13,13 @@
#include "compiler/translator/SymbolTable.h"
#include <algorithm>
#include <set>
#include "angle_gl.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/IntermNode.h"
#include <stdio.h>
#include <algorithm>
#include "compiler/translator/StaticType.h"
namespace sh
{
......@@ -44,9 +45,6 @@ class TSymbolTable::TSymbolTableLevel
void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
void insertUnmangledBuiltInName(const char *name);
bool hasUnmangledBuiltIn(const char *name) const;
private:
using tLevel = TUnorderedMap<ImmutableString,
TSymbol *,
......@@ -55,8 +53,34 @@ class TSymbolTable::TSymbolTableLevel
using tInsertResult = std::pair<tLevel::iterator, bool>;
tLevel level;
std::set<std::string> mInvariantVaryings;
bool mGlobalInvariant;
};
class TSymbolTable::TSymbolTableBuiltInLevel
{
public:
TSymbolTableBuiltInLevel() = default;
bool insert(const TSymbol *symbol);
// Insert a function using its unmangled name as the key.
bool insertUnmangled(const TFunction *function);
const TSymbol *find(const ImmutableString &name) const;
void insertUnmangledBuiltInName(const char *name);
bool hasUnmangledBuiltIn(const char *name) const;
private:
using tLevel = TUnorderedMap<ImmutableString,
const TSymbol *,
ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
using tLevelPair = const tLevel::value_type;
using tInsertResult = std::pair<tLevel::iterator, bool>;
tLevel mLevel;
std::set<ImmutableString> mUnmangledBuiltInNames;
};
......@@ -65,7 +89,6 @@ bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
{
// returning true means symbol was added to the table
tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
return result.second;
}
......@@ -73,7 +96,6 @@ bool TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
{
// returning true means symbol was added to the table
tInsertResult result = level.insert(tLevelPair(function->name(), function));
return result.second;
}
......@@ -81,34 +103,66 @@ TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) cons
{
tLevel::const_iterator it = level.find(name);
if (it == level.end())
return 0;
return nullptr;
else
return (*it).second;
}
bool TSymbolTable::TSymbolTableBuiltInLevel::insert(const TSymbol *symbol)
{
// returning true means symbol was added to the table
tInsertResult result = mLevel.insert(tLevelPair(symbol->getMangledName(), symbol));
return result.second;
}
bool TSymbolTable::TSymbolTableBuiltInLevel::insertUnmangled(const TFunction *function)
{
// returning true means symbol was added to the table
tInsertResult result = mLevel.insert(tLevelPair(function->name(), function));
return result.second;
}
const TSymbol *TSymbolTable::TSymbolTableBuiltInLevel::find(const ImmutableString &name) const
{
tLevel::const_iterator it = mLevel.find(name);
if (it == mLevel.end())
return nullptr;
else
return (*it).second;
}
void TSymbolTable::TSymbolTableLevel::insertUnmangledBuiltInName(const char *name)
void TSymbolTable::TSymbolTableBuiltInLevel::insertUnmangledBuiltInName(const char *name)
{
mUnmangledBuiltInNames.insert(ImmutableString(name));
}
bool TSymbolTable::TSymbolTableLevel::hasUnmangledBuiltIn(const char *name) const
bool TSymbolTable::TSymbolTableBuiltInLevel::hasUnmangledBuiltIn(const char *name) const
{
return mUnmangledBuiltInNames.count(ImmutableString(name)) > 0;
}
TSymbolTable::TSymbolTable() : mUniqueIdCounter(0), mUserDefinedUniqueIdsStart(-1)
{
}
TSymbolTable::~TSymbolTable() = default;
void TSymbolTable::pushBuiltInLevel()
{
mBuiltInTable.push_back(
std::unique_ptr<TSymbolTableBuiltInLevel>(new TSymbolTableBuiltInLevel));
}
void TSymbolTable::push()
{
table.push_back(new TSymbolTableLevel);
precisionStack.push_back(new PrecisionStackLevel);
mTable.push_back(std::unique_ptr<TSymbolTableLevel>(new TSymbolTableLevel));
mPrecisionStack.push_back(std::unique_ptr<PrecisionStackLevel>(new PrecisionStackLevel));
}
void TSymbolTable::pop()
{
delete table.back();
table.pop_back();
delete precisionStack.back();
precisionStack.pop_back();
mTable.pop_back();
mPrecisionStack.pop_back();
}
const TFunction *TSymbolTable::markUserDefinedFunctionHasPrototypeDeclaration(
......@@ -144,37 +198,31 @@ const TFunction *TSymbolTable::setUserDefinedFunctionParameterNamesFromDefinitio
const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
{
int level = currentLevel();
TSymbol *symbol = nullptr;
do
int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
while (userDefinedLevel >= 0)
{
if (level == GLSL_BUILTINS)
level--;
if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
level--;
if (level == ESSL3_BUILTINS && shaderVersion < 300)
level--;
if (level == ESSL1_BUILTINS && shaderVersion != 100)
level--;
symbol = table[level]->find(name);
level--;
} while (symbol == nullptr && level >= 0);
const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
if (symbol)
{
return symbol;
}
userDefinedLevel--;
}
return symbol;
return findBuiltIn(name, shaderVersion, false);
}
TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &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));
ASSERT(!mTable.empty());
return static_cast<TFunction *>(mTable[0]->find(name));
}
const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
{
ASSERT(table.size() > GLOBAL_LEVEL);
return table[GLOBAL_LEVEL]->find(name);
ASSERT(!mTable.empty());
return mTable[0]->find(name);
}
const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name, int shaderVersion) const
......@@ -197,7 +245,7 @@ const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name,
if (level == ESSL1_BUILTINS && shaderVersion != 100)
level--;
TSymbol *symbol = table[level]->find(name);
const TSymbol *symbol = mBuiltInTable[level]->find(name);
if (symbol)
return symbol;
......@@ -206,12 +254,6 @@ const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name,
return nullptr;
}
TSymbolTable::~TSymbolTable()
{
while (table.size() > 0)
pop();
}
constexpr bool IsGenType(const TType *type)
{
if (type)
......@@ -314,9 +356,9 @@ void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUn
if (insertUnmangledName)
{
// Insert the unmangled name to detect potential future redefinition as a variable.
table[GLOBAL_LEVEL]->insertUnmangled(function);
mTable[0]->insertUnmangled(function);
}
table[GLOBAL_LEVEL]->insert(function);
mTable[0]->insert(function);
}
TVariable *TSymbolTable::insertVariable(ESymbolLevel level,
......@@ -342,19 +384,17 @@ TVariable *TSymbolTable::insertVariable(ESymbolLevel level,
return nullptr;
}
TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level,
TExtension ext,
const ImmutableString &name,
const TType *type)
void TSymbolTable::insertVariableExt(ESymbolLevel level,
TExtension ext,
const ImmutableString &name,
const TType *type)
{
ASSERT(level <= LAST_BUILTIN_LEVEL);
ASSERT(type->isRealized());
TVariable *var = new TVariable(this, name, type, SymbolType::BuiltIn, ext);
if (insert(level, var))
{
return var;
}
return nullptr;
bool inserted = insert(level, var);
UNUSED_VARIABLE(inserted);
ASSERT(inserted);
}
bool TSymbolTable::insertVariable(ESymbolLevel level, TVariable *variable)
......@@ -367,7 +407,14 @@ bool TSymbolTable::insertVariable(ESymbolLevel level, TVariable *variable)
bool TSymbolTable::insert(ESymbolLevel level, TSymbol *symbol)
{
ASSERT(level > LAST_BUILTIN_LEVEL || mUserDefinedUniqueIdsStart == -1);
return table[level]->insert(symbol);
if (level <= LAST_BUILTIN_LEVEL)
{
return mBuiltInTable[level]->insert(symbol);
}
else
{
return mTable[level - LAST_BUILTIN_LEVEL - 1]->insert(symbol);
}
}
bool TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
......@@ -638,6 +685,13 @@ void TSymbolTable::insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
new TFunction(this, ImmutableString(name), rvalue, SymbolType::BuiltIn, false, op, ext));
}
void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
{
int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
// Uses map operator [], overwrites the current value
(*mPrecisionStack[indexOfLastElement])[type] = prec;
}
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
{
if (!SupportsPrecision(type))
......@@ -646,14 +700,14 @@ TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
// unsigned integers use the same precision as signed
TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
int level = static_cast<int>(precisionStack.size()) - 1;
assert(level >= 0); // Just to be safe. Should not happen.
int level = static_cast<int>(mPrecisionStack.size()) - 1;
ASSERT(level >= 0); // Just to be safe. Should not happen.
// If we dont find anything we return this. Some types don't have predefined default precision.
TPrecision prec = EbpUndefined;
while (level >= 0)
{
PrecisionStackLevel::iterator it = precisionStack[level]->find(baseType);
if (it != precisionStack[level]->end())
PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
if (it != mPrecisionStack[level]->end())
{
prec = (*it).second;
break;
......@@ -666,38 +720,36 @@ TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
void TSymbolTable::addInvariantVarying(const std::string &originalName)
{
ASSERT(atGlobalLevel());
table[currentLevel()]->addInvariantVarying(originalName);
mTable.back()->addInvariantVarying(originalName);
}
bool TSymbolTable::isVaryingInvariant(const std::string &originalName) const
{
ASSERT(atGlobalLevel());
return table[currentLevel()]->isVaryingInvariant(originalName);
return mTable.back()->isVaryingInvariant(originalName);
}
void TSymbolTable::setGlobalInvariant(bool invariant)
{
ASSERT(atGlobalLevel());
table[currentLevel()]->setGlobalInvariant(invariant);
mTable.back()->setGlobalInvariant(invariant);
}
void TSymbolTable::insertUnmangledBuiltInName(const char *name, ESymbolLevel level)
{
ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
ASSERT(level >= 0 && level <= LAST_BUILTIN_LEVEL);
ASSERT(mUserDefinedUniqueIdsStart == -1);
table[level]->insertUnmangledBuiltInName(name);
mBuiltInTable[level]->insertUnmangledBuiltInName(name);
}
bool TSymbolTable::hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level)
{
ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
return table[level]->hasUnmangledBuiltIn(name);
ASSERT(level >= 0 && level <= LAST_BUILTIN_LEVEL);
return mBuiltInTable[level]->hasUnmangledBuiltIn(name);
}
bool TSymbolTable::hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion)
{
ASSERT(static_cast<ESymbolLevel>(table.size()) > LAST_BUILTIN_LEVEL);
for (int level = LAST_BUILTIN_LEVEL; level >= 0; --level)
{
if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
......@@ -713,7 +765,7 @@ bool TSymbolTable::hasUnmangledBuiltInForShaderVersion(const char *name, int sha
--level;
}
if (table[level]->hasUnmangledBuiltIn(name))
if (mBuiltInTable[level]->hasUnmangledBuiltIn(name))
{
return true;
}
......@@ -731,7 +783,7 @@ void TSymbolTable::clearCompilationResults()
mUniqueIdCounter = mUserDefinedUniqueIdsStart;
// User-defined scopes should have already been cleared when the compilation finished.
ASSERT(table.size() == LAST_BUILTIN_LEVEL + 1u);
ASSERT(mTable.size() == 0u);
}
int TSymbolTable::nextUniqueIdValue()
......@@ -745,11 +797,14 @@ void TSymbolTable::initializeBuiltIns(sh::GLenum type,
const ShBuiltInResources &resources)
{
ASSERT(isEmpty());
push(); // COMMON_BUILTINS
push(); // ESSL1_BUILTINS
push(); // ESSL3_BUILTINS
push(); // ESSL3_1_BUILTINS
push(); // GLSL_BUILTINS
pushBuiltInLevel(); // COMMON_BUILTINS
pushBuiltInLevel(); // ESSL1_BUILTINS
pushBuiltInLevel(); // ESSL3_BUILTINS
pushBuiltInLevel(); // ESSL3_1_BUILTINS
pushBuiltInLevel(); // GLSL_BUILTINS
// We need just one precision stack level for predefined precisions.
mPrecisionStack.push_back(std::unique_ptr<PrecisionStackLevel>(new PrecisionStackLevel));
switch (type)
{
......
......@@ -31,15 +31,13 @@
//
#include <array>
#include <assert.h>
#include <set>
#include <memory>
#include "common/angleutils.h"
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
namespace sh
......@@ -62,19 +60,17 @@ const int GLOBAL_LEVEL = 5;
class TSymbolTable : angle::NonCopyable
{
public:
TSymbolTable() : mUniqueIdCounter(0), mUserDefinedUniqueIdsStart(-1)
{
// The symbol table cannot be used until push() is called, but
// the lack of an initial call to push() can be used to detect
// that the symbol table has not been preloaded with built-ins.
}
TSymbolTable();
// To start using the symbol table after construction:
// * initializeBuiltIns() needs to be called.
// * push() needs to be called to push the global level.
~TSymbolTable();
// When the symbol table is initialized with the built-ins, there should
// 'push' calls, so that built-ins are at level 0 and the shader
// globals are at level 1.
bool isEmpty() const { return table.empty(); }
bool isEmpty() const { return mTable.empty(); }
bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
......@@ -109,12 +105,7 @@ class TSymbolTable : angle::NonCopyable
int shaderVersion,
bool includeGLSLBuiltins) const;
void setDefaultPrecision(TBasicType type, TPrecision prec)
{
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
// Uses map operator [], overwrites the current value
(*precisionStack[indexOfLastElement])[type] = prec;
}
void setDefaultPrecision(TBasicType type, TPrecision prec);
// Searches down the precisionStack for a precision qualifier
// for the specified TBasicType
......@@ -146,18 +137,24 @@ class TSymbolTable : angle::NonCopyable
friend class TSymbolUniqueId;
int nextUniqueIdValue();
class TSymbolTableBuiltInLevel;
class TSymbolTableLevel;
ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
void pushBuiltInLevel();
ESymbolLevel currentLevel() const
{
return static_cast<ESymbolLevel>(mTable.size() + LAST_BUILTIN_LEVEL);
}
// The insert* entry points are used when initializing the symbol table with built-ins.
// 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 ImmutableString &name, const TType *type);
TVariable *insertVariableExt(ESymbolLevel level,
TExtension ext,
const ImmutableString &name,
const TType *type);
void insertVariableExt(ESymbolLevel level,
TExtension ext,
const ImmutableString &name,
const TType *type);
bool insertVariable(ESymbolLevel level, TVariable *variable);
bool insertStructType(ESymbolLevel level, TStructure *str);
bool insertInterfaceBlock(ESymbolLevel level, TInterfaceBlock *interfaceBlock);
......@@ -272,9 +269,13 @@ class TSymbolTable : angle::NonCopyable
const ShBuiltInResources &resources);
void markBuiltInInitializationFinished();
std::vector<TSymbolTableLevel *> table;
std::vector<std::unique_ptr<TSymbolTableBuiltInLevel>> mBuiltInTable;
std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
// There's one precision stack level for predefined precisions and then one level for each scope
// in table.
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
std::vector<PrecisionStackLevel *> precisionStack;
std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack;
int mUniqueIdCounter;
......
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