SymbolTable.h (13489B)
1 // 2 // Copyright 2002 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 7 #ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_ 8 #define COMPILER_TRANSLATOR_SYMBOLTABLE_H_ 9 10 // 11 // Symbol table for parsing. Has these design characteristics: 12 // 13 // * Same symbol table can be used to compile many shaders, to preserve 14 // effort of creating and loading with the large numbers of built-in 15 // symbols. 16 // 17 // * Name mangling will be used to give each function a unique name 18 // so that symbol table lookups are never ambiguous. This allows 19 // a simpler symbol table structure. 20 // 21 // * Pushing and popping of scope, so symbol table will really be a stack 22 // of symbol tables. Searched from the top, with new inserts going into 23 // the top. 24 // 25 // * Constants: Compile time constant symbols will keep their values 26 // in the symbol table. The parser can substitute constants at parse 27 // time, including doing constant folding and constant propagation. 28 // 29 // * No temporaries: Temporaries made from operations (+, --, .xy, etc.) 30 // are tracked in the intermediate representation, not the symbol table. 31 // 32 33 #include <limits> 34 #include <memory> 35 #include <set> 36 37 #include "common/angleutils.h" 38 #include "compiler/translator/ExtensionBehavior.h" 39 #include "compiler/translator/ImmutableString.h" 40 #include "compiler/translator/InfoSink.h" 41 #include "compiler/translator/IntermNode.h" 42 #include "compiler/translator/Symbol.h" 43 #include "compiler/translator/SymbolTable_autogen.h" 44 45 enum class Shader : uint8_t 46 { 47 ALL, 48 FRAGMENT, // GL_FRAGMENT_SHADER 49 VERTEX, // GL_VERTEX_SHADER 50 COMPUTE, // GL_COMPUTE_SHADER 51 GEOMETRY, // GL_GEOMETRY_SHADER 52 GEOMETRY_EXT, // GL_GEOMETRY_SHADER_EXT 53 TESS_CONTROL_EXT, // GL_TESS_CONTROL_SHADER_EXT 54 TESS_EVALUATION_EXT, // GL_TESS_EVALUATION_SHADER_EXT 55 NOT_COMPUTE 56 }; 57 58 namespace sh 59 { 60 61 struct UnmangledBuiltIn 62 { 63 constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {} 64 65 TExtension extension; 66 }; 67 68 using VarPointer = TSymbol *(TSymbolTableBase::*); 69 using ValidateExtension = int ShBuiltInResources::*; 70 71 enum class Spec : uint8_t 72 { 73 GLSL, 74 ESSL 75 }; 76 77 constexpr uint16_t kESSL1Only = 100; 78 // Some built-ins from backend shader languages are made available internally to ESSL for use in 79 // tree transformations. This (invalid) shader version is used to select those built-ins. This 80 // value needs to be larger than all other shader versions. 81 constexpr uint16_t kESSLInternalBackendBuiltIns = 0x3FFF; 82 83 // The version assigned to |kESSLInternalBackendBuiltIns| should be good until OpenGL 20.0! 84 static_assert(kESSLInternalBackendBuiltIns > 2000, 85 "Accidentally exposing internal backend built-ins in OpenGL"); 86 87 static_assert(offsetof(ShBuiltInResources, OES_standard_derivatives) != 0, 88 "Update SymbolTable extension logic"); 89 90 #define EXT_INDEX(Ext) (offsetof(ShBuiltInResources, Ext) / sizeof(int)) 91 92 class SymbolRule 93 { 94 public: 95 const TSymbol *get(ShShaderSpec shaderSpec, 96 int shaderVersion, 97 sh::GLenum shaderType, 98 const ShBuiltInResources &resources, 99 const TSymbolTableBase &symbolTable) const; 100 101 template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T> 102 constexpr static SymbolRule Get(T value); 103 104 private: 105 constexpr SymbolRule(Spec spec, 106 int version, 107 Shader shaders, 108 size_t extensionIndex, 109 const TSymbol *symbol); 110 111 constexpr SymbolRule(Spec spec, 112 int version, 113 Shader shaders, 114 size_t extensionIndex, 115 VarPointer resourceVar); 116 117 union SymbolOrVar 118 { 119 constexpr SymbolOrVar(const TSymbol *symbolIn) : symbol(symbolIn) {} 120 constexpr SymbolOrVar(VarPointer varIn) : var(varIn) {} 121 122 const TSymbol *symbol; 123 VarPointer var; 124 }; 125 126 uint16_t mIsDesktop : 1; 127 uint16_t mIsVar : 1; 128 uint16_t mVersion : 14; 129 uint8_t mShaders; 130 uint8_t mExtensionIndex; 131 SymbolOrVar mSymbolOrVar; 132 }; 133 134 constexpr SymbolRule::SymbolRule(Spec spec, 135 int version, 136 Shader shaders, 137 size_t extensionIndex, 138 const TSymbol *symbol) 139 : mIsDesktop(spec == Spec::GLSL ? 1u : 0u), 140 mIsVar(0u), 141 mVersion(static_cast<uint16_t>(version)), 142 mShaders(static_cast<uint8_t>(shaders)), 143 mExtensionIndex(extensionIndex), 144 mSymbolOrVar(symbol) 145 {} 146 147 constexpr SymbolRule::SymbolRule(Spec spec, 148 int version, 149 Shader shaders, 150 size_t extensionIndex, 151 VarPointer resourceVar) 152 : mIsDesktop(spec == Spec::GLSL ? 1u : 0u), 153 mIsVar(1u), 154 mVersion(static_cast<uint16_t>(version)), 155 mShaders(static_cast<uint8_t>(shaders)), 156 mExtensionIndex(extensionIndex), 157 mSymbolOrVar(resourceVar) 158 {} 159 160 template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T> 161 // static 162 constexpr SymbolRule SymbolRule::Get(T value) 163 { 164 static_assert(version < 0x4000u, "version OOR"); 165 static_assert(static_cast<uint8_t>(shaders) < 0xFFu, "shaders OOR"); 166 static_assert(static_cast<uint8_t>(extensionIndex) < 0xFF, "extensionIndex OOR"); 167 return SymbolRule(spec, version, shaders, extensionIndex, value); 168 } 169 170 const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec, 171 int shaderVersion, 172 sh::GLenum shaderType, 173 const ShBuiltInResources &resources, 174 const TSymbolTableBase &symbolTable, 175 const SymbolRule *rules, 176 uint16_t startIndex, 177 uint16_t endIndex); 178 179 class UnmangledEntry 180 { 181 public: 182 template <size_t ESSLExtCount> 183 constexpr UnmangledEntry(const char *name, 184 const std::array<TExtension, ESSLExtCount> &esslExtensions, 185 TExtension glslExtension, 186 int esslVersion, 187 int glslVersion, 188 Shader shaderType); 189 190 bool matches(const ImmutableString &name, 191 ShShaderSpec shaderSpec, 192 int shaderVersion, 193 sh::GLenum shaderType, 194 const TExtensionBehavior &extensions) const; 195 196 private: 197 const char *mName; 198 std::array<TExtension, 2u> mESSLExtensions; 199 TExtension mGLSLExtension; 200 uint8_t mShaderType; 201 uint16_t mESSLVersion; 202 uint16_t mGLSLVersion; 203 }; 204 205 template <size_t ESSLExtCount> 206 constexpr UnmangledEntry::UnmangledEntry(const char *name, 207 const std::array<TExtension, ESSLExtCount> &esslExtensions, 208 TExtension glslExtension, 209 int esslVersion, 210 int glslVersion, 211 Shader shaderType) 212 : mName(name), 213 mESSLExtensions{(ESSLExtCount >= 1) ? esslExtensions[0] : TExtension::UNDEFINED, 214 (ESSLExtCount >= 2) ? esslExtensions[1] : TExtension::UNDEFINED}, 215 mGLSLExtension(glslExtension), 216 mShaderType(static_cast<uint8_t>(shaderType)), 217 mESSLVersion(esslVersion < 0 ? std::numeric_limits<uint16_t>::max() 218 : static_cast<uint16_t>(esslVersion)), 219 mGLSLVersion(glslVersion < 0 ? std::numeric_limits<uint16_t>::max() 220 : static_cast<uint16_t>(glslVersion)) 221 {} 222 223 class TSymbolTable : angle::NonCopyable, TSymbolTableBase 224 { 225 public: 226 TSymbolTable(); 227 // To start using the symbol table after construction: 228 // * initializeBuiltIns() needs to be called. 229 // * push() needs to be called to push the global level. 230 231 ~TSymbolTable(); 232 233 bool isEmpty() const; 234 bool atGlobalLevel() const; 235 236 void push(); 237 void pop(); 238 239 // Declare a non-function symbol at the current scope. Return true in case the declaration was 240 // successful, and false if the declaration failed due to redefinition. 241 bool declare(TSymbol *symbol); 242 243 // Only used to declare internal variables. 244 bool declareInternal(TSymbol *symbol); 245 246 // Functions are always declared at global scope. 247 void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName); 248 249 // These return the TFunction pointer to keep using to refer to this function. 250 const TFunction *markFunctionHasPrototypeDeclaration(const ImmutableString &mangledName, 251 bool *hadPrototypeDeclarationOut) const; 252 const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function, 253 bool *wasDefinedOut) const; 254 255 // Return false if the gl_in array size has already been initialized with a mismatching value. 256 bool setGlInArraySize(unsigned int inputArraySize); 257 TVariable *getGlInVariableWithArraySize() const; 258 259 const TVariable *gl_FragData() const; 260 const TVariable *gl_SecondaryFragDataEXT() const; 261 262 void markStaticRead(const TVariable &variable); 263 void markStaticWrite(const TVariable &variable); 264 265 // Note: Should not call this for constant variables. 266 bool isStaticallyUsed(const TVariable &variable) const; 267 268 // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString 269 // with a reference to a short-lived char * is fine to pass here. 270 const TSymbol *find(const ImmutableString &name, int shaderVersion) const; 271 272 const TSymbol *findUserDefined(const ImmutableString &name) const; 273 274 TFunction *findUserDefinedFunction(const ImmutableString &name) const; 275 276 const TSymbol *findGlobal(const ImmutableString &name) const; 277 const TSymbol *findGlobalWithConversion(const std::vector<ImmutableString> &names) const; 278 279 const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const; 280 const TSymbol *findBuiltInWithConversion(const std::vector<ImmutableString> &names, 281 int shaderVersion) const; 282 283 void setDefaultPrecision(TBasicType type, TPrecision prec); 284 285 // Searches down the precisionStack for a precision qualifier 286 // for the specified TBasicType 287 TPrecision getDefaultPrecision(TBasicType type) const; 288 289 // This records invariant varyings declared through "invariant varying_name;". 290 void addInvariantVarying(const TVariable &variable); 291 292 // If this returns false, the varying could still be invariant if it is set as invariant during 293 // the varying variable declaration - this piece of information is stored in the variable's 294 // type, not here. 295 bool isVaryingInvariant(const TVariable &variable) const; 296 297 void setGlobalInvariant(bool invariant); 298 299 const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); } 300 301 // Gets the built-in accessible by a shader with the specified version, if any. 302 bool isUnmangledBuiltInName(const ImmutableString &name, 303 int shaderVersion, 304 const TExtensionBehavior &extensions) const; 305 306 void initializeBuiltIns(sh::GLenum type, 307 ShShaderSpec spec, 308 const ShBuiltInResources &resources); 309 void clearCompilationResults(); 310 311 ShShaderSpec getShaderSpec() const { return mShaderSpec; } 312 313 private: 314 friend class TSymbolUniqueId; 315 316 struct VariableMetadata 317 { 318 VariableMetadata(); 319 bool staticRead; 320 bool staticWrite; 321 bool invariant; 322 }; 323 324 int nextUniqueIdValue(); 325 326 class TSymbolTableLevel; 327 328 void initSamplerDefaultPrecision(TBasicType samplerType); 329 330 void initializeBuiltInVariables(sh::GLenum shaderType, 331 ShShaderSpec spec, 332 const ShBuiltInResources &resources); 333 334 VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable); 335 336 std::vector<std::unique_ptr<TSymbolTableLevel>> mTable; 337 338 // There's one precision stack level for predefined precisions and then one level for each scope 339 // in table. 340 typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; 341 std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack; 342 343 bool mGlobalInvariant; 344 345 int mUniqueIdCounter; 346 347 static const int kLastBuiltInId; 348 349 sh::GLenum mShaderType; 350 ShShaderSpec mShaderSpec; 351 ShBuiltInResources mResources; 352 353 // Indexed by unique id. Map instead of vector since the variables are fairly sparse. 354 std::map<int, VariableMetadata> mVariableMetadata; 355 356 // Store gl_in variable with its array size once the array size can be determined. The array 357 // size can also be checked against latter input primitive type declaration. 358 TVariable *mGlInVariableWithArraySize; 359 }; 360 361 } // namespace sh 362 363 #endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_