From 0a7aebadfbb3534284546aa3ca8612314c08f136 Mon Sep 17 00:00:00 2001 From: Miguel Costa Date: Tue, 26 Jun 2018 16:56:45 +0200 Subject: Update ANGLE to chromium/3280 Change-Id: I0802c0d7486f772d361f87a544d6c5af937f4ca1 Reviewed-by: Friedemann Kleint --- .../angle/src/compiler/translator/SymbolTable.h | 494 ++++++++++++--------- 1 file changed, 273 insertions(+), 221 deletions(-) (limited to 'src/3rdparty/angle/src/compiler/translator/SymbolTable.h') 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 #include #include #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 ¶metersSource); + 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 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 tLevel; + typedef TUnorderedMap tLevel; typedef tLevel::const_iterator const_iterator; typedef const tLevel::value_type tLevelPair; typedef std::pair 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 mInvariantVaryings; + bool mGlobalInvariant; + + private: + std::set 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 &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(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(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(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 table; typedef TMap PrecisionStackLevel; - std::vector< PrecisionStackLevel *> precisionStack; + std::vector precisionStack; - std::set mInvariantVaryings; - bool mGlobalInvariant; + int mUniqueIdCounter; - static int uniqueIdCounter; + const TSymbolUniqueId mEmptySymbolId; }; -#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ -- cgit v1.2.3