| // |
| // Copyright 2017 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // Symbol.h: Symbols representing variables, functions, structures and interface blocks. |
| // |
| |
| #ifndef COMPILER_TRANSLATOR_SYMBOL_H_ |
| #define COMPILER_TRANSLATOR_SYMBOL_H_ |
| |
| #include "common/angleutils.h" |
| #include "compiler/translator/ExtensionBehavior.h" |
| #include "compiler/translator/ImmutableString.h" |
| #include "compiler/translator/IntermNode.h" |
| #include "compiler/translator/SymbolUniqueId.h" |
| |
| namespace sh |
| { |
| |
| class TSymbolTable; |
| |
| // Symbol base class. (Can build functions or variables out of these...) |
| class TSymbol : angle::NonCopyable |
| { |
| public: |
| POOL_ALLOCATOR_NEW_DELETE |
| TSymbol(TSymbolTable *symbolTable, |
| const ImmutableString &name, |
| SymbolType symbolType, |
| SymbolClass symbolClass, |
| TExtension extension = TExtension::UNDEFINED); |
| |
| // Note that we can't have a virtual destructor in order to support constexpr symbols. Data is |
| // either statically allocated or pool allocated. |
| ~TSymbol() = default; |
| |
| // Calling name() for empty symbols (symbolType == SymbolType::Empty) generates a similar name |
| // as for internal variables. |
| ImmutableString name() const; |
| // Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty). |
| ImmutableString getMangledName() const; |
| |
| bool isFunction() const { return mSymbolClass == SymbolClass::Function; } |
| bool isVariable() const { return mSymbolClass == SymbolClass::Variable; } |
| bool isStruct() const { return mSymbolClass == SymbolClass::Struct; } |
| bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; } |
| |
| const TSymbolUniqueId &uniqueId() const { return mUniqueId; } |
| SymbolType symbolType() const { return mSymbolType; } |
| TExtension extension() const { return mExtension; } |
| |
| protected: |
| constexpr TSymbol(const TSymbolUniqueId &id, |
| const ImmutableString &name, |
| SymbolType symbolType, |
| TExtension extension, |
| SymbolClass symbolClass) |
| : mName(name), |
| mUniqueId(id), |
| mSymbolType(symbolType), |
| mExtension(extension), |
| mSymbolClass(symbolClass) |
| {} |
| |
| const ImmutableString mName; |
| |
| private: |
| const TSymbolUniqueId mUniqueId; |
| const SymbolType mSymbolType; |
| const TExtension mExtension; |
| |
| // We use this instead of having virtual functions for querying the class in order to support |
| // constexpr symbols. |
| const SymbolClass mSymbolClass; |
| }; |
| |
| // Variable. |
| // May store the value of a constant variable of any type (float, int, bool or struct). |
| class TVariable : public TSymbol |
| { |
| public: |
| TVariable(TSymbolTable *symbolTable, |
| const ImmutableString &name, |
| const TType *type, |
| SymbolType symbolType, |
| TExtension ext = TExtension::UNDEFINED); |
| |
| const TType &getType() const { return *mType; } |
| |
| const TConstantUnion *getConstPointer() const { return unionArray; } |
| |
| void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } |
| |
| // Note: only to be used for built-in variables with autogenerated ids! |
| constexpr TVariable(const TSymbolUniqueId &id, |
| const ImmutableString &name, |
| SymbolType symbolType, |
| TExtension extension, |
| const TType *type) |
| : TSymbol(id, name, symbolType, extension, SymbolClass::Variable), |
| mType(type), |
| unionArray(nullptr) |
| {} |
| |
| private: |
| const TType *mType; |
| const TConstantUnion *unionArray; |
| }; |
| |
| // Struct type. |
| class TStructure : public TSymbol, public TFieldListCollection |
| { |
| public: |
| TStructure(TSymbolTable *symbolTable, |
| const ImmutableString &name, |
| const TFieldList *fields, |
| SymbolType symbolType); |
| |
| // The char arrays passed in must be pool allocated or static. |
| void createSamplerSymbols(const char *namePrefix, |
| const TString &apiNamePrefix, |
| TVector<const TVariable *> *outputSymbols, |
| TMap<const TVariable *, TString> *outputSymbolsToAPINames, |
| TSymbolTable *symbolTable) const; |
| |
| void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; } |
| bool atGlobalScope() const { return mAtGlobalScope; } |
| |
| private: |
| friend class TSymbolTable; |
| // For creating built-in structs. |
| TStructure(const TSymbolUniqueId &id, |
| const ImmutableString &name, |
| TExtension extension, |
| const TFieldList *fields); |
| |
| // 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 ImmutableString &name); |
| |
| bool mAtGlobalScope; |
| }; |
| |
| // Interface block. Note that this contains the block name, not the instance name. Interface block |
| // instances are stored as TVariable. |
| class TInterfaceBlock : public TSymbol, public TFieldListCollection |
| { |
| public: |
| TInterfaceBlock(TSymbolTable *symbolTable, |
| const ImmutableString &name, |
| const TFieldList *fields, |
| const TLayoutQualifier &layoutQualifier, |
| SymbolType symbolType, |
| TExtension extension = TExtension::UNDEFINED); |
| |
| TLayoutBlockStorage blockStorage() const { return mBlockStorage; } |
| int blockBinding() const { return mBinding; } |
| |
| private: |
| friend class TSymbolTable; |
| // For creating built-in interface blocks. |
| TInterfaceBlock(const TSymbolUniqueId &id, |
| const ImmutableString &name, |
| TExtension extension, |
| const TFieldList *fields); |
| |
| TLayoutBlockStorage mBlockStorage; |
| int mBinding; |
| |
| // Note that we only record matrix packing on a per-field granularity. |
| }; |
| |
| // Parameter class used for parsing user-defined function parameters. |
| struct TParameter |
| { |
| // Destructively converts to TVariable. |
| // This method resets name and type to nullptrs to make sure |
| // their content cannot be modified after the call. |
| const TVariable *createVariable(TSymbolTable *symbolTable) |
| { |
| const ImmutableString constName(name); |
| const TType *constType = type; |
| name = nullptr; |
| type = nullptr; |
| return new TVariable(symbolTable, constName, constType, |
| constName.empty() ? SymbolType::Empty : SymbolType::UserDefined); |
| } |
| |
| const char *name; // either pool allocated or static. |
| TType *type; |
| }; |
| |
| // The function sub-class of a symbol. |
| class TFunction : public TSymbol |
| { |
| public: |
| // User-defined function |
| TFunction(TSymbolTable *symbolTable, |
| const ImmutableString &name, |
| SymbolType symbolType, |
| const TType *retType, |
| bool knownToNotHaveSideEffects); |
| |
| void addParameter(const TVariable *p); |
| void shareParameters(const TFunction ¶metersSource); |
| |
| ImmutableString getFunctionMangledName() const |
| { |
| ASSERT(symbolType() != SymbolType::BuiltIn); |
| if (mMangledName.empty()) |
| { |
| mMangledName = buildMangledName(); |
| } |
| return mMangledName; |
| } |
| |
| const TType &getReturnType() const { return *returnType; } |
| |
| TOperator getBuiltInOp() const { return mOp; } |
| |
| void setDefined() { defined = true; } |
| bool isDefined() { return defined; } |
| void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; } |
| bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } |
| |
| size_t getParamCount() const { return mParamCount; } |
| const TVariable *getParam(size_t i) const { return mParameters[i]; } |
| |
| bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } |
| |
| bool isMain() const; |
| bool isImageFunction() const; |
| bool isAtomicCounterFunction() const; |
| bool hasSamplerInStructOrArrayParams() const; |
| bool hasSamplerInStructOrArrayOfArrayParams() const; |
| |
| // Note: Only to be used for static built-in functions! |
| constexpr TFunction(const TSymbolUniqueId &id, |
| const ImmutableString &name, |
| TExtension extension, |
| const TVariable *const *parameters, |
| size_t paramCount, |
| const TType *retType, |
| TOperator op, |
| bool knownToNotHaveSideEffects) |
| : TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::Function), |
| mParametersVector(nullptr), |
| mParameters(parameters), |
| mParamCount(paramCount), |
| returnType(retType), |
| mMangledName(nullptr), |
| mOp(op), |
| defined(false), |
| mHasPrototypeDeclaration(false), |
| mKnownToNotHaveSideEffects(knownToNotHaveSideEffects) |
| {} |
| |
| private: |
| ImmutableString buildMangledName() const; |
| |
| typedef TVector<const TVariable *> TParamVector; |
| TParamVector *mParametersVector; |
| const TVariable *const *mParameters; |
| size_t mParamCount; |
| const TType *const returnType; |
| mutable ImmutableString mMangledName; |
| const TOperator mOp; // Only set for built-ins |
| bool defined; |
| bool mHasPrototypeDeclaration; |
| bool mKnownToNotHaveSideEffects; |
| }; |
| |
| } // namespace sh |
| |
| #endif // COMPILER_TRANSLATOR_SYMBOL_H_ |