| 1 | // |
| 2 | // Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. |
| 3 | // Use of this source code is governed by a BSD-style license that can be |
| 4 | // found in the LICENSE file. |
| 5 | // |
| 6 | // Symbol.h: Symbols representing variables, functions, structures and interface blocks. |
| 7 | // |
| 8 | |
| 9 | #ifndef COMPILER_TRANSLATOR_SYMBOL_H_ |
| 10 | #define COMPILER_TRANSLATOR_SYMBOL_H_ |
| 11 | |
| 12 | #include "common/angleutils.h" |
| 13 | #include "compiler/translator/ExtensionBehavior.h" |
| 14 | #include "compiler/translator/ImmutableString.h" |
| 15 | #include "compiler/translator/IntermNode.h" |
| 16 | #include "compiler/translator/SymbolUniqueId.h" |
| 17 | |
| 18 | namespace sh |
| 19 | { |
| 20 | |
| 21 | class TSymbolTable; |
| 22 | |
| 23 | // Symbol base class. (Can build functions or variables out of these...) |
| 24 | class TSymbol : angle::NonCopyable |
| 25 | { |
| 26 | public: |
| 27 | POOL_ALLOCATOR_NEW_DELETE |
| 28 | TSymbol(TSymbolTable *symbolTable, |
| 29 | const ImmutableString &name, |
| 30 | SymbolType symbolType, |
| 31 | SymbolClass symbolClass, |
| 32 | TExtension extension = TExtension::UNDEFINED); |
| 33 | |
| 34 | // Note that we can't have a virtual destructor in order to support constexpr symbols. Data is |
| 35 | // either statically allocated or pool allocated. |
| 36 | ~TSymbol() = default; |
| 37 | |
| 38 | // Calling name() for empty symbols (symbolType == SymbolType::Empty) generates a similar name |
| 39 | // as for internal variables. |
| 40 | ImmutableString name() const; |
| 41 | // Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty). |
| 42 | ImmutableString getMangledName() const; |
| 43 | |
| 44 | bool isFunction() const { return mSymbolClass == SymbolClass::Function; } |
| 45 | bool isVariable() const { return mSymbolClass == SymbolClass::Variable; } |
| 46 | bool isStruct() const { return mSymbolClass == SymbolClass::Struct; } |
| 47 | bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; } |
| 48 | |
| 49 | const TSymbolUniqueId &uniqueId() const { return mUniqueId; } |
| 50 | SymbolType symbolType() const { return mSymbolType; } |
| 51 | TExtension extension() const { return mExtension; } |
| 52 | |
| 53 | protected: |
| 54 | constexpr TSymbol(const TSymbolUniqueId &id, |
| 55 | const ImmutableString &name, |
| 56 | SymbolType symbolType, |
| 57 | TExtension extension, |
| 58 | SymbolClass symbolClass) |
| 59 | : mName(name), |
| 60 | mUniqueId(id), |
| 61 | mSymbolType(symbolType), |
| 62 | mExtension(extension), |
| 63 | mSymbolClass(symbolClass) |
| 64 | {} |
| 65 | |
| 66 | const ImmutableString mName; |
| 67 | |
| 68 | private: |
| 69 | const TSymbolUniqueId mUniqueId; |
| 70 | const SymbolType mSymbolType; |
| 71 | const TExtension mExtension; |
| 72 | |
| 73 | // We use this instead of having virtual functions for querying the class in order to support |
| 74 | // constexpr symbols. |
| 75 | const SymbolClass mSymbolClass; |
| 76 | }; |
| 77 | |
| 78 | // Variable. |
| 79 | // May store the value of a constant variable of any type (float, int, bool or struct). |
| 80 | class TVariable : public TSymbol |
| 81 | { |
| 82 | public: |
| 83 | TVariable(TSymbolTable *symbolTable, |
| 84 | const ImmutableString &name, |
| 85 | const TType *type, |
| 86 | SymbolType symbolType, |
| 87 | TExtension ext = TExtension::UNDEFINED); |
| 88 | |
| 89 | const TType &getType() const { return *mType; } |
| 90 | |
| 91 | const TConstantUnion *getConstPointer() const { return unionArray; } |
| 92 | |
| 93 | void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } |
| 94 | |
| 95 | // Note: only to be used for built-in variables with autogenerated ids! |
| 96 | constexpr TVariable(const TSymbolUniqueId &id, |
| 97 | const ImmutableString &name, |
| 98 | SymbolType symbolType, |
| 99 | TExtension extension, |
| 100 | const TType *type) |
| 101 | : TSymbol(id, name, symbolType, extension, SymbolClass::Variable), |
| 102 | mType(type), |
| 103 | unionArray(nullptr) |
| 104 | {} |
| 105 | |
| 106 | private: |
| 107 | const TType *mType; |
| 108 | const TConstantUnion *unionArray; |
| 109 | }; |
| 110 | |
| 111 | // Struct type. |
| 112 | class TStructure : public TSymbol, public TFieldListCollection |
| 113 | { |
| 114 | public: |
| 115 | TStructure(TSymbolTable *symbolTable, |
| 116 | const ImmutableString &name, |
| 117 | const TFieldList *fields, |
| 118 | SymbolType symbolType); |
| 119 | |
| 120 | // The char arrays passed in must be pool allocated or static. |
| 121 | void createSamplerSymbols(const char *namePrefix, |
| 122 | const TString &apiNamePrefix, |
| 123 | TVector<const TVariable *> *outputSymbols, |
| 124 | TMap<const TVariable *, TString> *outputSymbolsToAPINames, |
| 125 | TSymbolTable *symbolTable) const; |
| 126 | |
| 127 | void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; } |
| 128 | bool atGlobalScope() const { return mAtGlobalScope; } |
| 129 | |
| 130 | private: |
| 131 | friend class TSymbolTable; |
| 132 | // For creating built-in structs. |
| 133 | TStructure(const TSymbolUniqueId &id, |
| 134 | const ImmutableString &name, |
| 135 | TExtension extension, |
| 136 | const TFieldList *fields); |
| 137 | |
| 138 | // TODO(zmo): Find a way to get rid of the const_cast in function |
| 139 | // setName(). At the moment keep this function private so only |
| 140 | // friend class RegenerateStructNames may call it. |
| 141 | friend class RegenerateStructNames; |
| 142 | void setName(const ImmutableString &name); |
| 143 | |
| 144 | bool mAtGlobalScope; |
| 145 | }; |
| 146 | |
| 147 | // Interface block. Note that this contains the block name, not the instance name. Interface block |
| 148 | // instances are stored as TVariable. |
| 149 | class TInterfaceBlock : public TSymbol, public TFieldListCollection |
| 150 | { |
| 151 | public: |
| 152 | TInterfaceBlock(TSymbolTable *symbolTable, |
| 153 | const ImmutableString &name, |
| 154 | const TFieldList *fields, |
| 155 | const TLayoutQualifier &layoutQualifier, |
| 156 | SymbolType symbolType, |
| 157 | TExtension extension = TExtension::UNDEFINED); |
| 158 | |
| 159 | TLayoutBlockStorage blockStorage() const { return mBlockStorage; } |
| 160 | int blockBinding() const { return mBinding; } |
| 161 | |
| 162 | private: |
| 163 | friend class TSymbolTable; |
| 164 | // For creating built-in interface blocks. |
| 165 | TInterfaceBlock(const TSymbolUniqueId &id, |
| 166 | const ImmutableString &name, |
| 167 | TExtension extension, |
| 168 | const TFieldList *fields); |
| 169 | |
| 170 | TLayoutBlockStorage mBlockStorage; |
| 171 | int mBinding; |
| 172 | |
| 173 | // Note that we only record matrix packing on a per-field granularity. |
| 174 | }; |
| 175 | |
| 176 | // Parameter class used for parsing user-defined function parameters. |
| 177 | struct TParameter |
| 178 | { |
| 179 | // Destructively converts to TVariable. |
| 180 | // This method resets name and type to nullptrs to make sure |
| 181 | // their content cannot be modified after the call. |
| 182 | const TVariable *createVariable(TSymbolTable *symbolTable) |
| 183 | { |
| 184 | const ImmutableString constName(name); |
| 185 | const TType *constType = type; |
| 186 | name = nullptr; |
| 187 | type = nullptr; |
| 188 | return new TVariable(symbolTable, constName, constType, |
| 189 | constName.empty() ? SymbolType::Empty : SymbolType::UserDefined); |
| 190 | } |
| 191 | |
| 192 | const char *name; // either pool allocated or static. |
| 193 | TType *type; |
| 194 | }; |
| 195 | |
| 196 | // The function sub-class of a symbol. |
| 197 | class TFunction : public TSymbol |
| 198 | { |
| 199 | public: |
| 200 | // User-defined function |
| 201 | TFunction(TSymbolTable *symbolTable, |
| 202 | const ImmutableString &name, |
| 203 | SymbolType symbolType, |
| 204 | const TType *retType, |
| 205 | bool knownToNotHaveSideEffects); |
| 206 | |
| 207 | void addParameter(const TVariable *p); |
| 208 | void shareParameters(const TFunction &); |
| 209 | |
| 210 | ImmutableString getFunctionMangledName() const |
| 211 | { |
| 212 | ASSERT(symbolType() != SymbolType::BuiltIn); |
| 213 | if (mMangledName.empty()) |
| 214 | { |
| 215 | mMangledName = buildMangledName(); |
| 216 | } |
| 217 | return mMangledName; |
| 218 | } |
| 219 | |
| 220 | const TType &getReturnType() const { return *returnType; } |
| 221 | |
| 222 | TOperator getBuiltInOp() const { return mOp; } |
| 223 | |
| 224 | void setDefined() { defined = true; } |
| 225 | bool isDefined() { return defined; } |
| 226 | void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; } |
| 227 | bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } |
| 228 | |
| 229 | size_t getParamCount() const { return mParamCount; } |
| 230 | const TVariable *getParam(size_t i) const { return mParameters[i]; } |
| 231 | |
| 232 | bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } |
| 233 | |
| 234 | bool isMain() const; |
| 235 | bool isImageFunction() const; |
| 236 | bool isAtomicCounterFunction() const; |
| 237 | bool hasSamplerInStructParams() const; |
| 238 | |
| 239 | // Note: Only to be used for static built-in functions! |
| 240 | constexpr TFunction(const TSymbolUniqueId &id, |
| 241 | const ImmutableString &name, |
| 242 | TExtension extension, |
| 243 | const TVariable *const *parameters, |
| 244 | size_t paramCount, |
| 245 | const TType *retType, |
| 246 | TOperator op, |
| 247 | bool knownToNotHaveSideEffects) |
| 248 | : TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::Function), |
| 249 | mParametersVector(nullptr), |
| 250 | mParameters(parameters), |
| 251 | mParamCount(paramCount), |
| 252 | returnType(retType), |
| 253 | mMangledName(nullptr), |
| 254 | mOp(op), |
| 255 | defined(false), |
| 256 | mHasPrototypeDeclaration(false), |
| 257 | mKnownToNotHaveSideEffects(knownToNotHaveSideEffects) |
| 258 | {} |
| 259 | |
| 260 | private: |
| 261 | ImmutableString buildMangledName() const; |
| 262 | |
| 263 | typedef TVector<const TVariable *> TParamVector; |
| 264 | TParamVector *mParametersVector; |
| 265 | const TVariable *const *mParameters; |
| 266 | size_t mParamCount; |
| 267 | const TType *const returnType; |
| 268 | mutable ImmutableString mMangledName; |
| 269 | const TOperator mOp; // Only set for built-ins |
| 270 | bool defined; |
| 271 | bool mHasPrototypeDeclaration; |
| 272 | bool mKnownToNotHaveSideEffects; |
| 273 | }; |
| 274 | |
| 275 | } // namespace sh |
| 276 | |
| 277 | #endif // COMPILER_TRANSLATOR_SYMBOL_H_ |
| 278 | |