SymbolTable.cpp (17311B)
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 // Symbol table for parsing. The design principles and most of the functionality are documented in 7 // the header file. 8 // 9 10 #if defined(_MSC_VER) 11 # pragma warning(disable : 4718) 12 #endif 13 14 #include "compiler/translator/SymbolTable.h" 15 16 #include "angle_gl.h" 17 #include "compiler/translator/ImmutableString.h" 18 #include "compiler/translator/IntermNode.h" 19 #include "compiler/translator/StaticType.h" 20 #include "compiler/translator/util.h" 21 22 namespace sh 23 { 24 namespace 25 { 26 bool CheckShaderType(Shader expected, GLenum actual) 27 { 28 switch (expected) 29 { 30 case Shader::ALL: 31 return true; 32 case Shader::FRAGMENT: 33 return actual == GL_FRAGMENT_SHADER; 34 case Shader::VERTEX: 35 return actual == GL_VERTEX_SHADER; 36 case Shader::COMPUTE: 37 return actual == GL_COMPUTE_SHADER; 38 case Shader::GEOMETRY: 39 return actual == GL_GEOMETRY_SHADER; 40 case Shader::GEOMETRY_EXT: 41 return actual == GL_GEOMETRY_SHADER_EXT; 42 case Shader::TESS_CONTROL_EXT: 43 return actual == GL_TESS_CONTROL_SHADER_EXT; 44 case Shader::TESS_EVALUATION_EXT: 45 return actual == GL_TESS_EVALUATION_SHADER_EXT; 46 case Shader::NOT_COMPUTE: 47 return actual != GL_COMPUTE_SHADER; 48 default: 49 UNREACHABLE(); 50 return false; 51 } 52 } 53 54 bool CheckExtension(uint32_t extensionIndex, const ShBuiltInResources &resources) 55 { 56 const int *resourcePtr = reinterpret_cast<const int *>(&resources); 57 return resourcePtr[extensionIndex] > 0; 58 } 59 } // namespace 60 61 class TSymbolTable::TSymbolTableLevel 62 { 63 public: 64 TSymbolTableLevel() = default; 65 66 bool insert(TSymbol *symbol); 67 68 // Insert a function using its unmangled name as the key. 69 void insertUnmangled(TFunction *function); 70 71 TSymbol *find(const ImmutableString &name) const; 72 73 private: 74 using tLevel = TUnorderedMap<ImmutableString, 75 TSymbol *, 76 ImmutableString::FowlerNollVoHash<sizeof(size_t)>>; 77 using tLevelPair = const tLevel::value_type; 78 using tInsertResult = std::pair<tLevel::iterator, bool>; 79 80 tLevel level; 81 }; 82 83 bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol) 84 { 85 // returning true means symbol was added to the table 86 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); 87 return result.second; 88 } 89 90 void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function) 91 { 92 level.insert(tLevelPair(function->name(), function)); 93 } 94 95 TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const 96 { 97 tLevel::const_iterator it = level.find(name); 98 if (it == level.end()) 99 return nullptr; 100 else 101 return (*it).second; 102 } 103 104 TSymbolTable::TSymbolTable() 105 : mGlobalInvariant(false), 106 mUniqueIdCounter(0), 107 mShaderType(GL_FRAGMENT_SHADER), 108 mShaderSpec(SH_GLES2_SPEC), 109 mGlInVariableWithArraySize(nullptr) 110 {} 111 112 TSymbolTable::~TSymbolTable() = default; 113 114 bool TSymbolTable::isEmpty() const 115 { 116 return mTable.empty(); 117 } 118 119 bool TSymbolTable::atGlobalLevel() const 120 { 121 return mTable.size() == 1u; 122 } 123 124 void TSymbolTable::push() 125 { 126 mTable.emplace_back(new TSymbolTableLevel); 127 mPrecisionStack.emplace_back(new PrecisionStackLevel); 128 } 129 130 void TSymbolTable::pop() 131 { 132 mTable.pop_back(); 133 mPrecisionStack.pop_back(); 134 } 135 136 const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration( 137 const ImmutableString &mangledName, 138 bool *hadPrototypeDeclarationOut) const 139 { 140 TFunction *function = findUserDefinedFunction(mangledName); 141 *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration(); 142 function->setHasPrototypeDeclaration(); 143 return function; 144 } 145 146 const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function, 147 bool *wasDefinedOut) const 148 { 149 TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName()); 150 ASSERT(firstDeclaration); 151 // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as 152 // it would have just been put in the symbol table. Otherwise, we're looking up an earlier 153 // occurance. 154 if (function != firstDeclaration) 155 { 156 // The previous declaration should have the same parameters as the function definition 157 // (parameter names may differ). 158 firstDeclaration->shareParameters(*function); 159 } 160 161 *wasDefinedOut = firstDeclaration->isDefined(); 162 firstDeclaration->setDefined(); 163 return firstDeclaration; 164 } 165 166 bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize) 167 { 168 if (mGlInVariableWithArraySize) 169 { 170 return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize; 171 } 172 const TInterfaceBlock *glPerVertex = static_cast<const TInterfaceBlock *>(m_gl_PerVertex); 173 TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create()); 174 glInType->makeArray(inputArraySize); 175 mGlInVariableWithArraySize = 176 new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn, 177 TExtension::EXT_geometry_shader); 178 return true; 179 } 180 181 TVariable *TSymbolTable::getGlInVariableWithArraySize() const 182 { 183 return mGlInVariableWithArraySize; 184 } 185 186 const TVariable *TSymbolTable::gl_FragData() const 187 { 188 return static_cast<const TVariable *>(m_gl_FragData); 189 } 190 191 const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const 192 { 193 return static_cast<const TVariable *>(m_gl_SecondaryFragDataEXT); 194 } 195 196 TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable) 197 { 198 int id = variable.uniqueId().get(); 199 auto iter = mVariableMetadata.find(id); 200 if (iter == mVariableMetadata.end()) 201 { 202 iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first; 203 } 204 return &iter->second; 205 } 206 207 void TSymbolTable::markStaticWrite(const TVariable &variable) 208 { 209 auto metadata = getOrCreateVariableMetadata(variable); 210 metadata->staticWrite = true; 211 } 212 213 void TSymbolTable::markStaticRead(const TVariable &variable) 214 { 215 auto metadata = getOrCreateVariableMetadata(variable); 216 metadata->staticRead = true; 217 } 218 219 bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const 220 { 221 ASSERT(!variable.getConstPointer()); 222 int id = variable.uniqueId().get(); 223 auto iter = mVariableMetadata.find(id); 224 return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite); 225 } 226 227 void TSymbolTable::addInvariantVarying(const TVariable &variable) 228 { 229 ASSERT(atGlobalLevel()); 230 auto metadata = getOrCreateVariableMetadata(variable); 231 metadata->invariant = true; 232 } 233 234 bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const 235 { 236 ASSERT(atGlobalLevel()); 237 if (mGlobalInvariant && (IsShaderOutput(variable.getType().getQualifier()))) 238 { 239 return true; 240 } 241 int id = variable.uniqueId().get(); 242 auto iter = mVariableMetadata.find(id); 243 return iter != mVariableMetadata.end() && iter->second.invariant; 244 } 245 246 void TSymbolTable::setGlobalInvariant(bool invariant) 247 { 248 ASSERT(atGlobalLevel()); 249 mGlobalInvariant = invariant; 250 } 251 252 const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const 253 { 254 const TSymbol *userSymbol = findUserDefined(name); 255 if (userSymbol) 256 { 257 return userSymbol; 258 } 259 260 return findBuiltIn(name, shaderVersion); 261 } 262 263 const TSymbol *TSymbolTable::findUserDefined(const ImmutableString &name) const 264 { 265 int userDefinedLevel = static_cast<int>(mTable.size()) - 1; 266 while (userDefinedLevel >= 0) 267 { 268 const TSymbol *symbol = mTable[userDefinedLevel]->find(name); 269 if (symbol) 270 { 271 return symbol; 272 } 273 userDefinedLevel--; 274 } 275 276 return nullptr; 277 } 278 279 TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const 280 { 281 // User-defined functions are always declared at the global level. 282 ASSERT(!mTable.empty()); 283 return static_cast<TFunction *>(mTable[0]->find(name)); 284 } 285 286 const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const 287 { 288 ASSERT(!mTable.empty()); 289 return mTable[0]->find(name); 290 } 291 292 const TSymbol *TSymbolTable::findGlobalWithConversion( 293 const std::vector<ImmutableString> &names) const 294 { 295 for (const ImmutableString &name : names) 296 { 297 const TSymbol *target = findGlobal(name); 298 if (target != nullptr) 299 return target; 300 } 301 return nullptr; 302 } 303 304 const TSymbol *TSymbolTable::findBuiltInWithConversion(const std::vector<ImmutableString> &names, 305 int shaderVersion) const 306 { 307 for (const ImmutableString &name : names) 308 { 309 const TSymbol *target = findBuiltIn(name, shaderVersion); 310 if (target != nullptr) 311 return target; 312 } 313 return nullptr; 314 } 315 316 bool TSymbolTable::declare(TSymbol *symbol) 317 { 318 ASSERT(!mTable.empty()); 319 // The following built-ins may be redeclared by the shader: gl_ClipDistance, gl_CullDistance and 320 // gl_LastFragData. 321 ASSERT(symbol->symbolType() == SymbolType::UserDefined || 322 (symbol->symbolType() == SymbolType::BuiltIn && IsRedeclarableBuiltIn(symbol->name()))); 323 ASSERT(!symbol->isFunction()); 324 return mTable.back()->insert(symbol); 325 } 326 327 bool TSymbolTable::declareInternal(TSymbol *symbol) 328 { 329 ASSERT(!mTable.empty()); 330 ASSERT(symbol->symbolType() == SymbolType::AngleInternal); 331 ASSERT(!symbol->isFunction()); 332 return mTable.back()->insert(symbol); 333 } 334 335 void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName) 336 { 337 ASSERT(!mTable.empty()); 338 if (insertUnmangledName) 339 { 340 // Insert the unmangled name to detect potential future redefinition as a variable. 341 mTable[0]->insertUnmangled(function); 342 } 343 mTable[0]->insert(function); 344 } 345 346 void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec) 347 { 348 int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1; 349 // Uses map operator [], overwrites the current value 350 (*mPrecisionStack[indexOfLastElement])[type] = prec; 351 } 352 353 TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const 354 { 355 if (!SupportsPrecision(type)) 356 return EbpUndefined; 357 358 // unsigned integers use the same precision as signed 359 TBasicType baseType = (type == EbtUInt) ? EbtInt : type; 360 361 int level = static_cast<int>(mPrecisionStack.size()) - 1; 362 ASSERT(level >= 0); // Just to be safe. Should not happen. 363 // If we dont find anything we return this. Some types don't have predefined default precision. 364 TPrecision prec = EbpUndefined; 365 while (level >= 0) 366 { 367 PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType); 368 if (it != mPrecisionStack[level]->end()) 369 { 370 prec = (*it).second; 371 break; 372 } 373 level--; 374 } 375 return prec; 376 } 377 378 void TSymbolTable::clearCompilationResults() 379 { 380 mGlobalInvariant = false; 381 mUniqueIdCounter = kLastBuiltInId + 1; 382 mVariableMetadata.clear(); 383 mGlInVariableWithArraySize = nullptr; 384 385 // User-defined scopes should have already been cleared when the compilation finished. 386 ASSERT(mTable.empty()); 387 } 388 389 int TSymbolTable::nextUniqueIdValue() 390 { 391 ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max()); 392 return ++mUniqueIdCounter; 393 } 394 395 void TSymbolTable::initializeBuiltIns(sh::GLenum type, 396 ShShaderSpec spec, 397 const ShBuiltInResources &resources) 398 { 399 mShaderType = type; 400 mShaderSpec = spec; 401 mResources = resources; 402 403 // We need just one precision stack level for predefined precisions. 404 mPrecisionStack.emplace_back(new PrecisionStackLevel); 405 406 if (IsDesktopGLSpec(spec)) 407 { 408 setDefaultPrecision(EbtInt, EbpUndefined); 409 setDefaultPrecision(EbtFloat, EbpUndefined); 410 } 411 else 412 { 413 switch (type) 414 { 415 case GL_FRAGMENT_SHADER: 416 setDefaultPrecision(EbtInt, EbpMedium); 417 break; 418 case GL_VERTEX_SHADER: 419 case GL_COMPUTE_SHADER: 420 case GL_GEOMETRY_SHADER_EXT: 421 case GL_TESS_CONTROL_SHADER_EXT: 422 case GL_TESS_EVALUATION_SHADER_EXT: 423 setDefaultPrecision(EbtInt, EbpHigh); 424 setDefaultPrecision(EbtFloat, EbpHigh); 425 break; 426 default: 427 UNREACHABLE(); 428 } 429 } 430 431 // Set defaults for sampler types that have default precision, even those that are 432 // only available if an extension exists. 433 // New sampler types in ESSL3 don't have default precision. ESSL1 types do. 434 initSamplerDefaultPrecision(EbtSampler2D); 435 initSamplerDefaultPrecision(EbtSamplerCube); 436 // SamplerExternalOES is specified in the extension to have default precision. 437 initSamplerDefaultPrecision(EbtSamplerExternalOES); 438 // SamplerExternal2DY2YEXT is specified in the extension to have default precision. 439 initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT); 440 // It isn't specified whether Sampler2DRect has default precision. 441 initSamplerDefaultPrecision(EbtSampler2DRect); 442 443 if (spec < SH_GLES3_SPEC) 444 { 445 // Only set the default precision of shadow samplers in ESLL1. They become core in ESSL3 446 // where they do not have a defalut precision. 447 initSamplerDefaultPrecision(EbtSampler2DShadow); 448 } 449 450 setDefaultPrecision(EbtAtomicCounter, EbpHigh); 451 452 initializeBuiltInVariables(type, spec, resources); 453 mUniqueIdCounter = kLastBuiltInId + 1; 454 } 455 456 void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType) 457 { 458 ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd); 459 setDefaultPrecision(samplerType, EbpLow); 460 } 461 462 TSymbolTable::VariableMetadata::VariableMetadata() 463 : staticRead(false), staticWrite(false), invariant(false) 464 {} 465 466 const TSymbol *SymbolRule::get(ShShaderSpec shaderSpec, 467 int shaderVersion, 468 sh::GLenum shaderType, 469 const ShBuiltInResources &resources, 470 const TSymbolTableBase &symbolTable) const 471 { 472 if (IsDesktopGLSpec(shaderSpec) != (mIsDesktop == 1)) 473 return nullptr; 474 475 if (mVersion == kESSL1Only && shaderVersion != static_cast<int>(kESSL1Only)) 476 return nullptr; 477 478 if (mVersion > shaderVersion) 479 return nullptr; 480 481 if (!CheckShaderType(static_cast<Shader>(mShaders), shaderType)) 482 return nullptr; 483 484 if (mExtensionIndex != 0 && !CheckExtension(mExtensionIndex, resources)) 485 return nullptr; 486 487 return mIsVar > 0 ? symbolTable.*(mSymbolOrVar.var) : mSymbolOrVar.symbol; 488 } 489 490 const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec, 491 int shaderVersion, 492 sh::GLenum shaderType, 493 const ShBuiltInResources &resources, 494 const TSymbolTableBase &symbolTable, 495 const SymbolRule *rules, 496 uint16_t startIndex, 497 uint16_t endIndex) 498 { 499 for (uint32_t ruleIndex = startIndex; ruleIndex < endIndex; ++ruleIndex) 500 { 501 const TSymbol *symbol = 502 rules[ruleIndex].get(shaderSpec, shaderVersion, shaderType, resources, symbolTable); 503 if (symbol) 504 { 505 return symbol; 506 } 507 } 508 509 return nullptr; 510 } 511 512 bool UnmangledEntry::matches(const ImmutableString &name, 513 ShShaderSpec shaderSpec, 514 int shaderVersion, 515 sh::GLenum shaderType, 516 const TExtensionBehavior &extensions) const 517 { 518 if (name != mName) 519 return false; 520 521 if (!CheckShaderType(static_cast<Shader>(mShaderType), shaderType)) 522 return false; 523 524 if (IsDesktopGLSpec(shaderSpec)) 525 { 526 if (mGLSLVersion > shaderVersion) 527 return false; 528 529 if (mGLSLExtension == TExtension::UNDEFINED) 530 return true; 531 532 return IsExtensionEnabled(extensions, mGLSLExtension); 533 } 534 else 535 { 536 if (mESSLVersion == kESSL1Only && shaderVersion != static_cast<int>(kESSL1Only)) 537 return false; 538 539 if (mESSLVersion > shaderVersion) 540 return false; 541 542 bool anyExtension = false; 543 bool anyExtensionEnabled = false; 544 for (TExtension ext : mESSLExtensions) 545 { 546 if (ext != TExtension::UNDEFINED) 547 { 548 anyExtension = true; 549 anyExtensionEnabled = anyExtensionEnabled || IsExtensionEnabled(extensions, ext); 550 } 551 } 552 553 if (!anyExtension) 554 return true; 555 556 return anyExtensionEnabled; 557 } 558 } 559 } // namespace sh