| // | |
| // 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_ |