summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/SymbolTable.h')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolTable.h494
1 files changed, 273 insertions, 221 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
index 2706149e3c..5d792ec188 100644
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
@@ -18,7 +18,7 @@
// so that symbol table lookups are never ambiguous. This allows
// a simpler symbol table structure.
//
-// * Pushing and popping of scope, so symbol table will really be a stack
+// * Pushing and popping of scope, so symbol table will really be a stack
// of symbol tables. Searched from the top, with new inserts going into
// the top.
//
@@ -30,111 +30,78 @@
// are tracked in the intermediate representation, not the symbol table.
//
+#include <array>
#include <assert.h>
#include <set>
#include "common/angleutils.h"
+#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolUniqueId.h"
+
+namespace sh
+{
// Symbol base class. (Can build functions or variables out of these...)
class TSymbol : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
- TSymbol(const TString *n)
- : uniqueId(0),
- name(n)
- {
- }
+ TSymbol(TSymbolTable *symbolTable, const TString *n);
+
virtual ~TSymbol()
{
// don't delete name, it's from the pool
}
- const TString &getName() const
- {
- return *name;
- }
- virtual const TString &getMangledName() const
- {
- return getName();
- }
- virtual bool isFunction() const
- {
- return false;
- }
- virtual bool isVariable() const
- {
- return false;
- }
- void setUniqueId(int id)
- {
- uniqueId = id;
- }
- int getUniqueId() const
- {
- return uniqueId;
- }
- void relateToExtension(const TString &ext)
- {
- extension = ext;
- }
- const TString &getExtension() const
- {
- return extension;
- }
+ const TString &getName() const { return *name; }
+ virtual const TString &getMangledName() const { return getName(); }
+ virtual bool isFunction() const { return false; }
+ virtual bool isVariable() const { return false; }
+ const TSymbolUniqueId &getUniqueId() const { return uniqueId; }
+ void relateToExtension(TExtension ext) { extension = ext; }
+ TExtension getExtension() const { return extension; }
private:
- int uniqueId; // For real comparing during code generation
+ const TSymbolUniqueId uniqueId;
const TString *name;
- TString extension;
+ TExtension extension;
};
-// Variable class, 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.
+// Variable, meaning a symbol that's not a function.
+//
+// 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;
- }
- const TType &getType() const
- {
- return type;
- }
- bool isUserType() const
- {
- return userType;
- }
- void setQualifier(TQualifier qualifier)
- {
- type.setQualifier(qualifier);
- }
+ 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; }
void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
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)
+ {
+ }
+
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;
@@ -143,34 +110,18 @@ class TVariable : public TSymbol
// Immutable version of TParameter.
struct TConstParameter
{
- TConstParameter()
- : name(nullptr),
- type(nullptr)
- {
- }
- explicit TConstParameter(const TString *n)
- : name(n),
- type(nullptr)
- {
- }
- explicit TConstParameter(const TType *t)
- : name(nullptr),
- type(t)
- {
- }
- TConstParameter(const TString *n, const TType *t)
- : name(n),
- type(t)
- {
- }
+ TConstParameter() : name(nullptr), type(nullptr) {}
+ explicit TConstParameter(const TString *n) : name(n), type(nullptr) {}
+ explicit TConstParameter(const TType *t) : name(nullptr), type(t) {}
+ TConstParameter(const TString *n, const TType *t) : name(n), type(t) {}
// Both constructor arguments must be const.
- TConstParameter(TString *n, TType *t) = delete;
+ TConstParameter(TString *n, TType *t) = delete;
TConstParameter(const TString *n, TType *t) = delete;
TConstParameter(TString *n, const TType *t) = delete;
- const TString *name;
- const TType *type;
+ const TString *const name;
+ const TType *const type;
};
// The function sub-class of symbols and the parser will need to
@@ -183,25 +134,26 @@ struct TParameter
TConstParameter turnToConst()
{
const TString *constName = name;
- const TType *constType = type;
- name = nullptr;
- type = nullptr;
+ const TType *constType = type;
+ name = nullptr;
+ type = nullptr;
return TConstParameter(constName, constType);
}
- TString *name;
+ const TString *name;
TType *type;
};
-// The function sub-class of a symbol.
+// The function sub-class of a symbol.
class TFunction : public TSymbol
{
public:
- TFunction(const TString *name,
+ TFunction(TSymbolTable *symbolTable,
+ const TString *name,
const TType *retType,
- TOperator tOp = EOpNull,
- const char *ext = "")
- : TSymbol(name),
+ TOperator tOp = EOpNull,
+ TExtension ext = TExtension::UNDEFINED)
+ : TSymbol(symbolTable, name),
returnType(retType),
mangledName(nullptr),
op(tOp),
@@ -213,21 +165,14 @@ class TFunction : public TSymbol
~TFunction() override;
bool isFunction() const override { return true; }
- static TString mangleName(const TString &name)
- {
- return name + '(';
- }
- static TString unmangleName(const TString &mangledName)
- {
- return TString(mangledName.c_str(), mangledName.find_first_of('('));
- }
-
void addParameter(const TConstParameter &p)
{
parameters.push_back(p);
mangledName = nullptr;
}
+ void swapParameters(const TFunction &parametersSource);
+
const TString &getMangledName() const override
{
if (mangledName == nullptr)
@@ -236,31 +181,25 @@ class TFunction : public TSymbol
}
return *mangledName;
}
- const TType &getReturnType() const
- {
- return *returnType;
- }
- TOperator getBuiltInOp() const
- {
- return op;
- }
+ static const TString &GetMangledNameFromCall(const TString &functionName,
+ const TIntermSequence &arguments);
+
+ const TType &getReturnType() const { return *returnType; }
+
+ TOperator getBuiltInOp() const { return op; }
void setDefined() { defined = true; }
bool isDefined() { return defined; }
void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
- size_t getParamCount() const
- {
- return parameters.size();
- }
- const TConstParameter &getParam(size_t i) const
- {
- return parameters[i];
- }
+ size_t getParamCount() const { return parameters.size(); }
+ const TConstParameter &getParam(size_t i) const { return parameters[i]; }
private:
+ void clearParameters();
+
const TString *buildMangledName() const;
typedef TVector<TConstParameter> TParamList;
@@ -276,12 +215,11 @@ class TFunction : public TSymbol
class TInterfaceBlockName : public TSymbol
{
public:
- TInterfaceBlockName(const TString *name)
- : TSymbol(name)
- {
- }
+ virtual ~TInterfaceBlockName() {}
- virtual ~TInterfaceBlockName()
+ private:
+ friend class TSymbolTable;
+ TInterfaceBlockName(TSymbolTable *symbolTable, const TString *name) : TSymbol(symbolTable, name)
{
}
};
@@ -289,14 +227,12 @@ class TInterfaceBlockName : public TSymbol
class TSymbolTableLevel
{
public:
- typedef TMap<TString, TSymbol *> tLevel;
+ typedef TUnorderedMap<TString, TSymbol *> tLevel;
typedef tLevel::const_iterator const_iterator;
typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult;
- TSymbolTableLevel()
- {
- }
+ TSymbolTableLevel() : mGlobalInvariant(false) {}
~TSymbolTableLevel();
bool insert(TSymbol *symbol);
@@ -306,25 +242,52 @@ class TSymbolTableLevel
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 std::string &name)
+ {
+ mUnmangledBuiltInNames.insert(name);
+ }
+
+ bool hasUnmangledBuiltIn(const std::string &name)
+ {
+ return mUnmangledBuiltInNames.count(name) > 0;
+ }
+
protected:
tLevel level;
+ std::set<std::string> mInvariantVaryings;
+ bool mGlobalInvariant;
+
+ private:
+ std::set<std::string> mUnmangledBuiltInNames;
};
// Define ESymbolLevel as int rather than an enum since level can go
// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
// compiler optimizes the >= of the last element to ==.
typedef int ESymbolLevel;
-const int COMMON_BUILTINS = 0;
-const int ESSL1_BUILTINS = 1;
-const int ESSL3_BUILTINS = 2;
-const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS;
-const int GLOBAL_LEVEL = 3;
+const int COMMON_BUILTINS = 0;
+const int ESSL1_BUILTINS = 1;
+const int ESSL3_BUILTINS = 2;
+const int ESSL3_1_BUILTINS = 3;
+// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement
+// features in ANGLE's GLSL backend. They're not visible to the parser.
+const int GLSL_BUILTINS = 4;
+const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
+const int GLOBAL_LEVEL = 5;
class TSymbolTable : angle::NonCopyable
{
public:
- TSymbolTable()
- : mGlobalInvariant(false)
+ TSymbolTable() : mUniqueIdCounter(0), mEmptySymbolId(this)
{
// The symbol table cannot be used until push() is called, but
// the lack of an initial call to push() can be used to detect
@@ -336,18 +299,9 @@ class TSymbolTable : angle::NonCopyable
// 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 atBuiltInLevel() const
- {
- return currentLevel() <= LAST_BUILTIN_LEVEL;
- }
- bool atGlobalLevel() const
- {
- return currentLevel() <= GLOBAL_LEVEL;
- }
+ bool isEmpty() const { return table.empty(); }
+ bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
+ bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
void push()
{
table.push_back(new TSymbolTableLevel);
@@ -363,87 +317,159 @@ 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);
- }
-
- bool insertConstInt(ESymbolLevel level, const char *name, int value)
+ // 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,
+ TExtension ext,
+ const char *name,
+ const TType &type);
+ TVariable *insertStructType(ESymbolLevel level, TStructure *str);
+ TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level,
+ TExtension ext,
+ const TString *name);
+
+ bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
{
- TVariable *constant = new TVariable(
- NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+ TVariable *constant =
+ new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray[0].setIConst(value);
constant->shareConstPointer(unionArray);
return insert(level, constant);
}
- bool insertConstIntExt(ESymbolLevel level, const char *ext, const char *name, int value)
+ bool insertConstIntExt(ESymbolLevel level,
+ TExtension ext,
+ const char *name,
+ int value,
+ TPrecision precision)
{
TVariable *constant =
- new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+ new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray[0].setIConst(value);
constant->shareConstPointer(unionArray);
return insert(level, ext, constant);
}
- void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0);
-
- void insertBuiltIn(ESymbolLevel level, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
+ bool insertConstIvec3(ESymbolLevel level,
+ const char *name,
+ const std::array<int, 3> &values,
+ TPrecision precision)
{
- insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
- }
+ TVariable *constantIvec3 =
+ new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 3));
- void insertBuiltIn(ESymbolLevel level, const char *ext, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
- {
+ TConstantUnion *unionArray = new TConstantUnion[3];
+ for (size_t index = 0u; index < 3u; ++index)
+ {
+ unionArray[index].setIConst(values[index]);
+ }
+ constantIvec3->shareConstPointer(unionArray);
+
+ return insert(level, constantIvec3);
+ }
+
+ void insertBuiltIn(ESymbolLevel level,
+ TOperator op,
+ TExtension ext,
+ const TType *rvalue,
+ const char *name,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0);
+
+ void insertBuiltIn(ESymbolLevel level,
+ const TType *rvalue,
+ const char *name,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0)
+ {
+ insertUnmangledBuiltInName(name, level);
+ insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3,
+ ptype4, ptype5);
+ }
+
+ void insertBuiltIn(ESymbolLevel level,
+ TExtension ext,
+ const TType *rvalue,
+ const char *name,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0)
+ {
+ insertUnmangledBuiltInName(name, level);
insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
}
- void insertBuiltIn(ESymbolLevel level, TOperator op, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
- {
- insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
- }
+ void insertBuiltInOp(ESymbolLevel level,
+ TOperator op,
+ const TType *rvalue,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0);
+
+ void insertBuiltInOp(ESymbolLevel level,
+ TOperator op,
+ TExtension ext,
+ const TType *rvalue,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0);
+
+ void insertBuiltInFunctionNoParameters(ESymbolLevel level,
+ TOperator op,
+ const TType *rvalue,
+ const char *name);
+
+ void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
+ TExtension ext,
+ TOperator op,
+ const TType *rvalue,
+ const char *name);
+
+ TSymbol *find(const TString &name,
+ int shaderVersion,
+ bool *builtIn = nullptr,
+ bool *sameScope = nullptr) const;
+
+ TSymbol *findGlobal(const TString &name) const;
- TSymbol *find(const TString &name, int shaderVersion,
- bool *builtIn = NULL, bool *sameScope = NULL) const;
TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
-
+
+ TSymbol *findBuiltIn(const TString &name, int shaderVersion, bool includeGLSLBuiltins) const;
+
TSymbolTableLevel *getOuterLevel()
{
assert(currentLevel() >= 1);
return table[currentLevel() - 1];
}
- void dump(TInfoSink &infoSink) const;
-
- bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
+ void setDefaultPrecision(TBasicType type, TPrecision prec)
{
- if (!SupportsPrecision(type.type))
- return false;
- if (type.type == EbtUInt)
- return false; // ESSL 3.00.4 section 4.5.4
- if (type.isAggregate())
- return false; // Not allowed to set for aggregate types
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
// Uses map operator [], overwrites the current value
- (*precisionStack[indexOfLastElement])[type.type] = prec;
- return true;
+ (*precisionStack[indexOfLastElement])[type] = prec;
}
// Searches down the precisionStack for a precision qualifier
@@ -454,7 +480,8 @@ class TSymbolTable : angle::NonCopyable
// "invariant varying_name;".
void addInvariantVarying(const std::string &originalName)
{
- mInvariantVaryings.insert(originalName);
+ ASSERT(atGlobalLevel());
+ table[currentLevel()]->addInvariantVarying(originalName);
}
// If this returns false, the varying could still be invariant
// if it is set as invariant during the varying variable
@@ -462,32 +489,57 @@ class TSymbolTable : angle::NonCopyable
// variable's type, not here.
bool isVaryingInvariant(const std::string &originalName) const
{
- return (mGlobalInvariant ||
- mInvariantVaryings.count(originalName) > 0);
+ ASSERT(atGlobalLevel());
+ return table[currentLevel()]->isVaryingInvariant(originalName);
}
- void setGlobalInvariant() { mGlobalInvariant = true; }
- bool getGlobalInvariant() const { return mGlobalInvariant; }
-
- static int nextUniqueId()
+ void setGlobalInvariant(bool invariant)
{
- return ++uniqueIdCounter;
+ ASSERT(atGlobalLevel());
+ table[currentLevel()]->setGlobalInvariant(invariant);
}
+ const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
+
+ // The empty symbol id is shared between all empty string ("") symbols. They are used in the
+ // AST for unused function parameters and struct type declarations that don't declare a
+ // variable, for example.
+ const TSymbolUniqueId &getEmptySymbolId() { return mEmptySymbolId; }
+
+ // Checks whether there is a built-in accessible by a shader with the specified version.
+ bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion);
+
private:
- ESymbolLevel currentLevel() const
+ friend class TSymbolUniqueId;
+ int nextUniqueIdValue() { return ++mUniqueIdCounter; }
+
+ 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, TExtension ext, TSymbol *symbol)
{
- return static_cast<ESymbolLevel>(table.size() - 1);
+ 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);
+
+ bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level);
+
std::vector<TSymbolTableLevel *> table;
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
- std::vector< PrecisionStackLevel *> precisionStack;
+ std::vector<PrecisionStackLevel *> precisionStack;
- std::set<std::string> mInvariantVaryings;
- bool mGlobalInvariant;
+ int mUniqueIdCounter;
- static int uniqueIdCounter;
+ const TSymbolUniqueId mEmptySymbolId;
};
-#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_