1 // 2 // Copyright 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 isFunction()44 bool isFunction() const { return mSymbolClass == SymbolClass::Function; } isVariable()45 bool isVariable() const { return mSymbolClass == SymbolClass::Variable; } isStruct()46 bool isStruct() const { return mSymbolClass == SymbolClass::Struct; } isInterfaceBlock()47 bool isInterfaceBlock() const { return mSymbolClass == SymbolClass::InterfaceBlock; } 48 uniqueId()49 const TSymbolUniqueId &uniqueId() const { return mUniqueId; } symbolType()50 SymbolType symbolType() const { return mSymbolType; } extension()51 TExtension extension() const { return mExtension; } 52 53 protected: TSymbol(const TSymbolUniqueId & id,const ImmutableString & name,SymbolType symbolType,TExtension extension,SymbolClass symbolClass)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 getType()89 const TType &getType() const { return *mType; } 90 getConstPointer()91 const TConstantUnion *getConstPointer() const { return unionArray; } 92 shareConstPointer(const TConstantUnion * constArray)93 void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } 94 95 // Note: only to be used for built-in variables with autogenerated ids! TVariable(const TSymbolUniqueId & id,const ImmutableString & name,SymbolType symbolType,TExtension extension,const TType * type)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 setAtGlobalScope(bool atGlobalScope)127 void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; } 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 blockStorage()159 TLayoutBlockStorage blockStorage() const { return mBlockStorage; } blockBinding()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. createVariableTParameter182 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 ¶metersSource); 209 getFunctionMangledName()210 ImmutableString getFunctionMangledName() const 211 { 212 ASSERT(symbolType() != SymbolType::BuiltIn); 213 if (mMangledName.empty()) 214 { 215 mMangledName = buildMangledName(); 216 } 217 return mMangledName; 218 } 219 getReturnType()220 const TType &getReturnType() const { return *returnType; } 221 getBuiltInOp()222 TOperator getBuiltInOp() const { return mOp; } 223 setDefined()224 void setDefined() { defined = true; } isDefined()225 bool isDefined() { return defined; } setHasPrototypeDeclaration()226 void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; } hasPrototypeDeclaration()227 bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } 228 getParamCount()229 size_t getParamCount() const { return mParamCount; } getParam(size_t i)230 const TVariable *getParam(size_t i) const { return mParameters[i]; } 231 isKnownToNotHaveSideEffects()232 bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } 233 234 bool isMain() const; 235 bool isImageFunction() const; 236 bool isAtomicCounterFunction() const; 237 bool hasSamplerInStructOrArrayParams() const; 238 bool hasSamplerInStructOrArrayOfArrayParams() const; 239 240 // Note: Only to be used for static built-in functions! TFunction(const TSymbolUniqueId & id,const ImmutableString & name,TExtension extension,const TVariable * const * parameters,size_t paramCount,const TType * retType,TOperator op,bool knownToNotHaveSideEffects)241 constexpr TFunction(const TSymbolUniqueId &id, 242 const ImmutableString &name, 243 TExtension extension, 244 const TVariable *const *parameters, 245 size_t paramCount, 246 const TType *retType, 247 TOperator op, 248 bool knownToNotHaveSideEffects) 249 : TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::Function), 250 mParametersVector(nullptr), 251 mParameters(parameters), 252 mParamCount(paramCount), 253 returnType(retType), 254 mMangledName(nullptr), 255 mOp(op), 256 defined(false), 257 mHasPrototypeDeclaration(false), 258 mKnownToNotHaveSideEffects(knownToNotHaveSideEffects) 259 {} 260 261 private: 262 ImmutableString buildMangledName() const; 263 264 typedef TVector<const TVariable *> TParamVector; 265 TParamVector *mParametersVector; 266 const TVariable *const *mParameters; 267 size_t mParamCount; 268 const TType *const returnType; 269 mutable ImmutableString mMangledName; 270 const TOperator mOp; // Only set for built-ins 271 bool defined; 272 bool mHasPrototypeDeclaration; 273 bool mKnownToNotHaveSideEffects; 274 }; 275 276 } // namespace sh 277 278 #endif // COMPILER_TRANSLATOR_SYMBOL_H_ 279