1 // 2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 // Copyright (C) 2012-2015 LunarG, Inc. 4 // Copyright (C) 2015-2016 Google, Inc. 5 // 6 // All rights reserved. 7 // 8 // Redistribution and use in source and binary forms, with or without 9 // modification, are permitted provided that the following conditions 10 // are met: 11 // 12 // Redistributions of source code must retain the above copyright 13 // notice, this list of conditions and the following disclaimer. 14 // 15 // Redistributions in binary form must reproduce the above 16 // copyright notice, this list of conditions and the following 17 // disclaimer in the documentation and/or other materials provided 18 // with the distribution. 19 // 20 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 21 // contributors may be used to endorse or promote products derived 22 // from this software without specific prior written permission. 23 // 24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 // POSSIBILITY OF SUCH DAMAGE. 36 // 37 38 #include "ParseHelper.h" 39 #include "Scan.h" 40 41 #include "../OSDependent/osinclude.h" 42 #include <algorithm> 43 44 #include "preprocessor/PpContext.h" 45 46 extern int yyparse(glslang::TParseContext*); 47 48 namespace glslang { 49 50 TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, 51 int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, 52 TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) : 53 TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, 54 infoSink, forwardCompatible, messages), 55 inMain(false), 56 blockName(nullptr), 57 limits(resources.limits), 58 atomicUintOffsets(nullptr), anyIndexLimits(false) 59 { 60 // decide whether precision qualifiers should be ignored or respected 61 if (profile == EEsProfile || spvVersion.vulkan > 0) { 62 precisionManager.respectPrecisionQualifiers(); 63 if (! parsingBuiltins && language == EShLangFragment && profile != EEsProfile && spvVersion.vulkan > 0) 64 precisionManager.warnAboutDefaults(); 65 } 66 67 setPrecisionDefaults(); 68 69 globalUniformDefaults.clear(); 70 globalUniformDefaults.layoutMatrix = ElmColumnMajor; 71 globalUniformDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd140 : ElpShared; 72 73 globalBufferDefaults.clear(); 74 globalBufferDefaults.layoutMatrix = ElmColumnMajor; 75 globalBufferDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd430 : ElpShared; 76 77 globalInputDefaults.clear(); 78 globalOutputDefaults.clear(); 79 80 // "Shaders in the transform 81 // feedback capturing mode have an initial global default of 82 // layout(xfb_buffer = 0) out;" 83 if (language == EShLangVertex || 84 language == EShLangTessControl || 85 language == EShLangTessEvaluation || 86 language == EShLangGeometry) 87 globalOutputDefaults.layoutXfbBuffer = 0; 88 89 if (language == EShLangGeometry) 90 globalOutputDefaults.layoutStream = 0; 91 } 92 93 TParseContext::~TParseContext() 94 { 95 delete [] atomicUintOffsets; 96 } 97 98 // Set up all default precisions as needed by the current environment. 99 // Intended just as a TParseContext constructor helper. 100 void TParseContext::setPrecisionDefaults() 101 { 102 // Set all precision defaults to EpqNone, which is correct for all types 103 // when not obeying precision qualifiers, and correct for types that don't 104 // have defaults (thus getting an error on use) when obeying precision 105 // qualifiers. 106 107 for (int type = 0; type < EbtNumTypes; ++type) 108 defaultPrecision[type] = EpqNone; 109 110 for (int type = 0; type < maxSamplerIndex; ++type) 111 defaultSamplerPrecision[type] = EpqNone; 112 113 // replace with real precision defaults for those that have them 114 if (obeyPrecisionQualifiers()) { 115 if (profile == EEsProfile) { 116 // Most don't have defaults, a few default to lowp. 117 TSampler sampler; 118 sampler.set(EbtFloat, Esd2D); 119 defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; 120 sampler.set(EbtFloat, EsdCube); 121 defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; 122 sampler.set(EbtFloat, Esd2D); 123 sampler.external = true; 124 defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; 125 } else { 126 // Non-ES profile 127 // All default to highp. 128 for (int type = 0; type < maxSamplerIndex; ++type) 129 defaultSamplerPrecision[type] = EpqHigh; 130 } 131 132 // If we are parsing built-in computational variables/functions, it is meaningful to record 133 // whether the built-in has no precision qualifier, as that ambiguity 134 // is used to resolve the precision from the supplied arguments/operands instead. 135 // So, we don't actually want to replace EpqNone with a default precision for built-ins. 136 if (! parsingBuiltins) { 137 if (profile == EEsProfile && language == EShLangFragment) { 138 defaultPrecision[EbtInt] = EpqMedium; 139 defaultPrecision[EbtUint] = EpqMedium; 140 } else { 141 defaultPrecision[EbtInt] = EpqHigh; 142 defaultPrecision[EbtUint] = EpqHigh; 143 defaultPrecision[EbtFloat] = EpqHigh; 144 } 145 } 146 147 defaultPrecision[EbtSampler] = EpqLow; 148 defaultPrecision[EbtAtomicUint] = EpqHigh; 149 } 150 } 151 152 void TParseContext::setLimits(const TBuiltInResource& r) 153 { 154 resources = r; 155 156 anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing || 157 ! limits.generalConstantMatrixVectorIndexing || 158 ! limits.generalSamplerIndexing || 159 ! limits.generalUniformIndexing || 160 ! limits.generalVariableIndexing || 161 ! limits.generalVaryingIndexing; 162 163 intermediate.setLimits(resources); 164 165 // "Each binding point tracks its own current default offset for 166 // inheritance of subsequent variables using the same binding. The initial state of compilation is that all 167 // binding points have an offset of 0." 168 atomicUintOffsets = new int[resources.maxAtomicCounterBindings]; 169 for (int b = 0; b < resources.maxAtomicCounterBindings; ++b) 170 atomicUintOffsets[b] = 0; 171 } 172 173 // 174 // Parse an array of strings using yyparse, going through the 175 // preprocessor to tokenize the shader strings, then through 176 // the GLSL scanner. 177 // 178 // Returns true for successful acceptance of the shader, false if any errors. 179 // 180 bool TParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError) 181 { 182 currentScanner = &input; 183 ppContext.setInput(input, versionWillBeError); 184 yyparse(this); 185 186 finish(); 187 188 return numErrors == 0; 189 } 190 191 // This is called from bison when it has a parse (syntax) error 192 // Note though that to stop cascading errors, we set EOF, which 193 // will usually cause a syntax error, so be more accurate that 194 // compilation is terminating. 195 void TParseContext::parserError(const char* s) 196 { 197 if (! getScanner()->atEndOfInput() || numErrors == 0) 198 error(getCurrentLoc(), "", "", s, ""); 199 else 200 error(getCurrentLoc(), "compilation terminated", "", ""); 201 } 202 203 void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens) 204 { 205 if (pragmaCallback) 206 pragmaCallback(loc.line, tokens); 207 208 if (tokens.size() == 0) 209 return; 210 211 if (tokens[0].compare("optimize") == 0) { 212 if (tokens.size() != 4) { 213 error(loc, "optimize pragma syntax is incorrect", "#pragma", ""); 214 return; 215 } 216 217 if (tokens[1].compare("(") != 0) { 218 error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", ""); 219 return; 220 } 221 222 if (tokens[2].compare("on") == 0) 223 contextPragma.optimize = true; 224 else if (tokens[2].compare("off") == 0) 225 contextPragma.optimize = false; 226 else { 227 error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); 228 return; 229 } 230 231 if (tokens[3].compare(")") != 0) { 232 error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", ""); 233 return; 234 } 235 } else if (tokens[0].compare("debug") == 0) { 236 if (tokens.size() != 4) { 237 error(loc, "debug pragma syntax is incorrect", "#pragma", ""); 238 return; 239 } 240 241 if (tokens[1].compare("(") != 0) { 242 error(loc, "\"(\" expected after 'debug' keyword", "#pragma", ""); 243 return; 244 } 245 246 if (tokens[2].compare("on") == 0) 247 contextPragma.debug = true; 248 else if (tokens[2].compare("off") == 0) 249 contextPragma.debug = false; 250 else { 251 error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); 252 return; 253 } 254 255 if (tokens[3].compare(")") != 0) { 256 error(loc, "\")\" expected to end 'debug' pragma", "#pragma", ""); 257 return; 258 } 259 } else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) { 260 if (tokens.size() != 1) 261 error(loc, "extra tokens", "#pragma", ""); 262 intermediate.setUseStorageBuffer(); 263 } 264 } 265 266 // 267 // Handle seeing a variable identifier in the grammar. 268 // 269 TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string) 270 { 271 TIntermTyped* node = nullptr; 272 273 // Error check for requiring specific extensions present. 274 if (symbol && symbol->getNumExtensions()) 275 requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); 276 277 if (symbol && symbol->isReadOnly()) { 278 // All shared things containing an implicitly sized array must be copied up 279 // on first use, so that all future references will share its array structure, 280 // so that editing the implicit size will effect all nodes consuming it, 281 // and so that editing the implicit size won't change the shared one. 282 // 283 // If this is a variable or a block, check it and all it contains, but if this 284 // is a member of an anonymous block, check the whole block, as the whole block 285 // will need to be copied up if it contains an implicitly-sized array. 286 if (symbol->getType().containsImplicitlySizedArray() || 287 (symbol->getAsAnonMember() && 288 symbol->getAsAnonMember()->getAnonContainer().getType().containsImplicitlySizedArray())) 289 makeEditable(symbol); 290 } 291 292 const TVariable* variable; 293 const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; 294 if (anon) { 295 // It was a member of an anonymous container. 296 297 // The "getNumExtensions()" mechanism above doesn't yet work for block members 298 blockMemberExtensionCheck(loc, nullptr, *string); 299 300 // Create a subtree for its dereference. 301 variable = anon->getAnonContainer().getAsVariable(); 302 TIntermTyped* container = intermediate.addSymbol(*variable, loc); 303 TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc); 304 node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc); 305 306 node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); 307 if (node->getType().hiddenMember()) 308 error(loc, "member of nameless block was not redeclared", string->c_str(), ""); 309 } else { 310 // Not a member of an anonymous container. 311 312 // The symbol table search was done in the lexical phase. 313 // See if it was a variable. 314 variable = symbol ? symbol->getAsVariable() : nullptr; 315 if (variable) { 316 if ((variable->getType().getBasicType() == EbtBlock || 317 variable->getType().getBasicType() == EbtStruct) && variable->getType().getStruct() == nullptr) { 318 error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), ""); 319 variable = nullptr; 320 } 321 } else { 322 if (symbol) 323 error(loc, "variable name expected", string->c_str(), ""); 324 } 325 326 // Recovery, if it wasn't found or was not a variable. 327 if (! variable) 328 variable = new TVariable(string, TType(EbtVoid)); 329 330 if (variable->getType().getQualifier().isFrontEndConstant()) 331 node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc); 332 else 333 node = intermediate.addSymbol(*variable, loc); 334 } 335 336 if (variable->getType().getQualifier().isIo()) 337 intermediate.addIoAccessed(*string); 338 339 return node; 340 } 341 342 // 343 // Handle seeing a base[index] dereference in the grammar. 344 // 345 TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) 346 { 347 TIntermTyped* result = nullptr; 348 349 int indexValue = 0; 350 if (index->getQualifier().isFrontEndConstant()) 351 indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); 352 353 variableCheck(base); 354 if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) { 355 if (base->getAsSymbolNode()) 356 error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); 357 else 358 error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); 359 } else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) { 360 // both base and index are front-end constants 361 checkIndex(loc, base->getType(), indexValue); 362 return intermediate.foldDereference(base, indexValue, loc); 363 } else { 364 // at least one of base and index is not a front-end constant variable... 365 366 if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) 367 handleIoResizeArrayAccess(loc, base); 368 369 if (index->getQualifier().isFrontEndConstant()) { 370 if (base->getType().isImplicitlySizedArray()) 371 updateImplicitArraySize(loc, base, indexValue); 372 else 373 checkIndex(loc, base->getType(), indexValue); 374 result = intermediate.addIndex(EOpIndexDirect, base, index, loc); 375 } else { 376 if (base->getType().isImplicitlySizedArray()) { 377 if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) 378 error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable"); 379 else 380 error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable"); 381 } 382 if (base->getBasicType() == EbtBlock) { 383 if (base->getQualifier().storage == EvqBuffer) 384 requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array"); 385 else if (base->getQualifier().storage == EvqUniform) 386 profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, 387 "variable indexing uniform block array"); 388 else { 389 // input/output blocks either don't exist or can be variable indexed 390 } 391 } else if (language == EShLangFragment && base->getQualifier().isPipeOutput()) 392 requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader output array"); 393 else if (base->getBasicType() == EbtSampler && version >= 130) { 394 const char* explanation = "variable indexing sampler array"; 395 requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation); 396 profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation); 397 profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation); 398 } 399 400 result = intermediate.addIndex(EOpIndexIndirect, base, index, loc); 401 } 402 } 403 404 if (result == nullptr) { 405 // Insert dummy error-recovery result 406 result = intermediate.addConstantUnion(0.0, EbtFloat, loc); 407 } else { 408 // Insert valid dereferenced result 409 TType newType(base->getType(), 0); // dereferenced type 410 if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) { 411 newType.getQualifier().storage = EvqConst; 412 // If base or index is a specialization constant, the result should also be a specialization constant. 413 if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) { 414 newType.getQualifier().makeSpecConstant(); 415 } 416 } else { 417 newType.getQualifier().makePartialTemporary(); 418 } 419 result->setType(newType); 420 421 if (anyIndexLimits) 422 handleIndexLimits(loc, base, index); 423 } 424 425 return result; 426 } 427 428 void TParseContext::checkIndex(const TSourceLoc& loc, const TType& type, int& index) 429 { 430 if (index < 0) { 431 error(loc, "", "[", "index out of range '%d'", index); 432 index = 0; 433 } else if (type.isArray()) { 434 if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) { 435 error(loc, "", "[", "array index out of range '%d'", index); 436 index = type.getOuterArraySize() - 1; 437 } 438 } else if (type.isVector()) { 439 if (index >= type.getVectorSize()) { 440 error(loc, "", "[", "vector index out of range '%d'", index); 441 index = type.getVectorSize() - 1; 442 } 443 } else if (type.isMatrix()) { 444 if (index >= type.getMatrixCols()) { 445 error(loc, "", "[", "matrix index out of range '%d'", index); 446 index = type.getMatrixCols() - 1; 447 } 448 } 449 } 450 451 // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms 452 void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index) 453 { 454 if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) || 455 (! limits.generalUniformIndexing && base->getQualifier().isUniformOrBuffer() && language != EShLangVertex) || 456 (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) || 457 (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) || 458 (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() && 459 ! base->getType().getQualifier().isPipeInput() && 460 ! base->getType().getQualifier().isPipeOutput() && 461 ! base->getType().getQualifier().isConstant()) || 462 (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || 463 base->getType().getQualifier().isPipeOutput()))) { 464 // it's too early to know what the inductive variables are, save it for post processing 465 needsIndexLimitationChecking.push_back(index); 466 } 467 } 468 469 // Make a shared symbol have a non-shared version that can be edited by the current 470 // compile, such that editing its type will not change the shared version and will 471 // effect all nodes sharing it. 472 void TParseContext::makeEditable(TSymbol*& symbol) 473 { 474 TParseContextBase::makeEditable(symbol); 475 476 // See if it's tied to IO resizing 477 if (isIoResizeArray(symbol->getType())) 478 ioArraySymbolResizeList.push_back(symbol); 479 } 480 481 // Return true if this is a geometry shader input array or tessellation control output array. 482 bool TParseContext::isIoResizeArray(const TType& type) const 483 { 484 return type.isArray() && 485 ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || 486 (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch)); 487 } 488 489 // If an array is not isIoResizeArray() but is an io array, make sure it has the right size 490 void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type) 491 { 492 if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel()) 493 return; 494 495 assert(! isIoResizeArray(type)); 496 497 if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch) 498 return; 499 500 if (language == EShLangTessControl || language == EShLangTessEvaluation) { 501 if (type.getOuterArraySize() != resources.maxPatchVertices) { 502 if (type.isExplicitlySizedArray()) 503 error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", ""); 504 type.changeOuterArraySize(resources.maxPatchVertices); 505 } 506 } 507 } 508 509 // Issue any errors if the non-array object is missing arrayness WRT 510 // shader I/O that has array requirements. 511 // All arrayness checking is handled in array paths, this is for 512 void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) 513 { 514 if (! type.isArray() && ! symbolTable.atBuiltInLevel()) { 515 if (type.getQualifier().isArrayedIo(language) 516 #ifdef NV_EXTENSIONS 517 && !type.getQualifier().layoutPassthrough 518 #endif 519 ) 520 error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str()); 521 } 522 } 523 524 // Handle a dereference of a geometry shader input array or tessellation control output array. 525 // See ioArraySymbolResizeList comment in ParseHelper.h. 526 // 527 void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base) 528 { 529 TIntermSymbol* symbolNode = base->getAsSymbolNode(); 530 assert(symbolNode); 531 if (! symbolNode) 532 return; 533 534 // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing) 535 if (symbolNode->getType().isImplicitlySizedArray()) { 536 int newSize = getIoArrayImplicitSize(); 537 if (newSize > 0) 538 symbolNode->getWritableType().changeOuterArraySize(newSize); 539 } 540 } 541 542 // If there has been an input primitive declaration (geometry shader) or an output 543 // number of vertices declaration(tessellation shader), make sure all input array types 544 // match it in size. Types come either from nodes in the AST or symbols in the 545 // symbol table. 546 // 547 // Types without an array size will be given one. 548 // Types already having a size that is wrong will get an error. 549 // 550 void TParseContext::checkIoArraysConsistency(const TSourceLoc& loc, bool tailOnly) 551 { 552 int requiredSize = getIoArrayImplicitSize(); 553 if (requiredSize == 0) 554 return; 555 556 const char* feature; 557 if (language == EShLangGeometry) 558 feature = TQualifier::getGeometryString(intermediate.getInputPrimitive()); 559 else if (language == EShLangTessControl) 560 feature = "vertices"; 561 else 562 feature = "unknown"; 563 564 if (tailOnly) { 565 checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName()); 566 return; 567 } 568 569 for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i) 570 checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName()); 571 } 572 573 int TParseContext::getIoArrayImplicitSize() const 574 { 575 if (language == EShLangGeometry) 576 return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); 577 else if (language == EShLangTessControl) 578 return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; 579 else 580 return 0; 581 } 582 583 void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name) 584 { 585 if (type.isImplicitlySizedArray()) 586 type.changeOuterArraySize(requiredSize); 587 else if (type.getOuterArraySize() != requiredSize) { 588 if (language == EShLangGeometry) 589 error(loc, "inconsistent input primitive for array size of", feature, name.c_str()); 590 else if (language == EShLangTessControl) 591 error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str()); 592 else 593 assert(0); 594 } 595 } 596 597 // Handle seeing a binary node with a math operation. 598 // Returns nullptr if not semantically allowed. 599 TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right) 600 { 601 rValueErrorCheck(loc, str, left->getAsTyped()); 602 rValueErrorCheck(loc, str, right->getAsTyped()); 603 604 bool allowed = true; 605 switch (op) { 606 // TODO: Bring more source language-specific checks up from intermediate.cpp 607 // to the specific parse helpers for that source language. 608 case EOpLessThan: 609 case EOpGreaterThan: 610 case EOpLessThanEqual: 611 case EOpGreaterThanEqual: 612 if (! left->isScalar() || ! right->isScalar()) 613 allowed = false; 614 break; 615 default: 616 break; 617 } 618 619 TIntermTyped* result = nullptr; 620 if (allowed) 621 result = intermediate.addBinaryMath(op, left, right, loc); 622 623 if (result == nullptr) 624 binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString()); 625 626 return result; 627 } 628 629 // Handle seeing a unary node with a math operation. 630 TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* childNode) 631 { 632 rValueErrorCheck(loc, str, childNode); 633 634 TIntermTyped* result = intermediate.addUnaryMath(op, childNode, loc); 635 636 if (result) 637 return result; 638 else 639 unaryOpError(loc, str, childNode->getCompleteString()); 640 641 return childNode; 642 } 643 644 // 645 // Handle seeing a base.field dereference in the grammar. 646 // 647 TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field) 648 { 649 variableCheck(base); 650 651 // 652 // .length() can't be resolved until we later see the function-calling syntax. 653 // Save away the name in the AST for now. Processing is completed in 654 // handleLengthMethod(). 655 // 656 if (field == "length") { 657 if (base->isArray()) { 658 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, ".length"); 659 profileRequires(loc, EEsProfile, 300, nullptr, ".length"); 660 } else if (base->isVector() || base->isMatrix()) { 661 const char* feature = ".length() on vectors and matrices"; 662 requireProfile(loc, ~EEsProfile, feature); 663 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature); 664 } else { 665 error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str()); 666 667 return base; 668 } 669 670 return intermediate.addMethod(base, TType(EbtInt), &field, loc); 671 } 672 673 // It's not .length() if we get to here. 674 675 if (base->isArray()) { 676 error(loc, "cannot apply to an array:", ".", field.c_str()); 677 678 return base; 679 } 680 681 // It's neither an array nor .length() if we get here, 682 // leaving swizzles and struct/block dereferences. 683 684 TIntermTyped* result = base; 685 if (base->isVector() || base->isScalar()) { 686 if (base->isScalar()) { 687 const char* dotFeature = "scalar swizzle"; 688 requireProfile(loc, ~EEsProfile, dotFeature); 689 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature); 690 } 691 692 TSwizzleSelectors<TVectorSelector> selectors; 693 parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); 694 695 if (base->isScalar()) { 696 if (selectors.size() == 1) 697 return result; 698 else { 699 TType type(base->getBasicType(), EvqTemporary, selectors.size()); 700 // Swizzle operations propagate specialization-constantness 701 if (base->getQualifier().isSpecConstant()) 702 type.getQualifier().makeSpecConstant(); 703 return addConstructor(loc, base, type); 704 } 705 } 706 707 if (base->getType().getQualifier().isFrontEndConstant()) 708 result = intermediate.foldSwizzle(base, selectors, loc); 709 else { 710 if (selectors.size() == 1) { 711 TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); 712 result = intermediate.addIndex(EOpIndexDirect, base, index, loc); 713 result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision)); 714 } else { 715 TIntermTyped* index = intermediate.addSwizzle(selectors, loc); 716 result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); 717 result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); 718 } 719 // Swizzle operations propagate specialization-constantness 720 if (base->getType().getQualifier().isSpecConstant()) 721 result->getWritableType().getQualifier().makeSpecConstant(); 722 } 723 } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { 724 const TTypeList* fields = base->getType().getStruct(); 725 bool fieldFound = false; 726 int member; 727 for (member = 0; member < (int)fields->size(); ++member) { 728 if ((*fields)[member].type->getFieldName() == field) { 729 fieldFound = true; 730 break; 731 } 732 } 733 if (fieldFound) { 734 if (base->getType().getQualifier().isFrontEndConstant()) 735 result = intermediate.foldDereference(base, member, loc); 736 else { 737 blockMemberExtensionCheck(loc, base, field); 738 TIntermTyped* index = intermediate.addConstantUnion(member, loc); 739 result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); 740 result->setType(*(*fields)[member].type); 741 } 742 } else 743 error(loc, "no such field in structure", field.c_str(), ""); 744 } else 745 error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str()); 746 747 // Propagate noContraction up the dereference chain 748 if (base->getQualifier().noContraction) 749 result->getWritableType().getQualifier().noContraction = true; 750 751 return result; 752 } 753 754 void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* /*base*/, const TString& field) 755 { 756 if (profile == EEsProfile && field == "gl_PointSize") { 757 if (language == EShLangGeometry) 758 requireExtensions(loc, Num_AEP_geometry_point_size, AEP_geometry_point_size, "gl_PointSize"); 759 else if (language == EShLangTessControl || language == EShLangTessEvaluation) 760 requireExtensions(loc, Num_AEP_tessellation_point_size, AEP_tessellation_point_size, "gl_PointSize"); 761 } 762 } 763 764 // 765 // Handle seeing a function declarator in the grammar. This is the precursor 766 // to recognizing a function prototype or function definition. 767 // 768 TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype) 769 { 770 // ES can't declare prototypes inside functions 771 if (! symbolTable.atGlobalLevel()) 772 requireProfile(loc, ~EEsProfile, "local function declaration"); 773 774 // 775 // Multiple declarations of the same function name are allowed. 776 // 777 // If this is a definition, the definition production code will check for redefinitions 778 // (we don't know at this point if it's a definition or not). 779 // 780 // Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match. 781 // - except ES 100, which only allows a single prototype 782 // 783 // ES 100 does not allow redefining, but does allow overloading of built-in functions. 784 // ES 300 does not allow redefining or overloading of built-in functions. 785 // 786 bool builtIn; 787 TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); 788 if (symbol && symbol->getAsFunction() && builtIn) 789 requireProfile(loc, ~EEsProfile, "redefinition of built-in function"); 790 const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; 791 if (prevDec) { 792 if (prevDec->isPrototyped() && prototype) 793 profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function"); 794 if (prevDec->getType() != function.getType()) 795 error(loc, "overloaded functions must have the same return type", function.getType().getBasicTypeString().c_str(), ""); 796 for (int i = 0; i < prevDec->getParamCount(); ++i) { 797 if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage) 798 error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1); 799 800 if ((*prevDec)[i].type->getQualifier().precision != function[i].type->getQualifier().precision) 801 error(loc, "overloaded functions must have the same parameter precision qualifiers for argument", function[i].type->getPrecisionQualifierString(), "%d", i+1); 802 } 803 } 804 805 arrayObjectCheck(loc, function.getType(), "array in function return type"); 806 807 if (prototype) { 808 // All built-in functions are defined, even though they don't have a body. 809 // Count their prototype as a definition instead. 810 if (symbolTable.atBuiltInLevel()) 811 function.setDefined(); 812 else { 813 if (prevDec && ! builtIn) 814 symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const 815 function.setPrototyped(); 816 } 817 } 818 819 // This insert won't actually insert it if it's a duplicate signature, but it will still check for 820 // other forms of name collisions. 821 if (! symbolTable.insert(function)) 822 error(loc, "function name is redeclaration of existing name", function.getName().c_str(), ""); 823 824 // 825 // If this is a redeclaration, it could also be a definition, 826 // in which case, we need to use the parameter names from this one, and not the one that's 827 // being redeclared. So, pass back this declaration, not the one in the symbol table. 828 // 829 return &function; 830 } 831 832 // 833 // Handle seeing the function prototype in front of a function definition in the grammar. 834 // The body is handled after this function returns. 835 // 836 TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function) 837 { 838 currentCaller = function.getMangledName(); 839 TSymbol* symbol = symbolTable.find(function.getMangledName()); 840 TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; 841 842 if (! prevDec) 843 error(loc, "can't find function", function.getName().c_str(), ""); 844 // Note: 'prevDec' could be 'function' if this is the first time we've seen function 845 // as it would have just been put in the symbol table. Otherwise, we're looking up 846 // an earlier occurrence. 847 848 if (prevDec && prevDec->isDefined()) { 849 // Then this function already has a body. 850 error(loc, "function already has a body", function.getName().c_str(), ""); 851 } 852 if (prevDec && ! prevDec->isDefined()) { 853 prevDec->setDefined(); 854 855 // Remember the return type for later checking for RETURN statements. 856 currentFunctionType = &(prevDec->getType()); 857 } else 858 currentFunctionType = new TType(EbtVoid); 859 functionReturnsValue = false; 860 861 // Check for entry point 862 if (function.getName().compare(intermediate.getEntryPointName().c_str()) == 0) { 863 intermediate.setEntryPointMangledName(function.getMangledName().c_str()); 864 intermediate.incrementEntryPointCount(); 865 inMain = true; 866 } else 867 inMain = false; 868 869 // 870 // Raise error message if main function takes any parameters or returns anything other than void 871 // 872 if (inMain) { 873 if (function.getParamCount() > 0) 874 error(loc, "function cannot take any parameter(s)", function.getName().c_str(), ""); 875 if (function.getType().getBasicType() != EbtVoid) 876 error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value"); 877 } 878 879 // 880 // New symbol table scope for body of function plus its arguments 881 // 882 symbolTable.push(); 883 884 // 885 // Insert parameters into the symbol table. 886 // If the parameter has no name, it's not an error, just don't insert it 887 // (could be used for unused args). 888 // 889 // Also, accumulate the list of parameters into the HIL, so lower level code 890 // knows where to find parameters. 891 // 892 TIntermAggregate* paramNodes = new TIntermAggregate; 893 for (int i = 0; i < function.getParamCount(); i++) { 894 TParameter& param = function[i]; 895 if (param.name != nullptr) { 896 TVariable *variable = new TVariable(param.name, *param.type); 897 898 // Insert the parameters with name in the symbol table. 899 if (! symbolTable.insert(*variable)) 900 error(loc, "redefinition", variable->getName().c_str(), ""); 901 else { 902 // Transfer ownership of name pointer to symbol table. 903 param.name = nullptr; 904 905 // Add the parameter to the HIL 906 paramNodes = intermediate.growAggregate(paramNodes, 907 intermediate.addSymbol(*variable, loc), 908 loc); 909 } 910 } else 911 paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); 912 } 913 intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); 914 loopNestingLevel = 0; 915 statementNestingLevel = 0; 916 controlFlowNestingLevel = 0; 917 postEntryPointReturn = false; 918 919 return paramNodes; 920 } 921 922 // 923 // Handle seeing function call syntax in the grammar, which could be any of 924 // - .length() method 925 // - constructor 926 // - a call to a built-in function mapped to an operator 927 // - a call to a built-in function that will remain a function call (e.g., texturing) 928 // - user function 929 // - subroutine call (not implemented yet) 930 // 931 TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments) 932 { 933 TIntermTyped* result = nullptr; 934 935 if (function->getBuiltInOp() == EOpArrayLength) 936 result = handleLengthMethod(loc, function, arguments); 937 else if (function->getBuiltInOp() != EOpNull) { 938 // 939 // Then this should be a constructor. 940 // Don't go through the symbol table for constructors. 941 // Their parameters will be verified algorithmically. 942 // 943 TType type(EbtVoid); // use this to get the type back 944 if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) { 945 // 946 // It's a constructor, of type 'type'. 947 // 948 result = addConstructor(loc, arguments, type); 949 if (result == nullptr) 950 error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), ""); 951 } 952 } else { 953 // 954 // Find it in the symbol table. 955 // 956 const TFunction* fnCandidate; 957 bool builtIn; 958 fnCandidate = findFunction(loc, *function, builtIn); 959 if (fnCandidate) { 960 // This is a declared function that might map to 961 // - a built-in operator, 962 // - a built-in function not mapped to an operator, or 963 // - a user function. 964 965 // Error check for a function requiring specific extensions present. 966 if (builtIn && fnCandidate->getNumExtensions()) 967 requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); 968 969 if (arguments) { 970 // Make sure qualifications work for these arguments. 971 TIntermAggregate* aggregate = arguments->getAsAggregate(); 972 for (int i = 0; i < fnCandidate->getParamCount(); ++i) { 973 // At this early point there is a slight ambiguity between whether an aggregate 'arguments' 974 // is the single argument itself or its children are the arguments. Only one argument 975 // means take 'arguments' itself as the one argument. 976 TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments); 977 TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier(); 978 if (formalQualifier.isParamOutput()) { 979 if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped())) 980 error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", ""); 981 } 982 TQualifier& argQualifier = arg->getAsTyped()->getQualifier(); 983 if (argQualifier.isMemory()) { 984 const char* message = "argument cannot drop memory qualifier when passed to formal parameter"; 985 if (argQualifier.volatil && ! formalQualifier.volatil) 986 error(arguments->getLoc(), message, "volatile", ""); 987 if (argQualifier.coherent && ! formalQualifier.coherent) 988 error(arguments->getLoc(), message, "coherent", ""); 989 if (argQualifier.readonly && ! formalQualifier.readonly) 990 error(arguments->getLoc(), message, "readonly", ""); 991 if (argQualifier.writeonly && ! formalQualifier.writeonly) 992 error(arguments->getLoc(), message, "writeonly", ""); 993 } 994 // TODO 4.5 functionality: A shader will fail to compile 995 // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or 996 // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the 997 // memargument of an atomic memory function, as long as the underlying array or vector is a buffer or 998 // shared variable. 999 } 1000 1001 // Convert 'in' arguments 1002 addInputArgumentConversions(*fnCandidate, arguments); // arguments may be modified if it's just a single argument node 1003 } 1004 1005 if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) { 1006 // A function call mapped to a built-in operation. 1007 result = handleBuiltInFunctionCall(loc, *arguments, *fnCandidate); 1008 } else { 1009 // This is a function call not mapped to built-in operator. 1010 // It could still be a built-in function, but only if PureOperatorBuiltins == false. 1011 result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc); 1012 TIntermAggregate* call = result->getAsAggregate(); 1013 call->setName(fnCandidate->getMangledName()); 1014 1015 // this is how we know whether the given function is a built-in function or a user-defined function 1016 // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also 1017 // if builtIn == true, it's definitely a built-in function with EOpNull 1018 if (! builtIn) { 1019 call->setUserDefined(); 1020 if (symbolTable.atGlobalLevel()) { 1021 requireProfile(loc, ~EEsProfile, "calling user function from global scope"); 1022 intermediate.addToCallGraph(infoSink, "main(", fnCandidate->getMangledName()); 1023 } else 1024 intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName()); 1025 } 1026 1027 if (builtIn) 1028 nonOpBuiltInCheck(loc, *fnCandidate, *call); 1029 else 1030 userFunctionCallCheck(loc, *call); 1031 } 1032 1033 // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. 1034 // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. 1035 // Also, build the qualifier list for user function calls, which are always called with an aggregate. 1036 if (result->getAsAggregate()) { 1037 TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); 1038 for (int i = 0; i < fnCandidate->getParamCount(); ++i) { 1039 TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; 1040 qualifierList.push_back(qual); 1041 } 1042 result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate()); 1043 } 1044 } 1045 } 1046 1047 // generic error recovery 1048 // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades 1049 if (result == nullptr) 1050 result = intermediate.addConstantUnion(0.0, EbtFloat, loc); 1051 1052 return result; 1053 } 1054 1055 TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode& arguments, 1056 const TFunction& function) 1057 { 1058 checkLocation(loc, function.getBuiltInOp()); 1059 TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(), 1060 function.getParamCount() == 1, 1061 &arguments, function.getType()); 1062 if (obeyPrecisionQualifiers()) 1063 computeBuiltinPrecisions(*result, function); 1064 1065 if (result == nullptr) { 1066 error(arguments.getLoc(), " wrong operand type", "Internal Error", 1067 "built in unary operator function. Type: %s", 1068 static_cast<TIntermTyped*>(&arguments)->getCompleteString().c_str()); 1069 } else if (result->getAsOperator()) 1070 builtInOpCheck(loc, function, *result->getAsOperator()); 1071 1072 return result; 1073 } 1074 1075 // "The operation of a built-in function can have a different precision 1076 // qualification than the precision qualification of the resulting value. 1077 // These two precision qualifications are established as follows. 1078 // 1079 // The precision qualification of the operation of a built-in function is 1080 // based on the precision qualification of its input arguments and formal 1081 // parameters: When a formal parameter specifies a precision qualifier, 1082 // that is used, otherwise, the precision qualification of the calling 1083 // argument is used. The highest precision of these will be the precision 1084 // qualification of the operation of the built-in function. Generally, 1085 // this is applied across all arguments to a built-in function, with the 1086 // exceptions being: 1087 // - bitfieldExtract and bitfieldInsert ignore the 'offset' and 'bits' 1088 // arguments. 1089 // - interpolateAt* functions only look at the 'interpolant' argument. 1090 // 1091 // The precision qualification of the result of a built-in function is 1092 // determined in one of the following ways: 1093 // 1094 // - For the texture sampling, image load, and image store functions, 1095 // the precision of the return type matches the precision of the 1096 // sampler type 1097 // 1098 // Otherwise: 1099 // 1100 // - For prototypes that do not specify a resulting precision qualifier, 1101 // the precision will be the same as the precision of the operation. 1102 // 1103 // - For prototypes that do specify a resulting precision qualifier, 1104 // the specified precision qualifier is the precision qualification of 1105 // the result." 1106 // 1107 void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction& function) 1108 { 1109 TPrecisionQualifier operationPrecision = EpqNone; 1110 TPrecisionQualifier resultPrecision = EpqNone; 1111 1112 TIntermOperator* opNode = node.getAsOperator(); 1113 if (opNode == nullptr) 1114 return; 1115 1116 if (TIntermUnary* unaryNode = node.getAsUnaryNode()) { 1117 operationPrecision = std::max(function[0].type->getQualifier().precision, 1118 unaryNode->getOperand()->getType().getQualifier().precision); 1119 if (function.getType().getBasicType() != EbtBool) 1120 resultPrecision = function.getType().getQualifier().precision == EpqNone ? 1121 operationPrecision : 1122 function.getType().getQualifier().precision; 1123 } else if (TIntermAggregate* agg = node.getAsAggregate()) { 1124 TIntermSequence& sequence = agg->getSequence(); 1125 unsigned int numArgs = (unsigned int)sequence.size(); 1126 switch (agg->getOp()) { 1127 case EOpBitfieldExtract: 1128 numArgs = 1; 1129 break; 1130 case EOpBitfieldInsert: 1131 numArgs = 2; 1132 break; 1133 case EOpInterpolateAtCentroid: 1134 case EOpInterpolateAtOffset: 1135 case EOpInterpolateAtSample: 1136 numArgs = 1; 1137 break; 1138 default: 1139 break; 1140 } 1141 // find the maximum precision from the arguments and parameters 1142 for (unsigned int arg = 0; arg < numArgs; ++arg) { 1143 operationPrecision = std::max(operationPrecision, sequence[arg]->getAsTyped()->getQualifier().precision); 1144 operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision); 1145 } 1146 // compute the result precision 1147 #ifdef AMD_EXTENSIONS 1148 if (agg->isSampling() || 1149 agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore || 1150 agg->getOp() == EOpImageLoadLod || agg->getOp() == EOpImageStoreLod) 1151 #else 1152 if (agg->isSampling() || agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore) 1153 #endif 1154 resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision; 1155 else if (function.getType().getBasicType() != EbtBool) 1156 resultPrecision = function.getType().getQualifier().precision == EpqNone ? 1157 operationPrecision : 1158 function.getType().getQualifier().precision; 1159 } 1160 1161 // Propagate precision through this node and its children. That algorithm stops 1162 // when a precision is found, so start by clearing this subroot precision 1163 opNode->getQualifier().precision = EpqNone; 1164 if (operationPrecision != EpqNone) { 1165 opNode->propagatePrecision(operationPrecision); 1166 opNode->setOperationPrecision(operationPrecision); 1167 } 1168 // Now, set the result precision, which might not match 1169 opNode->getQualifier().precision = resultPrecision; 1170 } 1171 1172 TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value) 1173 { 1174 functionReturnsValue = true; 1175 if (currentFunctionType->getBasicType() == EbtVoid) { 1176 error(loc, "void function cannot return a value", "return", ""); 1177 return intermediate.addBranch(EOpReturn, loc); 1178 } else if (*currentFunctionType != value->getType()) { 1179 TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value); 1180 if (converted) { 1181 if (*currentFunctionType != converted->getType()) 1182 error(loc, "cannot convert return value to function return type", "return", ""); 1183 if (version < 420) 1184 warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", ""); 1185 return intermediate.addBranch(EOpReturn, converted, loc); 1186 } else { 1187 error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); 1188 return intermediate.addBranch(EOpReturn, value, loc); 1189 } 1190 } else 1191 return intermediate.addBranch(EOpReturn, value, loc); 1192 } 1193 1194 // See if the operation is being done in an illegal location. 1195 void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op) 1196 { 1197 switch (op) { 1198 case EOpBarrier: 1199 if (language == EShLangTessControl) { 1200 if (controlFlowNestingLevel > 0) 1201 error(loc, "tessellation control barrier() cannot be placed within flow control", "", ""); 1202 if (! inMain) 1203 error(loc, "tessellation control barrier() must be in main()", "", ""); 1204 else if (postEntryPointReturn) 1205 error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", ""); 1206 } 1207 break; 1208 default: 1209 break; 1210 } 1211 } 1212 1213 // Finish processing object.length(). This started earlier in handleDotDereference(), where 1214 // the ".length" part was recognized and semantically checked, and finished here where the 1215 // function syntax "()" is recognized. 1216 // 1217 // Return resulting tree node. 1218 TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction* function, TIntermNode* intermNode) 1219 { 1220 int length = 0; 1221 1222 if (function->getParamCount() > 0) 1223 error(loc, "method does not accept any arguments", function->getName().c_str(), ""); 1224 else { 1225 const TType& type = intermNode->getAsTyped()->getType(); 1226 if (type.isArray()) { 1227 if (type.isRuntimeSizedArray()) { 1228 // Create a unary op and let the back end handle it 1229 return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); 1230 } else if (type.isImplicitlySizedArray()) { 1231 if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) { 1232 // We could be between a layout declaration that gives a built-in io array implicit size and 1233 // a user redeclaration of that array, meaning we have to substitute its implicit size here 1234 // without actually redeclaring the array. (It is an error to use a member before the 1235 // redeclaration, but not an error to use the array name itself.) 1236 const TString& name = intermNode->getAsSymbolNode()->getName(); 1237 if (name == "gl_in" || name == "gl_out") 1238 length = getIoArrayImplicitSize(); 1239 } 1240 if (length == 0) { 1241 if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) 1242 error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); 1243 else 1244 error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); 1245 } 1246 } else if (type.getOuterArrayNode()) { 1247 // If the array's outer size is specified by an intermediate node, it means the array's length 1248 // was specified by a specialization constant. In such a case, we should return the node of the 1249 // specialization constants to represent the length. 1250 return type.getOuterArrayNode(); 1251 } else 1252 length = type.getOuterArraySize(); 1253 } else if (type.isMatrix()) 1254 length = type.getMatrixCols(); 1255 else if (type.isVector()) 1256 length = type.getVectorSize(); 1257 else { 1258 // we should not get here, because earlier semantic checking should have prevented this path 1259 error(loc, ".length()", "unexpected use of .length()", ""); 1260 } 1261 } 1262 1263 if (length == 0) 1264 length = 1; 1265 1266 return intermediate.addConstantUnion(length, loc); 1267 } 1268 1269 // 1270 // Add any needed implicit conversions for function-call arguments to input parameters. 1271 // 1272 void TParseContext::addInputArgumentConversions(const TFunction& function, TIntermNode*& arguments) const 1273 { 1274 TIntermAggregate* aggregate = arguments->getAsAggregate(); 1275 1276 // Process each argument's conversion 1277 for (int i = 0; i < function.getParamCount(); ++i) { 1278 // At this early point there is a slight ambiguity between whether an aggregate 'arguments' 1279 // is the single argument itself or its children are the arguments. Only one argument 1280 // means take 'arguments' itself as the one argument. 1281 TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped()); 1282 if (*function[i].type != arg->getType()) { 1283 if (function[i].type->getQualifier().isParamInput()) { 1284 // In-qualified arguments just need an extra node added above the argument to 1285 // convert to the correct type. 1286 arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg); 1287 if (arg) { 1288 if (function.getParamCount() == 1) 1289 arguments = arg; 1290 else { 1291 if (aggregate) 1292 aggregate->getSequence()[i] = arg; 1293 else 1294 arguments = arg; 1295 } 1296 } 1297 } 1298 } 1299 } 1300 } 1301 1302 // 1303 // Add any needed implicit output conversions for function-call arguments. This 1304 // can require a new tree topology, complicated further by whether the function 1305 // has a return value. 1306 // 1307 // Returns a node of a subtree that evaluates to the return value of the function. 1308 // 1309 TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const 1310 { 1311 TIntermSequence& arguments = intermNode.getSequence(); 1312 1313 // Will there be any output conversions? 1314 bool outputConversions = false; 1315 for (int i = 0; i < function.getParamCount(); ++i) { 1316 if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().isParamOutput()) { 1317 outputConversions = true; 1318 break; 1319 } 1320 } 1321 1322 if (! outputConversions) 1323 return &intermNode; 1324 1325 // Setup for the new tree, if needed: 1326 // 1327 // Output conversions need a different tree topology. 1328 // Out-qualified arguments need a temporary of the correct type, with the call 1329 // followed by an assignment of the temporary to the original argument: 1330 // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...) 1331 // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet) 1332 // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment. 1333 TIntermTyped* conversionTree = nullptr; 1334 TVariable* tempRet = nullptr; 1335 if (intermNode.getBasicType() != EbtVoid) { 1336 // do the "tempRet = function(...), " bit from above 1337 tempRet = makeInternalVariable("tempReturn", intermNode.getType()); 1338 TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); 1339 conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc()); 1340 } else 1341 conversionTree = &intermNode; 1342 1343 conversionTree = intermediate.makeAggregate(conversionTree); 1344 1345 // Process each argument's conversion 1346 for (int i = 0; i < function.getParamCount(); ++i) { 1347 if (*function[i].type != arguments[i]->getAsTyped()->getType()) { 1348 if (function[i].type->getQualifier().isParamOutput()) { 1349 // Out-qualified arguments need to use the topology set up above. 1350 // do the " ...(tempArg, ...), arg = tempArg" bit from above 1351 TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type); 1352 tempArg->getWritableType().getQualifier().makeTemporary(); 1353 TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc()); 1354 TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc()); 1355 conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc()); 1356 // replace the argument with another node for the same tempArg variable 1357 arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc()); 1358 } 1359 } 1360 } 1361 1362 // Finalize the tree topology (see bigger comment above). 1363 if (tempRet) { 1364 // do the "..., tempRet" bit from above 1365 TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); 1366 conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc()); 1367 } 1368 conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc()); 1369 1370 return conversionTree; 1371 } 1372 1373 // 1374 // Do additional checking of built-in function calls that is not caught 1375 // by normal semantic checks on argument type, extension tagging, etc. 1376 // 1377 // Assumes there has been a semantically correct match to a built-in function prototype. 1378 // 1379 void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode) 1380 { 1381 // Set up convenience accessors to the argument(s). There is almost always 1382 // multiple arguments for the cases below, but when there might be one, 1383 // check the unaryArg first. 1384 const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference 1385 const TIntermTyped* unaryArg = nullptr; 1386 const TIntermTyped* arg0 = nullptr; 1387 if (callNode.getAsAggregate()) { 1388 argp = &callNode.getAsAggregate()->getSequence(); 1389 if (argp->size() > 0) 1390 arg0 = (*argp)[0]->getAsTyped(); 1391 } else { 1392 assert(callNode.getAsUnaryNode()); 1393 unaryArg = callNode.getAsUnaryNode()->getOperand(); 1394 arg0 = unaryArg; 1395 } 1396 1397 switch (callNode.getOp()) { 1398 case EOpTextureGather: 1399 case EOpTextureGatherOffset: 1400 case EOpTextureGatherOffsets: 1401 { 1402 // Figure out which variants are allowed by what extensions, 1403 // and what arguments must be constant for which situations. 1404 1405 TString featureString = fnCandidate.getName() + "(...)"; 1406 const char* feature = featureString.c_str(); 1407 profileRequires(loc, EEsProfile, 310, nullptr, feature); 1408 int compArg = -1; // track which argument, if any, is the constant component argument 1409 switch (callNode.getOp()) { 1410 case EOpTextureGather: 1411 // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, 1412 // otherwise, need GL_ARB_texture_gather. 1413 if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { 1414 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1415 if (! fnCandidate[0].type->getSampler().shadow) 1416 compArg = 2; 1417 } else 1418 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 1419 break; 1420 case EOpTextureGatherOffset: 1421 // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument 1422 if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) 1423 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 1424 else 1425 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1426 if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) 1427 profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, 1428 "non-constant offset argument"); 1429 if (! fnCandidate[0].type->getSampler().shadow) 1430 compArg = 3; 1431 break; 1432 case EOpTextureGatherOffsets: 1433 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1434 if (! fnCandidate[0].type->getSampler().shadow) 1435 compArg = 3; 1436 // check for constant offsets 1437 if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) 1438 error(loc, "must be a compile-time constant:", feature, "offsets argument"); 1439 break; 1440 default: 1441 break; 1442 } 1443 1444 if (compArg > 0 && compArg < fnCandidate.getParamCount()) { 1445 if ((*argp)[compArg]->getAsConstantUnion()) { 1446 int value = (*argp)[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1447 if (value < 0 || value > 3) 1448 error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); 1449 } else 1450 error(loc, "must be a compile-time constant:", feature, "component argument"); 1451 } 1452 1453 #ifdef AMD_EXTENSIONS 1454 bool bias = false; 1455 if (callNode.getOp() == EOpTextureGather) 1456 bias = fnCandidate.getParamCount() > 3; 1457 else if (callNode.getOp() == EOpTextureGatherOffset || 1458 callNode.getOp() == EOpTextureGatherOffsets) 1459 bias = fnCandidate.getParamCount() > 4; 1460 1461 if (bias) { 1462 TString biasFeatureString = fnCandidate.getName() + "with bias argument"; 1463 const char* feature = biasFeatureString.c_str(); 1464 profileRequires(loc, ~EEsProfile, 450, nullptr, feature); 1465 requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); 1466 } 1467 #endif 1468 1469 break; 1470 } 1471 1472 #ifdef AMD_EXTENSIONS 1473 case EOpSparseTextureGather: 1474 case EOpSparseTextureGatherOffset: 1475 case EOpSparseTextureGatherOffsets: 1476 { 1477 bool bias = false; 1478 if (callNode.getOp() == EOpSparseTextureGather) 1479 bias = fnCandidate.getParamCount() > 4; 1480 else if (callNode.getOp() == EOpSparseTextureGatherOffset || 1481 callNode.getOp() == EOpSparseTextureGatherOffsets) 1482 bias = fnCandidate.getParamCount() > 5; 1483 1484 if (bias) { 1485 TString featureString = fnCandidate.getName() + "with bias argument"; 1486 const char* feature = featureString.c_str(); 1487 profileRequires(loc, ~EEsProfile, 450, nullptr, feature); 1488 requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); 1489 } 1490 1491 break; 1492 } 1493 1494 case EOpSparseTextureGatherLod: 1495 case EOpSparseTextureGatherLodOffset: 1496 case EOpSparseTextureGatherLodOffsets: 1497 { 1498 requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str()); 1499 break; 1500 } 1501 #endif 1502 1503 case EOpTextureOffset: 1504 case EOpTextureFetchOffset: 1505 case EOpTextureProjOffset: 1506 case EOpTextureLodOffset: 1507 case EOpTextureProjLodOffset: 1508 case EOpTextureGradOffset: 1509 case EOpTextureProjGradOffset: 1510 { 1511 // Handle texture-offset limits checking 1512 // Pick which argument has to hold constant offsets 1513 int arg = -1; 1514 switch (callNode.getOp()) { 1515 case EOpTextureOffset: arg = 2; break; 1516 case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().dim != EsdRect) ? 3 : 2; break; 1517 case EOpTextureProjOffset: arg = 2; break; 1518 case EOpTextureLodOffset: arg = 3; break; 1519 case EOpTextureProjLodOffset: arg = 3; break; 1520 case EOpTextureGradOffset: arg = 4; break; 1521 case EOpTextureProjGradOffset: arg = 4; break; 1522 default: 1523 assert(0); 1524 break; 1525 } 1526 1527 if (arg > 0) { 1528 if (! (*argp)[arg]->getAsConstantUnion()) 1529 error(loc, "argument must be compile-time constant", "texel offset", ""); 1530 else { 1531 const TType& type = (*argp)[arg]->getAsTyped()->getType(); 1532 for (int c = 0; c < type.getVectorSize(); ++c) { 1533 int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); 1534 if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) 1535 error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); 1536 } 1537 } 1538 } 1539 1540 break; 1541 } 1542 1543 case EOpTextureQuerySamples: 1544 case EOpImageQuerySamples: 1545 // GL_ARB_shader_texture_image_samples 1546 profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); 1547 break; 1548 1549 case EOpImageAtomicAdd: 1550 case EOpImageAtomicMin: 1551 case EOpImageAtomicMax: 1552 case EOpImageAtomicAnd: 1553 case EOpImageAtomicOr: 1554 case EOpImageAtomicXor: 1555 case EOpImageAtomicExchange: 1556 case EOpImageAtomicCompSwap: 1557 { 1558 // Make sure the image types have the correct layout() format and correct argument types 1559 const TType& imageType = arg0->getType(); 1560 if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { 1561 if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui) 1562 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); 1563 } else { 1564 if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) 1565 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); 1566 else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile) 1567 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); 1568 } 1569 1570 break; 1571 } 1572 1573 case EOpInterpolateAtCentroid: 1574 case EOpInterpolateAtSample: 1575 case EOpInterpolateAtOffset: 1576 // Make sure the first argument is an interpolant, or an array element of an interpolant 1577 if (arg0->getType().getQualifier().storage != EvqVaryingIn) { 1578 // It might still be an array element. 1579 // 1580 // We could check more, but the semantics of the first argument are already met; the 1581 // only way to turn an array into a float/vec* is array dereference and swizzle. 1582 // 1583 // ES and desktop 4.3 and earlier: swizzles may not be used 1584 // desktop 4.4 and later: swizzles may be used 1585 bool swizzleOkay = (profile != EEsProfile) && (version >= 440); 1586 const TIntermTyped* base = TIntermediate::findLValueBase(arg0, swizzleOkay); 1587 if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn) 1588 error(loc, "first argument must be an interpolant, or interpolant-array element", fnCandidate.getName().c_str(), ""); 1589 } 1590 break; 1591 1592 case EOpEmitStreamVertex: 1593 case EOpEndStreamPrimitive: 1594 intermediate.setMultiStream(); 1595 break; 1596 1597 default: 1598 break; 1599 } 1600 } 1601 1602 extern bool PureOperatorBuiltins; 1603 1604 // Deprecated! Use PureOperatorBuiltins == true instead, in which case this 1605 // functionality is handled in builtInOpCheck() instead of here. 1606 // 1607 // Do additional checking of built-in function calls that were not mapped 1608 // to built-in operations (e.g., texturing functions). 1609 // 1610 // Assumes there has been a semantically correct match to a built-in function. 1611 // 1612 void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode) 1613 { 1614 // Further maintenance of this function is deprecated, because the "correct" 1615 // future-oriented design is to not have to do string compares on function names. 1616 1617 // If PureOperatorBuiltins == true, then all built-ins should be mapped 1618 // to a TOperator, and this function would then never get called. 1619 1620 assert(PureOperatorBuiltins == false); 1621 1622 // built-in texturing functions get their return value precision from the precision of the sampler 1623 if (fnCandidate.getType().getQualifier().precision == EpqNone && 1624 fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler) 1625 callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision; 1626 1627 if (fnCandidate.getName().compare(0, 7, "texture") == 0) { 1628 if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) { 1629 TString featureString = fnCandidate.getName() + "(...)"; 1630 const char* feature = featureString.c_str(); 1631 profileRequires(loc, EEsProfile, 310, nullptr, feature); 1632 1633 int compArg = -1; // track which argument, if any, is the constant component argument 1634 if (fnCandidate.getName().compare("textureGatherOffset") == 0) { 1635 // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument 1636 if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) 1637 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 1638 else 1639 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1640 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; 1641 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) 1642 profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, 1643 "non-constant offset argument"); 1644 if (! fnCandidate[0].type->getSampler().shadow) 1645 compArg = 3; 1646 } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) { 1647 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1648 if (! fnCandidate[0].type->getSampler().shadow) 1649 compArg = 3; 1650 // check for constant offsets 1651 int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; 1652 if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) 1653 error(loc, "must be a compile-time constant:", feature, "offsets argument"); 1654 } else if (fnCandidate.getName().compare("textureGather") == 0) { 1655 // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, 1656 // otherwise, need GL_ARB_texture_gather. 1657 if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { 1658 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); 1659 if (! fnCandidate[0].type->getSampler().shadow) 1660 compArg = 2; 1661 } else 1662 profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); 1663 } 1664 1665 if (compArg > 0 && compArg < fnCandidate.getParamCount()) { 1666 if (callNode.getSequence()[compArg]->getAsConstantUnion()) { 1667 int value = callNode.getSequence()[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); 1668 if (value < 0 || value > 3) 1669 error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); 1670 } else 1671 error(loc, "must be a compile-time constant:", feature, "component argument"); 1672 } 1673 } else { 1674 // this is only for functions not starting "textureGather"... 1675 if (fnCandidate.getName().find("Offset") != TString::npos) { 1676 1677 // Handle texture-offset limits checking 1678 int arg = -1; 1679 if (fnCandidate.getName().compare("textureOffset") == 0) 1680 arg = 2; 1681 else if (fnCandidate.getName().compare("texelFetchOffset") == 0) 1682 arg = 3; 1683 else if (fnCandidate.getName().compare("textureProjOffset") == 0) 1684 arg = 2; 1685 else if (fnCandidate.getName().compare("textureLodOffset") == 0) 1686 arg = 3; 1687 else if (fnCandidate.getName().compare("textureProjLodOffset") == 0) 1688 arg = 3; 1689 else if (fnCandidate.getName().compare("textureGradOffset") == 0) 1690 arg = 4; 1691 else if (fnCandidate.getName().compare("textureProjGradOffset") == 0) 1692 arg = 4; 1693 1694 if (arg > 0) { 1695 if (! callNode.getSequence()[arg]->getAsConstantUnion()) 1696 error(loc, "argument must be compile-time constant", "texel offset", ""); 1697 else { 1698 const TType& type = callNode.getSequence()[arg]->getAsTyped()->getType(); 1699 for (int c = 0; c < type.getVectorSize(); ++c) { 1700 int offset = callNode.getSequence()[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); 1701 if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) 1702 error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); 1703 } 1704 } 1705 } 1706 } 1707 } 1708 } 1709 1710 // GL_ARB_shader_texture_image_samples 1711 if (fnCandidate.getName().compare(0, 14, "textureSamples") == 0 || fnCandidate.getName().compare(0, 12, "imageSamples") == 0) 1712 profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); 1713 1714 if (fnCandidate.getName().compare(0, 11, "imageAtomic") == 0) { 1715 const TType& imageType = callNode.getSequence()[0]->getAsTyped()->getType(); 1716 if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { 1717 if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui) 1718 error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); 1719 } else { 1720 if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) 1721 error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); 1722 else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile) 1723 error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); 1724 } 1725 } 1726 } 1727 1728 // 1729 // Do any extra checking for a user function call. 1730 // 1731 void TParseContext::userFunctionCallCheck(const TSourceLoc& loc, TIntermAggregate& callNode) 1732 { 1733 TIntermSequence& arguments = callNode.getSequence(); 1734 1735 for (int i = 0; i < (int)arguments.size(); ++i) 1736 samplerConstructorLocationCheck(loc, "call argument", arguments[i]); 1737 } 1738 1739 // 1740 // Emit an error if this is a sampler constructor 1741 // 1742 void TParseContext::samplerConstructorLocationCheck(const TSourceLoc& loc, const char* token, TIntermNode* node) 1743 { 1744 if (node->getAsOperator() && node->getAsOperator()->getOp() == EOpConstructTextureSampler) 1745 error(loc, "sampler constructor must appear at point of use", token, ""); 1746 } 1747 1748 // 1749 // Handle seeing a built-in constructor in a grammar production. 1750 // 1751 TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType) 1752 { 1753 TType type(publicType); 1754 type.getQualifier().precision = EpqNone; 1755 1756 if (type.isArray()) { 1757 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed constructor"); 1758 profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor"); 1759 } 1760 1761 TOperator op = intermediate.mapTypeToConstructorOp(type); 1762 1763 if (op == EOpNull) { 1764 error(loc, "cannot construct this type", type.getBasicString(), ""); 1765 op = EOpConstructFloat; 1766 TType errorType(EbtFloat); 1767 type.shallowCopy(errorType); 1768 } 1769 1770 TString empty(""); 1771 1772 return new TFunction(&empty, type, op); 1773 } 1774 1775 // Handle seeing a precision qualifier in the grammar. 1776 void TParseContext::handlePrecisionQualifier(const TSourceLoc& /*loc*/, TQualifier& qualifier, TPrecisionQualifier precision) 1777 { 1778 if (obeyPrecisionQualifiers()) 1779 qualifier.precision = precision; 1780 } 1781 1782 // Check for messages to give on seeing a precision qualifier used in a 1783 // declaration in the grammar. 1784 void TParseContext::checkPrecisionQualifier(const TSourceLoc& loc, TPrecisionQualifier) 1785 { 1786 if (precisionManager.shouldWarnAboutDefaults()) { 1787 warn(loc, "all default precisions are highp; use precision statements to quiet warning, e.g.:\n" 1788 " \"precision mediump int; precision highp float;\"", "", ""); 1789 precisionManager.defaultWarningGiven(); 1790 } 1791 } 1792 1793 // 1794 // Same error message for all places assignments don't work. 1795 // 1796 void TParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right) 1797 { 1798 error(loc, "", op, "cannot convert from '%s' to '%s'", 1799 right.c_str(), left.c_str()); 1800 } 1801 1802 // 1803 // Same error message for all places unary operations don't work. 1804 // 1805 void TParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand) 1806 { 1807 error(loc, " wrong operand type", op, 1808 "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)", 1809 op, operand.c_str()); 1810 } 1811 1812 // 1813 // Same error message for all binary operations don't work. 1814 // 1815 void TParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right) 1816 { 1817 error(loc, " wrong operand types:", op, 1818 "no operation '%s' exists that takes a left-hand operand of type '%s' and " 1819 "a right operand of type '%s' (or there is no acceptable conversion)", 1820 op, left.c_str(), right.c_str()); 1821 } 1822 1823 // 1824 // A basic type of EbtVoid is a key that the name string was seen in the source, but 1825 // it was not found as a variable in the symbol table. If so, give the error 1826 // message and insert a dummy variable in the symbol table to prevent future errors. 1827 // 1828 void TParseContext::variableCheck(TIntermTyped*& nodePtr) 1829 { 1830 TIntermSymbol* symbol = nodePtr->getAsSymbolNode(); 1831 if (! symbol) 1832 return; 1833 1834 if (symbol->getType().getBasicType() == EbtVoid) { 1835 const char *extraInfoFormat = ""; 1836 if (spvVersion.vulkan != 0 && symbol->getName() == "gl_VertexID") { 1837 extraInfoFormat = "(Did you mean gl_VertexIndex?)"; 1838 } else if (spvVersion.vulkan != 0 && symbol->getName() == "gl_InstanceID") { 1839 extraInfoFormat = "(Did you mean gl_InstanceIndex?)"; 1840 } 1841 error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), extraInfoFormat); 1842 1843 // Add to symbol table to prevent future error messages on the same name 1844 if (symbol->getName().size() > 0) { 1845 TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat)); 1846 symbolTable.insert(*fakeVariable); 1847 1848 // substitute a symbol node for this new variable 1849 nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc()); 1850 } 1851 } else { 1852 switch (symbol->getQualifier().storage) { 1853 case EvqPointCoord: 1854 profileRequires(symbol->getLoc(), ENoProfile, 120, nullptr, "gl_PointCoord"); 1855 break; 1856 default: break; // some compilers want this 1857 } 1858 } 1859 } 1860 1861 // 1862 // Both test and if necessary, spit out an error, to see if the node is really 1863 // an l-value that can be operated on this way. 1864 // 1865 // Returns true if there was an error. 1866 // 1867 bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) 1868 { 1869 TIntermBinary* binaryNode = node->getAsBinaryNode(); 1870 1871 if (binaryNode) { 1872 bool errorReturn = false; 1873 1874 switch(binaryNode->getOp()) { 1875 case EOpIndexDirect: 1876 case EOpIndexIndirect: 1877 // ... tessellation control shader ... 1878 // If a per-vertex output variable is used as an l-value, it is a 1879 // compile-time or link-time error if the expression indicating the 1880 // vertex index is not the identifier gl_InvocationID. 1881 if (language == EShLangTessControl) { 1882 const TType& leftType = binaryNode->getLeft()->getType(); 1883 if (leftType.getQualifier().storage == EvqVaryingOut && ! leftType.getQualifier().patch && binaryNode->getLeft()->getAsSymbolNode()) { 1884 // we have a per-vertex output 1885 const TIntermSymbol* rightSymbol = binaryNode->getRight()->getAsSymbolNode(); 1886 if (! rightSymbol || rightSymbol->getQualifier().builtIn != EbvInvocationId) 1887 error(loc, "tessellation-control per-vertex output l-value must be indexed with gl_InvocationID", "[]", ""); 1888 } 1889 } 1890 1891 break; // left node is checked by base class 1892 case EOpIndexDirectStruct: 1893 break; // left node is checked by base class 1894 case EOpVectorSwizzle: 1895 errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft()); 1896 if (!errorReturn) { 1897 int offset[4] = {0,0,0,0}; 1898 1899 TIntermTyped* rightNode = binaryNode->getRight(); 1900 TIntermAggregate *aggrNode = rightNode->getAsAggregate(); 1901 1902 for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 1903 p != aggrNode->getSequence().end(); p++) { 1904 int value = (*p)->getAsTyped()->getAsConstantUnion()->getConstArray()[0].getIConst(); 1905 offset[value]++; 1906 if (offset[value] > 1) { 1907 error(loc, " l-value of swizzle cannot have duplicate components", op, "", ""); 1908 1909 return true; 1910 } 1911 } 1912 } 1913 1914 return errorReturn; 1915 default: 1916 break; 1917 } 1918 1919 if (errorReturn) { 1920 error(loc, " l-value required", op, "", ""); 1921 return true; 1922 } 1923 } 1924 1925 // Let the base class check errors 1926 if (TParseContextBase::lValueErrorCheck(loc, op, node)) 1927 return true; 1928 1929 const char* symbol = nullptr; 1930 TIntermSymbol* symNode = node->getAsSymbolNode(); 1931 if (symNode != nullptr) 1932 symbol = symNode->getName().c_str(); 1933 1934 const char* message = nullptr; 1935 switch (node->getQualifier().storage) { 1936 case EvqVaryingIn: message = "can't modify shader input"; break; 1937 case EvqInstanceId: message = "can't modify gl_InstanceID"; break; 1938 case EvqVertexId: message = "can't modify gl_VertexID"; break; 1939 case EvqFace: message = "can't modify gl_FrontFace"; break; 1940 case EvqFragCoord: message = "can't modify gl_FragCoord"; break; 1941 case EvqPointCoord: message = "can't modify gl_PointCoord"; break; 1942 case EvqFragDepth: 1943 intermediate.setDepthReplacing(); 1944 // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader." 1945 if (profile == EEsProfile && intermediate.getEarlyFragmentTests()) 1946 message = "can't modify gl_FragDepth if using early_fragment_tests"; 1947 break; 1948 1949 default: 1950 break; 1951 } 1952 1953 if (message == nullptr && binaryNode == nullptr && symNode == nullptr) { 1954 error(loc, " l-value required", op, "", ""); 1955 1956 return true; 1957 } 1958 1959 // 1960 // Everything else is okay, no error. 1961 // 1962 if (message == nullptr) 1963 return false; 1964 1965 // 1966 // If we get here, we have an error and a message. 1967 // 1968 if (symNode) 1969 error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); 1970 else 1971 error(loc, " l-value required", op, "(%s)", message); 1972 1973 return true; 1974 } 1975 1976 // Test for and give an error if the node can't be read from. 1977 void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) 1978 { 1979 // Let the base class check errors 1980 TParseContextBase::rValueErrorCheck(loc, op, node); 1981 1982 #ifdef AMD_EXTENSIONS 1983 TIntermSymbol* symNode = node->getAsSymbolNode(); 1984 if (!(symNode && symNode->getQualifier().writeonly)) // base class checks 1985 if (symNode && symNode->getQualifier().explicitInterp) 1986 error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str()); 1987 #endif 1988 } 1989 1990 // 1991 // Both test, and if necessary spit out an error, to see if the node is really 1992 // a constant. 1993 // 1994 void TParseContext::constantValueCheck(TIntermTyped* node, const char* token) 1995 { 1996 if (! node->getQualifier().isConstant()) 1997 error(node->getLoc(), "constant expression required", token, ""); 1998 } 1999 2000 // 2001 // Both test, and if necessary spit out an error, to see if the node is really 2002 // an integer. 2003 // 2004 void TParseContext::integerCheck(const TIntermTyped* node, const char* token) 2005 { 2006 if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar()) 2007 return; 2008 2009 error(node->getLoc(), "scalar integer expression required", token, ""); 2010 } 2011 2012 // 2013 // Both test, and if necessary spit out an error, to see if we are currently 2014 // globally scoped. 2015 // 2016 void TParseContext::globalCheck(const TSourceLoc& loc, const char* token) 2017 { 2018 if (! symbolTable.atGlobalLevel()) 2019 error(loc, "not allowed in nested scope", token, ""); 2020 } 2021 2022 // 2023 // Reserved errors for GLSL. 2024 // 2025 void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& identifier) 2026 { 2027 // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be 2028 // declared in a shader; this results in a compile-time error." 2029 if (! symbolTable.atBuiltInLevel()) { 2030 if (builtInName(identifier)) 2031 error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), ""); 2032 2033 // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification: 2034 // "In addition, all identifiers containing two consecutive underscores (__) are 2035 // reserved; using such a name does not itself result in an error, but may result 2036 // in undefined behavior." 2037 // however, before that, ES tests required an error. 2038 if (identifier.find("__") != TString::npos) { 2039 if (profile == EEsProfile && version <= 300) 2040 error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version <= 300", identifier.c_str(), ""); 2041 else 2042 warn(loc, "identifiers containing consecutive underscores (\"__\") are reserved", identifier.c_str(), ""); 2043 } 2044 } 2045 } 2046 2047 // 2048 // Reserved errors for the preprocessor. 2049 // 2050 void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* identifier, const char* op) 2051 { 2052 // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification: 2053 // "All macro names containing two consecutive underscores ( __ ) are reserved; 2054 // defining such a name does not itself result in an error, but may result in 2055 // undefined behavior. All macro names prefixed with "GL_" ("GL" followed by a 2056 // single underscore) are also reserved, and defining such a name results in a 2057 // compile-time error." 2058 // however, before that, ES tests required an error. 2059 if (strncmp(identifier, "GL_", 3) == 0) 2060 ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier); 2061 else if (strncmp(identifier, "defined", 8) == 0) 2062 ppError(loc, "\"defined\" can't be (un)defined:", op, identifier); 2063 else if (strstr(identifier, "__") != 0) { 2064 if (profile == EEsProfile && version >= 300 && 2065 (strcmp(identifier, "__LINE__") == 0 || 2066 strcmp(identifier, "__FILE__") == 0 || 2067 strcmp(identifier, "__VERSION__") == 0)) 2068 ppError(loc, "predefined names can't be (un)defined:", op, identifier); 2069 else { 2070 if (profile == EEsProfile && version <= 300) 2071 ppError(loc, "names containing consecutive underscores are reserved, and an error if version <= 300:", op, identifier); 2072 else 2073 ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier); 2074 } 2075 } 2076 } 2077 2078 // 2079 // See if this version/profile allows use of the line-continuation character '\'. 2080 // 2081 // Returns true if a line continuation should be done. 2082 // 2083 bool TParseContext::lineContinuationCheck(const TSourceLoc& loc, bool endOfComment) 2084 { 2085 const char* message = "line continuation"; 2086 2087 bool lineContinuationAllowed = (profile == EEsProfile && version >= 300) || 2088 (profile != EEsProfile && (version >= 420 || extensionTurnedOn(E_GL_ARB_shading_language_420pack))); 2089 2090 if (endOfComment) { 2091 if (lineContinuationAllowed) 2092 warn(loc, "used at end of comment; the following line is still part of the comment", message, ""); 2093 else 2094 warn(loc, "used at end of comment, but this version does not provide line continuation", message, ""); 2095 2096 return lineContinuationAllowed; 2097 } 2098 2099 if (relaxedErrors()) { 2100 if (! lineContinuationAllowed) 2101 warn(loc, "not allowed in this version", message, ""); 2102 return true; 2103 } else { 2104 profileRequires(loc, EEsProfile, 300, nullptr, message); 2105 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, message); 2106 } 2107 2108 return lineContinuationAllowed; 2109 } 2110 2111 bool TParseContext::builtInName(const TString& identifier) 2112 { 2113 return identifier.compare(0, 3, "gl_") == 0; 2114 } 2115 2116 // 2117 // Make sure there is enough data and not too many arguments provided to the 2118 // constructor to build something of the type of the constructor. Also returns 2119 // the type of the constructor. 2120 // 2121 // Part of establishing type is establishing specialization-constness. 2122 // We don't yet know "top down" whether type is a specialization constant, 2123 // but a const constructor can becomes a specialization constant if any of 2124 // its children are, subject to KHR_vulkan_glsl rules: 2125 // 2126 // - int(), uint(), and bool() constructors for type conversions 2127 // from any of the following types to any of the following types: 2128 // * int 2129 // * uint 2130 // * bool 2131 // - vector versions of the above conversion constructors 2132 // 2133 // Returns true if there was an error in construction. 2134 // 2135 bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, TOperator op, TType& type) 2136 { 2137 type.shallowCopy(function.getType()); 2138 2139 bool constructingMatrix = false; 2140 switch(op) { 2141 case EOpConstructTextureSampler: 2142 return constructorTextureSamplerError(loc, function); 2143 case EOpConstructMat2x2: 2144 case EOpConstructMat2x3: 2145 case EOpConstructMat2x4: 2146 case EOpConstructMat3x2: 2147 case EOpConstructMat3x3: 2148 case EOpConstructMat3x4: 2149 case EOpConstructMat4x2: 2150 case EOpConstructMat4x3: 2151 case EOpConstructMat4x4: 2152 case EOpConstructDMat2x2: 2153 case EOpConstructDMat2x3: 2154 case EOpConstructDMat2x4: 2155 case EOpConstructDMat3x2: 2156 case EOpConstructDMat3x3: 2157 case EOpConstructDMat3x4: 2158 case EOpConstructDMat4x2: 2159 case EOpConstructDMat4x3: 2160 case EOpConstructDMat4x4: 2161 #ifdef AMD_EXTENSIONS 2162 case EOpConstructF16Mat2x2: 2163 case EOpConstructF16Mat2x3: 2164 case EOpConstructF16Mat2x4: 2165 case EOpConstructF16Mat3x2: 2166 case EOpConstructF16Mat3x3: 2167 case EOpConstructF16Mat3x4: 2168 case EOpConstructF16Mat4x2: 2169 case EOpConstructF16Mat4x3: 2170 case EOpConstructF16Mat4x4: 2171 #endif 2172 constructingMatrix = true; 2173 break; 2174 default: 2175 break; 2176 } 2177 2178 // 2179 // Walk the arguments for first-pass checks and collection of information. 2180 // 2181 2182 int size = 0; 2183 bool constType = true; 2184 bool specConstType = false; // value is only valid if constType is true 2185 bool full = false; 2186 bool overFull = false; 2187 bool matrixInMatrix = false; 2188 bool arrayArg = false; 2189 bool floatArgument = false; 2190 for (int arg = 0; arg < function.getParamCount(); ++arg) { 2191 if (function[arg].type->isArray()) { 2192 if (! function[arg].type->isExplicitlySizedArray()) { 2193 // Can't construct from an unsized array. 2194 error(loc, "array argument must be sized", "constructor", ""); 2195 return true; 2196 } 2197 arrayArg = true; 2198 } 2199 if (constructingMatrix && function[arg].type->isMatrix()) 2200 matrixInMatrix = true; 2201 2202 // 'full' will go to true when enough args have been seen. If we loop 2203 // again, there is an extra argument. 2204 if (full) { 2205 // For vectors and matrices, it's okay to have too many components 2206 // available, but not okay to have unused arguments. 2207 overFull = true; 2208 } 2209 2210 size += function[arg].type->computeNumComponents(); 2211 if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) 2212 full = true; 2213 2214 if (! function[arg].type->getQualifier().isConstant()) 2215 constType = false; 2216 if (function[arg].type->getQualifier().isSpecConstant()) 2217 specConstType = true; 2218 if (function[arg].type->isFloatingDomain()) 2219 floatArgument = true; 2220 } 2221 2222 // inherit constness from children 2223 if (constType) { 2224 bool makeSpecConst; 2225 // Finish pinning down spec-const semantics 2226 if (specConstType) { 2227 switch (op) { 2228 case EOpConstructInt: 2229 case EOpConstructUint: 2230 case EOpConstructInt64: 2231 case EOpConstructUint64: 2232 #ifdef AMD_EXTENSIONS 2233 case EOpConstructInt16: 2234 case EOpConstructUint16: 2235 #endif 2236 case EOpConstructBool: 2237 case EOpConstructBVec2: 2238 case EOpConstructBVec3: 2239 case EOpConstructBVec4: 2240 case EOpConstructIVec2: 2241 case EOpConstructIVec3: 2242 case EOpConstructIVec4: 2243 case EOpConstructUVec2: 2244 case EOpConstructUVec3: 2245 case EOpConstructUVec4: 2246 case EOpConstructI64Vec2: 2247 case EOpConstructI64Vec3: 2248 case EOpConstructI64Vec4: 2249 case EOpConstructU64Vec2: 2250 case EOpConstructU64Vec3: 2251 case EOpConstructU64Vec4: 2252 #ifdef AMD_EXTENSIONS 2253 case EOpConstructI16Vec2: 2254 case EOpConstructI16Vec3: 2255 case EOpConstructI16Vec4: 2256 case EOpConstructU16Vec2: 2257 case EOpConstructU16Vec3: 2258 case EOpConstructU16Vec4: 2259 #endif 2260 // This was the list of valid ones, if they aren't converting from float 2261 // and aren't making an array. 2262 makeSpecConst = ! floatArgument && ! type.isArray(); 2263 break; 2264 default: 2265 // anything else wasn't white-listed in the spec as a conversion 2266 makeSpecConst = false; 2267 break; 2268 } 2269 } else 2270 makeSpecConst = false; 2271 2272 if (makeSpecConst) 2273 type.getQualifier().makeSpecConstant(); 2274 else if (specConstType) 2275 type.getQualifier().makeTemporary(); 2276 else 2277 type.getQualifier().storage = EvqConst; 2278 } 2279 2280 if (type.isArray()) { 2281 if (function.getParamCount() == 0) { 2282 error(loc, "array constructor must have at least one argument", "constructor", ""); 2283 return true; 2284 } 2285 2286 if (type.isImplicitlySizedArray()) { 2287 // auto adapt the constructor type to the number of arguments 2288 type.changeOuterArraySize(function.getParamCount()); 2289 } else if (type.getOuterArraySize() != function.getParamCount()) { 2290 error(loc, "array constructor needs one argument per array element", "constructor", ""); 2291 return true; 2292 } 2293 2294 if (type.isArrayOfArrays()) { 2295 // Types have to match, but we're still making the type. 2296 // Finish making the type, and the comparison is done later 2297 // when checking for conversion. 2298 TArraySizes& arraySizes = type.getArraySizes(); 2299 2300 // At least the dimensionalities have to match. 2301 if (! function[0].type->isArray() || arraySizes.getNumDims() != function[0].type->getArraySizes().getNumDims() + 1) { 2302 error(loc, "array constructor argument not correct type to construct array element", "constructor", ""); 2303 return true; 2304 } 2305 2306 if (arraySizes.isInnerImplicit()) { 2307 // "Arrays of arrays ..., and the size for any dimension is optional" 2308 // That means we need to adopt (from the first argument) the other array sizes into the type. 2309 for (int d = 1; d < arraySizes.getNumDims(); ++d) { 2310 if (arraySizes.getDimSize(d) == UnsizedArraySize) { 2311 arraySizes.setDimSize(d, function[0].type->getArraySizes().getDimSize(d - 1)); 2312 } 2313 } 2314 } 2315 } 2316 } 2317 2318 if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { 2319 error(loc, "constructing non-array constituent from array argument", "constructor", ""); 2320 return true; 2321 } 2322 2323 if (matrixInMatrix && ! type.isArray()) { 2324 profileRequires(loc, ENoProfile, 120, nullptr, "constructing matrix from matrix"); 2325 2326 // "If a matrix argument is given to a matrix constructor, 2327 // it is a compile-time error to have any other arguments." 2328 if (function.getParamCount() != 1) 2329 error(loc, "matrix constructed from matrix can only have one argument", "constructor", ""); 2330 return false; 2331 } 2332 2333 if (overFull) { 2334 error(loc, "too many arguments", "constructor", ""); 2335 return true; 2336 } 2337 2338 if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) { 2339 error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); 2340 return true; 2341 } 2342 2343 if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) || 2344 (op == EOpConstructStruct && size < type.computeNumComponents())) { 2345 error(loc, "not enough data provided for construction", "constructor", ""); 2346 return true; 2347 } 2348 2349 TIntermTyped* typed = node->getAsTyped(); 2350 if (typed == nullptr) { 2351 error(loc, "constructor argument does not have a type", "constructor", ""); 2352 return true; 2353 } 2354 if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) { 2355 error(loc, "cannot convert a sampler", "constructor", ""); 2356 return true; 2357 } 2358 if (op != EOpConstructStruct && typed->getBasicType() == EbtAtomicUint) { 2359 error(loc, "cannot convert an atomic_uint", "constructor", ""); 2360 return true; 2361 } 2362 if (typed->getBasicType() == EbtVoid) { 2363 error(loc, "cannot convert a void", "constructor", ""); 2364 return true; 2365 } 2366 2367 return false; 2368 } 2369 2370 // Verify all the correct semantics for constructing a combined texture/sampler. 2371 // Return true if the semantics are incorrect. 2372 bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function) 2373 { 2374 TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change 2375 const char* token = constructorName.c_str(); 2376 2377 // exactly two arguments needed 2378 if (function.getParamCount() != 2) { 2379 error(loc, "sampler-constructor requires two arguments", token, ""); 2380 return true; 2381 } 2382 2383 // For now, not allowing arrayed constructors, the rest of this function 2384 // is set up to allow them, if this test is removed: 2385 if (function.getType().isArray()) { 2386 error(loc, "sampler-constructor cannot make an array of samplers", token, ""); 2387 return true; 2388 } 2389 2390 // first argument 2391 // * the constructor's first argument must be a texture type 2392 // * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array) 2393 // of the texture type must match that of the constructed sampler type 2394 // (that is, the suffixes of the type of the first argument and the 2395 // type of the constructor will be spelled the same way) 2396 if (function[0].type->getBasicType() != EbtSampler || 2397 ! function[0].type->getSampler().isTexture() || 2398 function[0].type->isArray()) { 2399 error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, ""); 2400 return true; 2401 } 2402 // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=() 2403 TSampler texture = function.getType().getSampler(); 2404 texture.combined = false; 2405 texture.shadow = false; 2406 if (texture != function[0].type->getSampler()) { 2407 error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, ""); 2408 return true; 2409 } 2410 2411 // second argument 2412 // * the constructor's second argument must be a scalar of type 2413 // *sampler* or *samplerShadow* 2414 // * the presence or absence of depth comparison (Shadow) must match 2415 // between the constructed sampler type and the type of the second argument 2416 if ( function[1].type->getBasicType() != EbtSampler || 2417 ! function[1].type->getSampler().isPureSampler() || 2418 function[1].type->isArray()) { 2419 error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, ""); 2420 return true; 2421 } 2422 if (function.getType().getSampler().shadow != function[1].type->getSampler().shadow) { 2423 error(loc, "sampler-constructor second argument presence of shadow must match constructor presence of shadow", token, ""); 2424 return true; 2425 } 2426 2427 return false; 2428 } 2429 2430 // Checks to see if a void variable has been declared and raise an error message for such a case 2431 // 2432 // returns true in case of an error 2433 // 2434 bool TParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType) 2435 { 2436 if (basicType == EbtVoid) { 2437 error(loc, "illegal use of type 'void'", identifier.c_str(), ""); 2438 return true; 2439 } 2440 2441 return false; 2442 } 2443 2444 // Checks to see if the node (for the expression) contains a scalar boolean expression or not 2445 void TParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type) 2446 { 2447 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) 2448 error(loc, "boolean expression expected", "", ""); 2449 } 2450 2451 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not 2452 void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType) 2453 { 2454 if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) 2455 error(loc, "boolean expression expected", "", ""); 2456 } 2457 2458 void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/) 2459 { 2460 if (type.getQualifier().storage == EvqUniform) 2461 return; 2462 2463 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler)) 2464 error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str()); 2465 else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) { 2466 // non-uniform sampler 2467 // not yet: okay if it has an initializer 2468 // if (! initializer) 2469 error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); 2470 } 2471 } 2472 2473 void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) 2474 { 2475 if (type.getQualifier().storage == EvqUniform) 2476 return; 2477 2478 if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAtomicUint)) 2479 error(loc, "non-uniform struct contains an atomic_uint:", type.getBasicTypeString().c_str(), identifier.c_str()); 2480 else if (type.getBasicType() == EbtAtomicUint && type.getQualifier().storage != EvqUniform) 2481 error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); 2482 } 2483 2484 void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) 2485 { 2486 if (parsingBuiltins) 2487 return; 2488 2489 if (type.getQualifier().storage != EvqUniform) 2490 return; 2491 2492 if (type.containsNonOpaque()) { 2493 // Vulkan doesn't allow transparent uniforms outside of blocks 2494 if (spvVersion.vulkan > 0) 2495 vulkanRemoved(loc, "non-opaque uniforms outside a block"); 2496 // OpenGL wants locations on these (unless they are getting automapped) 2497 if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations()) 2498 error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), ""); 2499 } 2500 } 2501 2502 // 2503 // Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. 2504 // 2505 void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier) 2506 { 2507 // move from parameter/unknown qualifiers to pipeline in/out qualifiers 2508 switch (qualifier.storage) { 2509 case EvqIn: 2510 profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs"); 2511 profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs"); 2512 qualifier.storage = EvqVaryingIn; 2513 break; 2514 case EvqOut: 2515 profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs"); 2516 profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs"); 2517 qualifier.storage = EvqVaryingOut; 2518 break; 2519 case EvqInOut: 2520 qualifier.storage = EvqVaryingIn; 2521 error(loc, "cannot use 'inout' at global scope", "", ""); 2522 break; 2523 default: 2524 break; 2525 } 2526 2527 invariantCheck(loc, qualifier); 2528 } 2529 2530 // 2531 // Check a full qualifier and type (no variable yet) at global level. 2532 // 2533 void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TPublicType& publicType) 2534 { 2535 if (! symbolTable.atGlobalLevel()) 2536 return; 2537 2538 if (qualifier.isMemory() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) 2539 error(loc, "memory qualifiers cannot be used on this type", "", ""); 2540 2541 if (qualifier.storage == EvqBuffer && publicType.basicType != EbtBlock) 2542 error(loc, "buffers can be declared only as blocks", "buffer", ""); 2543 2544 if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) 2545 return; 2546 2547 if (publicType.shaderQualifiers.blendEquation) 2548 error(loc, "can only be applied to a standalone 'out'", "blend equation", ""); 2549 2550 // now, knowing it is a shader in/out, do all the in/out semantic checks 2551 2552 if (publicType.basicType == EbtBool) { 2553 error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), ""); 2554 return; 2555 } 2556 2557 if (publicType.basicType == EbtInt || publicType.basicType == EbtUint || 2558 #ifdef AMD_EXTENSIONS 2559 publicType.basicType == EbtInt16 || publicType.basicType == EbtUint16 || 2560 #endif 2561 publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 || 2562 publicType.basicType == EbtDouble) 2563 profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output"); 2564 2565 #ifdef AMD_EXTENSIONS 2566 if (! qualifier.flat && ! qualifier.explicitInterp) { 2567 #else 2568 if (!qualifier.flat) { 2569 #endif 2570 if (publicType.basicType == EbtInt || publicType.basicType == EbtUint || 2571 #ifdef AMD_EXTENSIONS 2572 publicType.basicType == EbtInt16 || publicType.basicType == EbtUint16 || 2573 #endif 2574 publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 || 2575 publicType.basicType == EbtDouble || 2576 (publicType.userDef && (publicType.userDef->containsBasicType(EbtInt) || 2577 publicType.userDef->containsBasicType(EbtUint) || 2578 publicType.userDef->containsBasicType(EbtInt64) || 2579 publicType.userDef->containsBasicType(EbtUint64) || 2580 publicType.userDef->containsBasicType(EbtDouble)))) { 2581 if (qualifier.storage == EvqVaryingIn && language == EShLangFragment) 2582 error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); 2583 else if (qualifier.storage == EvqVaryingOut && language == EShLangVertex && version == 300) 2584 error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); 2585 } 2586 } 2587 2588 if (qualifier.patch && qualifier.isInterpolation()) 2589 error(loc, "cannot use interpolation qualifiers with patch", "patch", ""); 2590 2591 if (qualifier.storage == EvqVaryingIn) { 2592 switch (language) { 2593 case EShLangVertex: 2594 if (publicType.basicType == EbtStruct) { 2595 error(loc, "cannot be a structure or array", GetStorageQualifierString(qualifier.storage), ""); 2596 return; 2597 } 2598 if (publicType.arraySizes) { 2599 requireProfile(loc, ~EEsProfile, "vertex input arrays"); 2600 profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); 2601 } 2602 if (publicType.basicType == EbtDouble) 2603 profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input"); 2604 if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant) 2605 error(loc, "vertex input cannot be further qualified", "", ""); 2606 break; 2607 2608 case EShLangTessControl: 2609 if (qualifier.patch) 2610 error(loc, "can only use on output in tessellation-control shader", "patch", ""); 2611 break; 2612 2613 case EShLangTessEvaluation: 2614 break; 2615 2616 case EShLangGeometry: 2617 break; 2618 2619 case EShLangFragment: 2620 if (publicType.userDef) { 2621 profileRequires(loc, EEsProfile, 300, nullptr, "fragment-shader struct input"); 2622 profileRequires(loc, ~EEsProfile, 150, nullptr, "fragment-shader struct input"); 2623 if (publicType.userDef->containsStructure()) 2624 requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing structure"); 2625 if (publicType.userDef->containsArray()) 2626 requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing an array"); 2627 } 2628 break; 2629 2630 case EShLangCompute: 2631 if (! symbolTable.atBuiltInLevel()) 2632 error(loc, "global storage input qualifier cannot be used in a compute shader", "in", ""); 2633 break; 2634 2635 default: 2636 break; 2637 } 2638 } else { 2639 // qualifier.storage == EvqVaryingOut 2640 switch (language) { 2641 case EShLangVertex: 2642 if (publicType.userDef) { 2643 profileRequires(loc, EEsProfile, 300, nullptr, "vertex-shader struct output"); 2644 profileRequires(loc, ~EEsProfile, 150, nullptr, "vertex-shader struct output"); 2645 if (publicType.userDef->containsStructure()) 2646 requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing structure"); 2647 if (publicType.userDef->containsArray()) 2648 requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing an array"); 2649 } 2650 2651 break; 2652 2653 case EShLangTessControl: 2654 break; 2655 2656 case EShLangTessEvaluation: 2657 if (qualifier.patch) 2658 error(loc, "can only use on input in tessellation-evaluation shader", "patch", ""); 2659 break; 2660 2661 case EShLangGeometry: 2662 break; 2663 2664 case EShLangFragment: 2665 profileRequires(loc, EEsProfile, 300, nullptr, "fragment shader output"); 2666 if (publicType.basicType == EbtStruct) { 2667 error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), ""); 2668 return; 2669 } 2670 if (publicType.matrixRows > 0) { 2671 error(loc, "cannot be a matrix", GetStorageQualifierString(qualifier.storage), ""); 2672 return; 2673 } 2674 if (qualifier.isAuxiliary()) 2675 error(loc, "can't use auxiliary qualifier on a fragment output", "centroid/sample/patch", ""); 2676 if (qualifier.isInterpolation()) 2677 error(loc, "can't use interpolation qualifier on a fragment output", "flat/smooth/noperspective", ""); 2678 if (publicType.basicType == EbtDouble) 2679 error(loc, "cannot contain a double", GetStorageQualifierString(qualifier.storage), ""); 2680 break; 2681 2682 case EShLangCompute: 2683 error(loc, "global storage output qualifier cannot be used in a compute shader", "out", ""); 2684 break; 2685 2686 default: 2687 break; 2688 } 2689 } 2690 } 2691 2692 // 2693 // Merge characteristics of the 'src' qualifier into the 'dst'. 2694 // If there is duplication, issue error messages, unless 'force' 2695 // is specified, which means to just override default settings. 2696 // 2697 // Also, when force is false, it will be assumed that 'src' follows 2698 // 'dst', for the purpose of error checking order for versions 2699 // that require specific orderings of qualifiers. 2700 // 2701 void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, const TQualifier& src, bool force) 2702 { 2703 // Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers') 2704 if (src.isAuxiliary() && dst.isAuxiliary()) 2705 error(loc, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", ""); 2706 2707 // Multiple interpolation qualifiers (mostly done later by 'individual qualifiers') 2708 if (src.isInterpolation() && dst.isInterpolation()) 2709 #ifdef AMD_EXTENSIONS 2710 error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective, __explicitInterpAMD)", "", ""); 2711 #else 2712 error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", ""); 2713 #endif 2714 2715 // Ordering 2716 if (! force && ((profile != EEsProfile && version < 420) || 2717 (profile == EEsProfile && version < 310)) 2718 && ! extensionTurnedOn(E_GL_ARB_shading_language_420pack)) { 2719 // non-function parameters 2720 if (src.noContraction && (dst.invariant || dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) 2721 error(loc, "precise qualifier must appear first", "", ""); 2722 if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) 2723 error(loc, "invariant qualifier must appear before interpolation, storage, and precision qualifiers ", "", ""); 2724 else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) 2725 error(loc, "interpolation qualifiers must appear before storage and precision qualifiers", "", ""); 2726 else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone)) 2727 error(loc, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", ""); 2728 else if (src.storage != EvqTemporary && (dst.precision != EpqNone)) 2729 error(loc, "precision qualifier must appear as last qualifier", "", ""); 2730 2731 // function parameters 2732 if (src.noContraction && (dst.storage == EvqConst || dst.storage == EvqIn || dst.storage == EvqOut)) 2733 error(loc, "precise qualifier must appear first", "", ""); 2734 if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut)) 2735 error(loc, "in/out must appear before const", "", ""); 2736 } 2737 2738 // Storage qualification 2739 if (dst.storage == EvqTemporary || dst.storage == EvqGlobal) 2740 dst.storage = src.storage; 2741 else if ((dst.storage == EvqIn && src.storage == EvqOut) || 2742 (dst.storage == EvqOut && src.storage == EvqIn)) 2743 dst.storage = EvqInOut; 2744 else if ((dst.storage == EvqIn && src.storage == EvqConst) || 2745 (dst.storage == EvqConst && src.storage == EvqIn)) 2746 dst.storage = EvqConstReadOnly; 2747 else if (src.storage != EvqTemporary && 2748 src.storage != EvqGlobal) 2749 error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), ""); 2750 2751 // Precision qualifiers 2752 if (! force && src.precision != EpqNone && dst.precision != EpqNone) 2753 error(loc, "only one precision qualifier allowed", GetPrecisionQualifierString(src.precision), ""); 2754 if (dst.precision == EpqNone || (force && src.precision != EpqNone)) 2755 dst.precision = src.precision; 2756 2757 // Layout qualifiers 2758 mergeObjectLayoutQualifiers(dst, src, false); 2759 2760 // individual qualifiers 2761 bool repeated = false; 2762 #define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field; 2763 MERGE_SINGLETON(invariant); 2764 MERGE_SINGLETON(noContraction); 2765 MERGE_SINGLETON(centroid); 2766 MERGE_SINGLETON(smooth); 2767 MERGE_SINGLETON(flat); 2768 MERGE_SINGLETON(nopersp); 2769 #ifdef AMD_EXTENSIONS 2770 MERGE_SINGLETON(explicitInterp); 2771 #endif 2772 MERGE_SINGLETON(patch); 2773 MERGE_SINGLETON(sample); 2774 MERGE_SINGLETON(coherent); 2775 MERGE_SINGLETON(volatil); 2776 MERGE_SINGLETON(restrict); 2777 MERGE_SINGLETON(readonly); 2778 MERGE_SINGLETON(writeonly); 2779 MERGE_SINGLETON(specConstant); 2780 2781 if (repeated) 2782 error(loc, "replicated qualifiers", "", ""); 2783 } 2784 2785 void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publicType, TPrecisionQualifier qualifier) 2786 { 2787 TBasicType basicType = publicType.basicType; 2788 2789 if (basicType == EbtSampler) { 2790 defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)] = qualifier; 2791 2792 return; // all is well 2793 } 2794 2795 if (basicType == EbtInt || basicType == EbtFloat) { 2796 if (publicType.isScalar()) { 2797 defaultPrecision[basicType] = qualifier; 2798 if (basicType == EbtInt) { 2799 defaultPrecision[EbtUint] = qualifier; 2800 precisionManager.explicitIntDefaultSeen(); 2801 } else 2802 precisionManager.explicitFloatDefaultSeen(); 2803 2804 return; // all is well 2805 } 2806 } 2807 2808 if (basicType == EbtAtomicUint) { 2809 if (qualifier != EpqHigh) 2810 error(loc, "can only apply highp to atomic_uint", "precision", ""); 2811 2812 return; 2813 } 2814 2815 error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), ""); 2816 } 2817 2818 // used to flatten the sampler type space into a single dimension 2819 // correlates with the declaration of defaultSamplerPrecision[] 2820 int TParseContext::computeSamplerTypeIndex(TSampler& sampler) 2821 { 2822 int arrayIndex = sampler.arrayed ? 1 : 0; 2823 int shadowIndex = sampler.shadow ? 1 : 0; 2824 int externalIndex = sampler.external? 1 : 0; 2825 int imageIndex = sampler.image ? 1 : 0; 2826 int msIndex = sampler.ms ? 1 : 0; 2827 2828 int flattened = EsdNumDims * (EbtNumTypes * (2 * (2 * (2 * (2 * arrayIndex + msIndex) + imageIndex) + shadowIndex) + 2829 externalIndex) + sampler.type) + sampler.dim; 2830 assert(flattened < maxSamplerIndex); 2831 2832 return flattened; 2833 } 2834 2835 TPrecisionQualifier TParseContext::getDefaultPrecision(TPublicType& publicType) 2836 { 2837 if (publicType.basicType == EbtSampler) 2838 return defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)]; 2839 else 2840 return defaultPrecision[publicType.basicType]; 2841 } 2842 2843 void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType baseType, TQualifier& qualifier) 2844 { 2845 // Built-in symbols are allowed some ambiguous precisions, to be pinned down 2846 // later by context. 2847 if (! obeyPrecisionQualifiers() || parsingBuiltins) 2848 return; 2849 2850 if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh) 2851 error(loc, "atomic counters can only be highp", "atomic_uint", ""); 2852 2853 if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) { 2854 if (qualifier.precision == EpqNone) { 2855 if (relaxedErrors()) 2856 warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "substituting 'mediump'"); 2857 else 2858 error(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), ""); 2859 qualifier.precision = EpqMedium; 2860 defaultPrecision[baseType] = EpqMedium; 2861 } 2862 } else if (qualifier.precision != EpqNone) 2863 error(loc, "type cannot have precision qualifier", TType::getBasicString(baseType), ""); 2864 } 2865 2866 void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type) 2867 { 2868 if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque()) 2869 error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), ""); 2870 } 2871 2872 bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType basicType) 2873 { 2874 if (type.getBasicType() == basicType) 2875 return true; 2876 2877 if (type.getBasicType() == EbtStruct) { 2878 const TTypeList& structure = *type.getStruct(); 2879 for (unsigned int i = 0; i < structure.size(); ++i) { 2880 if (containsFieldWithBasicType(*structure[i].type, basicType)) 2881 return true; 2882 } 2883 } 2884 2885 return false; 2886 } 2887 2888 // 2889 // Do size checking for an array type's size. 2890 // 2891 void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair) 2892 { 2893 bool isConst = false; 2894 sizePair.node = nullptr; 2895 2896 int size = 1; 2897 2898 TIntermConstantUnion* constant = expr->getAsConstantUnion(); 2899 if (constant) { 2900 // handle true (non-specialization) constant 2901 size = constant->getConstArray()[0].getIConst(); 2902 isConst = true; 2903 } else { 2904 // see if it's a specialization constant instead 2905 if (expr->getQualifier().isSpecConstant()) { 2906 isConst = true; 2907 sizePair.node = expr; 2908 TIntermSymbol* symbol = expr->getAsSymbolNode(); 2909 if (symbol && symbol->getConstArray().size() > 0) 2910 size = symbol->getConstArray()[0].getIConst(); 2911 } 2912 } 2913 2914 sizePair.size = size; 2915 2916 if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) { 2917 error(loc, "array size must be a constant integer expression", "", ""); 2918 return; 2919 } 2920 2921 if (size <= 0) { 2922 error(loc, "array size must be a positive integer", "", ""); 2923 return; 2924 } 2925 } 2926 2927 // 2928 // See if this qualifier can be an array. 2929 // 2930 // Returns true if there is an error. 2931 // 2932 bool TParseContext::arrayQualifierError(const TSourceLoc& loc, const TQualifier& qualifier) 2933 { 2934 if (qualifier.storage == EvqConst) { 2935 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "const array"); 2936 profileRequires(loc, EEsProfile, 300, nullptr, "const array"); 2937 } 2938 2939 if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) { 2940 requireProfile(loc, ~EEsProfile, "vertex input arrays"); 2941 profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); 2942 } 2943 2944 return false; 2945 } 2946 2947 // 2948 // See if this qualifier and type combination can be an array. 2949 // Assumes arrayQualifierError() was also called to catch the type-invariant tests. 2950 // 2951 // Returns true if there is an error. 2952 // 2953 bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type) 2954 { 2955 if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) { 2956 if (type.isArrayOfArrays()) 2957 requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output"); 2958 else if (type.isStruct()) 2959 requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output"); 2960 } 2961 if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) { 2962 if (type.isArrayOfArrays()) 2963 requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input"); 2964 else if (type.isStruct()) 2965 requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input"); 2966 } 2967 if (type.getQualifier().storage == EvqVaryingOut && language == EShLangFragment) { 2968 if (type.isArrayOfArrays()) 2969 requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array output"); 2970 } 2971 2972 return false; 2973 } 2974 2975 // 2976 // Require array to be completely sized 2977 // 2978 void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes) 2979 { 2980 if (arraySizes.isImplicit()) 2981 error(loc, "array size required", "", ""); 2982 } 2983 2984 void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type) 2985 { 2986 const TTypeList& structure = *type.getStruct(); 2987 for (int m = 0; m < (int)structure.size(); ++m) { 2988 const TType& member = *structure[m].type; 2989 if (member.isArray()) 2990 arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes()); 2991 } 2992 } 2993 2994 void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember) 2995 { 2996 assert(arraySizes); 2997 2998 // always allow special built-in ins/outs sized to topologies 2999 if (parsingBuiltins) 3000 return; 3001 3002 // always allow an initializer to set any unknown array sizes 3003 if (initializer) 3004 return; 3005 3006 // No environment allows any non-outer-dimension to be implicitly sized 3007 if (arraySizes->isInnerImplicit()) 3008 error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", ""); 3009 3010 if (arraySizes->isInnerSpecialization()) 3011 error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", ""); 3012 3013 // desktop always allows outer-dimension-unsized variable arrays, 3014 if (profile != EEsProfile) 3015 return; 3016 3017 // for ES, if size isn't coming from an initializer, it has to be explicitly declared now, 3018 // with very few exceptions 3019 3020 // last member of ssbo block exception: 3021 if (qualifier.storage == EvqBuffer && lastMember) 3022 return; 3023 3024 // implicitly-sized io exceptions: 3025 switch (language) { 3026 case EShLangGeometry: 3027 if (qualifier.storage == EvqVaryingIn) 3028 if ((profile == EEsProfile && version >= 320) || 3029 extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader)) 3030 return; 3031 break; 3032 case EShLangTessControl: 3033 if ( qualifier.storage == EvqVaryingIn || 3034 (qualifier.storage == EvqVaryingOut && ! qualifier.patch)) 3035 if ((profile == EEsProfile && version >= 320) || 3036 extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) 3037 return; 3038 break; 3039 case EShLangTessEvaluation: 3040 if ((qualifier.storage == EvqVaryingIn && ! qualifier.patch) || 3041 qualifier.storage == EvqVaryingOut) 3042 if ((profile == EEsProfile && version >= 320) || 3043 extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) 3044 return; 3045 break; 3046 default: 3047 break; 3048 } 3049 3050 arraySizeRequiredCheck(loc, *arraySizes); 3051 } 3052 3053 void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc) 3054 { 3055 const char* feature = "arrays of arrays"; 3056 3057 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); 3058 profileRequires(loc, EEsProfile, 310, nullptr, feature); 3059 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); 3060 } 3061 3062 void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TArraySizes* sizes1, const TArraySizes* sizes2) 3063 { 3064 if ((sizes1 && sizes2) || 3065 (sizes1 && sizes1->getNumDims() > 1) || 3066 (sizes2 && sizes2->getNumDims() > 1)) 3067 arrayOfArrayVersionCheck(loc); 3068 } 3069 3070 void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TType* type, const TArraySizes* sizes2) 3071 { 3072 // skip checking for multiple dimensions on the type; it was caught earlier 3073 if ((type && type->isArray() && sizes2) || 3074 (sizes2 && sizes2->getNumDims() > 1)) 3075 arrayOfArrayVersionCheck(loc); 3076 } 3077 3078 // Merge array dimensions listed in 'sizes' onto the type's array dimensions. 3079 // 3080 // From the spec: "vec4[2] a[3]; // size-3 array of size-2 array of vec4" 3081 // 3082 // That means, the 'sizes' go in front of the 'type' as outermost sizes. 3083 // 'type' is the type part of the declaration (to the left) 3084 // 'sizes' is the arrayness tagged on the identifier (to the right) 3085 // 3086 void TParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes) 3087 { 3088 if (sizes) 3089 type.addArrayOuterSizes(*sizes); 3090 } 3091 3092 // 3093 // Do all the semantic checking for declaring or redeclaring an array, with and 3094 // without a size, and make the right changes to the symbol table. 3095 // 3096 void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol) 3097 { 3098 if (symbol == nullptr) { 3099 bool currentScope; 3100 symbol = symbolTable.find(identifier, nullptr, ¤tScope); 3101 3102 if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) { 3103 // bad shader (errors already reported) trying to redeclare a built-in name as an array 3104 symbol = nullptr; 3105 return; 3106 } 3107 if (symbol == nullptr || ! currentScope) { 3108 // 3109 // Successfully process a new definition. 3110 // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations) 3111 // 3112 symbol = new TVariable(&identifier, type); 3113 symbolTable.insert(*symbol); 3114 if (symbolTable.atGlobalLevel()) 3115 trackLinkage(*symbol); 3116 3117 if (! symbolTable.atBuiltInLevel()) { 3118 if (isIoResizeArray(type)) { 3119 ioArraySymbolResizeList.push_back(symbol); 3120 checkIoArraysConsistency(loc, true); 3121 } else 3122 fixIoArraySize(loc, symbol->getWritableType()); 3123 } 3124 3125 return; 3126 } 3127 if (symbol->getAsAnonMember()) { 3128 error(loc, "cannot redeclare a user-block member array", identifier.c_str(), ""); 3129 symbol = nullptr; 3130 return; 3131 } 3132 } 3133 3134 // 3135 // Process a redeclaration. 3136 // 3137 3138 if (symbol == nullptr) { 3139 error(loc, "array variable name expected", identifier.c_str(), ""); 3140 return; 3141 } 3142 3143 // redeclareBuiltinVariable() should have already done the copyUp() 3144 TType& existingType = symbol->getWritableType(); 3145 3146 if (! existingType.isArray()) { 3147 error(loc, "redeclaring non-array as array", identifier.c_str(), ""); 3148 return; 3149 } 3150 3151 if (! existingType.sameElementType(type)) { 3152 error(loc, "redeclaration of array with a different element type", identifier.c_str(), ""); 3153 return; 3154 } 3155 3156 if (! existingType.sameInnerArrayness(type)) { 3157 error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), ""); 3158 return; 3159 } 3160 3161 if (existingType.isExplicitlySizedArray()) { 3162 // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size 3163 if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize())) 3164 error(loc, "redeclaration of array with size", identifier.c_str(), ""); 3165 return; 3166 } 3167 3168 arrayLimitCheck(loc, identifier, type.getOuterArraySize()); 3169 3170 existingType.updateArraySizes(type); 3171 3172 if (isIoResizeArray(type)) 3173 checkIoArraysConsistency(loc); 3174 } 3175 3176 void TParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode *node, int index) 3177 { 3178 // maybe there is nothing to do... 3179 TIntermTyped* typedNode = node->getAsTyped(); 3180 if (typedNode->getType().getImplicitArraySize() > index) 3181 return; 3182 3183 // something to do... 3184 3185 // Figure out what symbol to lookup, as we will use its type to edit for the size change, 3186 // as that type will be shared through shallow copies for future references. 3187 TSymbol* symbol = nullptr; 3188 int blockIndex = -1; 3189 const TString* lookupName = nullptr; 3190 if (node->getAsSymbolNode()) 3191 lookupName = &node->getAsSymbolNode()->getName(); 3192 else if (node->getAsBinaryNode()) { 3193 const TIntermBinary* deref = node->getAsBinaryNode(); 3194 // This has to be the result of a block dereference, unless it's bad shader code 3195 // If it's a uniform block, then an error will be issued elsewhere, but 3196 // return early now to avoid crashing later in this function. 3197 if (deref->getLeft()->getBasicType() != EbtBlock || 3198 deref->getLeft()->getType().getQualifier().storage == EvqUniform || 3199 deref->getRight()->getAsConstantUnion() == nullptr) 3200 return; 3201 3202 const TIntermTyped* left = deref->getLeft(); 3203 const TIntermTyped* right = deref->getRight(); 3204 3205 if (left->getAsBinaryNode()) { 3206 left = left->getAsBinaryNode()->getLeft(); // Block array access 3207 assert(left->isArray()); 3208 } 3209 3210 if (! left->getAsSymbolNode()) 3211 return; 3212 3213 blockIndex = right->getAsConstantUnion()->getConstArray()[0].getIConst(); 3214 3215 lookupName = &left->getAsSymbolNode()->getName(); 3216 if (IsAnonymous(*lookupName)) 3217 lookupName = &(*left->getType().getStruct())[blockIndex].type->getFieldName(); 3218 } 3219 3220 // Lookup the symbol, should only fail if shader code is incorrect 3221 symbol = symbolTable.find(*lookupName); 3222 if (symbol == nullptr) 3223 return; 3224 3225 if (symbol->getAsFunction()) { 3226 error(loc, "array variable name expected", symbol->getName().c_str(), ""); 3227 return; 3228 } 3229 3230 if (symbol->getType().isStruct() && blockIndex != -1) 3231 (*symbol->getWritableType().getStruct())[blockIndex].type->setImplicitArraySize(index + 1); 3232 else 3233 symbol->getWritableType().setImplicitArraySize(index + 1); 3234 } 3235 3236 // Returns true if the first argument to the #line directive is the line number for the next line. 3237 // 3238 // Desktop, pre-version 3.30: "After processing this directive 3239 // (including its new-line), the implementation will behave as if it is compiling at line number line+1 and 3240 // source string number source-string-number." 3241 // 3242 // Desktop, version 3.30 and later, and ES: "After processing this directive 3243 // (including its new-line), the implementation will behave as if it is compiling at line number line and 3244 // source string number source-string-number. 3245 bool TParseContext::lineDirectiveShouldSetNextLine() const 3246 { 3247 return profile == EEsProfile || version >= 330; 3248 } 3249 3250 // 3251 // Enforce non-initializer type/qualifier rules. 3252 // 3253 void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier, TType& type) 3254 { 3255 // 3256 // Make the qualifier make sense, given that there is not an initializer. 3257 // 3258 if (type.getQualifier().storage == EvqConst || 3259 type.getQualifier().storage == EvqConstReadOnly) { 3260 type.getQualifier().makeTemporary(); 3261 error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); 3262 } 3263 } 3264 3265 // 3266 // See if the identifier is a built-in symbol that can be redeclared, and if so, 3267 // copy the symbol table's read-only built-in variable to the current 3268 // global level, where it can be modified based on the passed in type. 3269 // 3270 // Returns nullptr if no redeclaration took place; meaning a normal declaration still 3271 // needs to occur for it, not necessarily an error. 3272 // 3273 // Returns a redeclared and type-modified variable if a redeclarated occurred. 3274 // 3275 TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier, 3276 const TQualifier& qualifier, const TShaderQualifiers& publicType) 3277 { 3278 if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel()) 3279 return nullptr; 3280 3281 bool nonEsRedecls = (profile != EEsProfile && (version >= 130 || identifier == "gl_TexCoord")); 3282 bool esRedecls = (profile == EEsProfile && 3283 (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks))); 3284 if (! esRedecls && ! nonEsRedecls) 3285 return nullptr; 3286 3287 // Special case when using GL_ARB_separate_shader_objects 3288 bool ssoPre150 = false; // means the only reason this variable is redeclared is due to this combination 3289 if (profile != EEsProfile && version <= 140 && extensionTurnedOn(E_GL_ARB_separate_shader_objects)) { 3290 if (identifier == "gl_Position" || 3291 identifier == "gl_PointSize" || 3292 identifier == "gl_ClipVertex" || 3293 identifier == "gl_FogFragCoord") 3294 ssoPre150 = true; 3295 } 3296 3297 // Potentially redeclaring a built-in variable... 3298 3299 if (ssoPre150 || 3300 (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) || 3301 (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) || 3302 identifier == "gl_ClipDistance" || 3303 identifier == "gl_CullDistance" || 3304 identifier == "gl_FrontColor" || 3305 identifier == "gl_BackColor" || 3306 identifier == "gl_FrontSecondaryColor" || 3307 identifier == "gl_BackSecondaryColor" || 3308 identifier == "gl_SecondaryColor" || 3309 (identifier == "gl_Color" && language == EShLangFragment) || 3310 #ifdef NV_EXTENSIONS 3311 identifier == "gl_SampleMask" || 3312 identifier == "gl_Layer" || 3313 #endif 3314 identifier == "gl_TexCoord") { 3315 3316 // Find the existing symbol, if any. 3317 bool builtIn; 3318 TSymbol* symbol = symbolTable.find(identifier, &builtIn); 3319 3320 // If the symbol was not found, this must be a version/profile/stage 3321 // that doesn't have it. 3322 if (! symbol) 3323 return nullptr; 3324 3325 // If it wasn't at a built-in level, then it's already been redeclared; 3326 // that is, this is a redeclaration of a redeclaration; reuse that initial 3327 // redeclaration. Otherwise, make the new one. 3328 if (builtIn) 3329 makeEditable(symbol); 3330 3331 // Now, modify the type of the copy, as per the type of the current redeclaration. 3332 3333 TQualifier& symbolQualifier = symbol->getWritableType().getQualifier(); 3334 if (ssoPre150) { 3335 if (intermediate.inIoAccessed(identifier)) 3336 error(loc, "cannot redeclare after use", identifier.c_str(), ""); 3337 if (qualifier.hasLayout()) 3338 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); 3339 if (qualifier.isMemory() || qualifier.isAuxiliary() || (language == EShLangVertex && qualifier.storage != EvqVaryingOut) || 3340 (language == EShLangFragment && qualifier.storage != EvqVaryingIn)) 3341 error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); 3342 if (! qualifier.smooth) 3343 error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str()); 3344 } else if (identifier == "gl_FrontColor" || 3345 identifier == "gl_BackColor" || 3346 identifier == "gl_FrontSecondaryColor" || 3347 identifier == "gl_BackSecondaryColor" || 3348 identifier == "gl_SecondaryColor" || 3349 identifier == "gl_Color") { 3350 symbolQualifier.flat = qualifier.flat; 3351 symbolQualifier.smooth = qualifier.smooth; 3352 symbolQualifier.nopersp = qualifier.nopersp; 3353 if (qualifier.hasLayout()) 3354 error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); 3355 if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage) 3356 error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); 3357 } else if (identifier == "gl_TexCoord" || 3358 identifier == "gl_ClipDistance" || 3359 identifier == "gl_CullDistance") { 3360 if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() || 3361 qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || 3362 symbolQualifier.storage != qualifier.storage) 3363 error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str()); 3364 } else if (identifier == "gl_FragCoord") { 3365 if (intermediate.inIoAccessed("gl_FragCoord")) 3366 error(loc, "cannot redeclare after use", "gl_FragCoord", ""); 3367 if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || 3368 qualifier.isMemory() || qualifier.isAuxiliary()) 3369 error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); 3370 if (qualifier.storage != EvqVaryingIn) 3371 error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str()); 3372 if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() || 3373 publicType.originUpperLeft != intermediate.getOriginUpperLeft())) 3374 error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str()); 3375 if (publicType.pixelCenterInteger) 3376 intermediate.setPixelCenterInteger(); 3377 if (publicType.originUpperLeft) 3378 intermediate.setOriginUpperLeft(); 3379 } else if (identifier == "gl_FragDepth") { 3380 if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || 3381 qualifier.isMemory() || qualifier.isAuxiliary()) 3382 error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); 3383 if (qualifier.storage != EvqVaryingOut) 3384 error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); 3385 if (publicType.layoutDepth != EldNone) { 3386 if (intermediate.inIoAccessed("gl_FragDepth")) 3387 error(loc, "cannot redeclare after use", "gl_FragDepth", ""); 3388 if (! intermediate.setDepth(publicType.layoutDepth)) 3389 error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str()); 3390 } 3391 } 3392 #ifdef NV_EXTENSIONS 3393 else if (identifier == "gl_SampleMask") { 3394 if (!publicType.layoutOverrideCoverage) { 3395 error(loc, "redeclaration only allowed for override_coverage layout", "redeclaration", symbol->getName().c_str()); 3396 } 3397 intermediate.setLayoutOverrideCoverage(); 3398 } 3399 else if (identifier == "gl_Layer") { 3400 if (!qualifier.layoutViewportRelative && qualifier.layoutSecondaryViewportRelativeOffset == -2048) 3401 error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", symbol->getName().c_str()); 3402 symbolQualifier.layoutViewportRelative = qualifier.layoutViewportRelative; 3403 symbolQualifier.layoutSecondaryViewportRelativeOffset = qualifier.layoutSecondaryViewportRelativeOffset; 3404 } 3405 #endif 3406 3407 // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above 3408 3409 return symbol; 3410 } 3411 3412 return nullptr; 3413 } 3414 3415 // 3416 // Either redeclare the requested block, or give an error message why it can't be done. 3417 // 3418 // TODO: functionality: explicitly sizing members of redeclared blocks is not giving them an explicit size 3419 void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes) 3420 { 3421 const char* feature = "built-in block redeclaration"; 3422 profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); 3423 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); 3424 3425 if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment") { 3426 error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str()); 3427 return; 3428 } 3429 3430 // Redeclaring a built-in block... 3431 3432 if (instanceName && ! builtInName(*instanceName)) { 3433 error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), ""); 3434 return; 3435 } 3436 3437 // Blocks with instance names are easy to find, lookup the instance name, 3438 // Anonymous blocks need to be found via a member. 3439 bool builtIn; 3440 TSymbol* block; 3441 if (instanceName) 3442 block = symbolTable.find(*instanceName, &builtIn); 3443 else 3444 block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn); 3445 3446 // If the block was not found, this must be a version/profile/stage 3447 // that doesn't have it, or the instance name is wrong. 3448 const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str(); 3449 if (! block) { 3450 error(loc, "no declaration found for redeclaration", errorName, ""); 3451 return; 3452 } 3453 // Built-in blocks cannot be redeclared more than once, which if happened, 3454 // we'd be finding the already redeclared one here, rather than the built in. 3455 if (! builtIn) { 3456 error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), ""); 3457 return; 3458 } 3459 3460 // Copy the block to make a writable version, to insert into the block table after editing. 3461 block = symbolTable.copyUpDeferredInsert(block); 3462 3463 if (block->getType().getBasicType() != EbtBlock) { 3464 error(loc, "cannot redeclare a non block as a block", errorName, ""); 3465 return; 3466 } 3467 3468 // Edit and error check the container against the redeclaration 3469 // - remove unused members 3470 // - ensure remaining qualifiers/types match 3471 TType& type = block->getWritableType(); 3472 3473 #ifdef NV_EXTENSIONS 3474 // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position" 3475 // for passthrough purpose, the redclared block should have the same qualifers as 3476 // the current one 3477 if (currentBlockQualifier.layoutPassthrough) 3478 { 3479 type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough; 3480 type.getQualifier().storage = currentBlockQualifier.storage; 3481 type.getQualifier().layoutStream = currentBlockQualifier.layoutStream; 3482 type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; 3483 } 3484 #endif 3485 3486 TTypeList::iterator member = type.getWritableStruct()->begin(); 3487 size_t numOriginalMembersFound = 0; 3488 while (member != type.getStruct()->end()) { 3489 // look for match 3490 bool found = false; 3491 TTypeList::const_iterator newMember; 3492 TSourceLoc memberLoc; 3493 memberLoc.init(); 3494 for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) { 3495 if (member->type->getFieldName() == newMember->type->getFieldName()) { 3496 found = true; 3497 memberLoc = newMember->loc; 3498 break; 3499 } 3500 } 3501 3502 if (found) { 3503 ++numOriginalMembersFound; 3504 // - ensure match between redeclared members' types 3505 // - check for things that can't be changed 3506 // - update things that can be changed 3507 TType& oldType = *member->type; 3508 const TType& newType = *newMember->type; 3509 if (! newType.sameElementType(oldType)) 3510 error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), ""); 3511 if (oldType.isArray() != newType.isArray()) 3512 error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), ""); 3513 else if (! oldType.sameArrayness(newType) && oldType.isExplicitlySizedArray()) 3514 error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), ""); 3515 else if (newType.isArray()) 3516 arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize()); 3517 if (newType.getQualifier().isMemory()) 3518 error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); 3519 if (newType.getQualifier().hasLayout()) 3520 error(memberLoc, "cannot add layout to redeclared block member", member->type->getFieldName().c_str(), ""); 3521 if (newType.getQualifier().patch) 3522 error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), ""); 3523 oldType.getQualifier().centroid = newType.getQualifier().centroid; 3524 oldType.getQualifier().sample = newType.getQualifier().sample; 3525 oldType.getQualifier().invariant = newType.getQualifier().invariant; 3526 oldType.getQualifier().noContraction = newType.getQualifier().noContraction; 3527 oldType.getQualifier().smooth = newType.getQualifier().smooth; 3528 oldType.getQualifier().flat = newType.getQualifier().flat; 3529 oldType.getQualifier().nopersp = newType.getQualifier().nopersp; 3530 3531 #ifdef NV_EXTENSIONS 3532 if (member->type->getFieldName() == "gl_Layer") { 3533 if (!newType.getQualifier().layoutViewportRelative && newType.getQualifier().layoutSecondaryViewportRelativeOffset == -2048) 3534 error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", member->type->getFieldName().c_str()); 3535 oldType.getQualifier().layoutViewportRelative = newType.getQualifier().layoutViewportRelative; 3536 oldType.getQualifier().layoutSecondaryViewportRelativeOffset = newType.getQualifier().layoutSecondaryViewportRelativeOffset; 3537 } 3538 #endif 3539 if (oldType.isImplicitlySizedArray() && newType.isExplicitlySizedArray()) 3540 oldType.changeOuterArraySize(newType.getOuterArraySize()); 3541 3542 // go to next member 3543 ++member; 3544 } else { 3545 // For missing members of anonymous blocks that have been redeclared, 3546 // hide the original (shared) declaration. 3547 // Instance-named blocks can just have the member removed. 3548 if (instanceName) 3549 member = type.getWritableStruct()->erase(member); 3550 else { 3551 member->type->hideMember(); 3552 ++member; 3553 } 3554 } 3555 } 3556 3557 if (numOriginalMembersFound < newTypeList.size()) 3558 error(loc, "block redeclaration has extra members", blockName.c_str(), ""); 3559 if (type.isArray() != (arraySizes != nullptr)) 3560 error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), ""); 3561 else if (type.isArray()) { 3562 if (type.isExplicitlySizedArray() && arraySizes->getOuterSize() == UnsizedArraySize) 3563 error(loc, "block already declared with size, can't redeclare as implicitly-sized", blockName.c_str(), ""); 3564 else if (type.isExplicitlySizedArray() && type.getArraySizes() != *arraySizes) 3565 error(loc, "cannot change array size of redeclared block", blockName.c_str(), ""); 3566 else if (type.isImplicitlySizedArray() && arraySizes->getOuterSize() != UnsizedArraySize) 3567 type.changeOuterArraySize(arraySizes->getOuterSize()); 3568 } 3569 3570 symbolTable.insert(*block); 3571 3572 // Check for general layout qualifier errors 3573 layoutObjectCheck(loc, *block); 3574 3575 // Tracking for implicit sizing of array 3576 if (isIoResizeArray(block->getType())) { 3577 ioArraySymbolResizeList.push_back(block); 3578 checkIoArraysConsistency(loc, true); 3579 } else if (block->getType().isArray()) 3580 fixIoArraySize(loc, block->getWritableType()); 3581 3582 // Save it in the AST for linker use. 3583 trackLinkage(*block); 3584 } 3585 3586 void TParseContext::paramCheckFix(const TSourceLoc& loc, const TStorageQualifier& qualifier, TType& type) 3587 { 3588 switch (qualifier) { 3589 case EvqConst: 3590 case EvqConstReadOnly: 3591 type.getQualifier().storage = EvqConstReadOnly; 3592 break; 3593 case EvqIn: 3594 case EvqOut: 3595 case EvqInOut: 3596 type.getQualifier().storage = qualifier; 3597 break; 3598 case EvqGlobal: 3599 case EvqTemporary: 3600 type.getQualifier().storage = EvqIn; 3601 break; 3602 default: 3603 type.getQualifier().storage = EvqIn; 3604 error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), ""); 3605 break; 3606 } 3607 } 3608 3609 void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& qualifier, TType& type) 3610 { 3611 if (qualifier.isMemory()) { 3612 type.getQualifier().volatil = qualifier.volatil; 3613 type.getQualifier().coherent = qualifier.coherent; 3614 type.getQualifier().readonly = qualifier.readonly; 3615 type.getQualifier().writeonly = qualifier.writeonly; 3616 type.getQualifier().restrict = qualifier.restrict; 3617 } 3618 3619 if (qualifier.isAuxiliary() || 3620 qualifier.isInterpolation()) 3621 error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", ""); 3622 if (qualifier.hasLayout()) 3623 error(loc, "cannot use layout qualifiers on a function parameter", "", ""); 3624 if (qualifier.invariant) 3625 error(loc, "cannot use invariant qualifier on a function parameter", "", ""); 3626 if (qualifier.noContraction) { 3627 if (qualifier.isParamOutput()) 3628 type.getQualifier().noContraction = true; 3629 else 3630 warn(loc, "qualifier has no effect on non-output parameters", "precise", ""); 3631 } 3632 3633 paramCheckFix(loc, qualifier.storage, type); 3634 } 3635 3636 void TParseContext::nestedBlockCheck(const TSourceLoc& loc) 3637 { 3638 if (structNestingLevel > 0) 3639 error(loc, "cannot nest a block definition inside a structure or block", "", ""); 3640 ++structNestingLevel; 3641 } 3642 3643 void TParseContext::nestedStructCheck(const TSourceLoc& loc) 3644 { 3645 if (structNestingLevel > 0) 3646 error(loc, "cannot nest a structure definition inside a structure or block", "", ""); 3647 ++structNestingLevel; 3648 } 3649 3650 void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, const char* op) 3651 { 3652 // Some versions don't allow comparing arrays or structures containing arrays 3653 if (type.containsArray()) { 3654 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, op); 3655 profileRequires(loc, EEsProfile, 300, nullptr, op); 3656 } 3657 } 3658 3659 void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op) 3660 { 3661 if (containsFieldWithBasicType(type, EbtSampler)) 3662 error(loc, "can't use with samplers or structs containing samplers", op, ""); 3663 } 3664 3665 void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op) 3666 { 3667 if (type.containsSpecializationSize()) 3668 error(loc, "can't use with types containing arrays sized with a specialization constant", op, ""); 3669 } 3670 3671 void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publicType) 3672 { 3673 const TTypeList& typeList = *publicType.userDef->getStruct(); 3674 3675 // fix and check for member storage qualifiers and types that don't belong within a structure 3676 for (unsigned int member = 0; member < typeList.size(); ++member) { 3677 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 3678 const TSourceLoc& memberLoc = typeList[member].loc; 3679 if (memberQualifier.isAuxiliary() || 3680 memberQualifier.isInterpolation() || 3681 (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal)) 3682 error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); 3683 if (memberQualifier.isMemory()) 3684 error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); 3685 if (memberQualifier.hasLayout()) { 3686 error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); 3687 memberQualifier.clearLayout(); 3688 } 3689 if (memberQualifier.invariant) 3690 error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), ""); 3691 } 3692 } 3693 3694 // 3695 // See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A: 3696 // 3697 // "The loop index has type int or float. 3698 // 3699 // "The for statement has the form: 3700 // for ( init-declaration ; condition ; expression ) 3701 // init-declaration has the form: type-specifier identifier = constant-expression 3702 // condition has the form: loop-index relational_operator constant-expression 3703 // where relational_operator is one of: > >= < <= == or != 3704 // expression [sic] has one of the following forms: 3705 // loop-index++ 3706 // loop-index-- 3707 // loop-index += constant-expression 3708 // loop-index -= constant-expression 3709 // 3710 // The body is handled in an AST traversal. 3711 // 3712 void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop) 3713 { 3714 // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration 3715 bool badInit = false; 3716 if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1) 3717 badInit = true; 3718 TIntermBinary* binaryInit = 0; 3719 if (! badInit) { 3720 // get the declaration assignment 3721 binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode(); 3722 if (! binaryInit) 3723 badInit = true; 3724 } 3725 if (badInit) { 3726 error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); 3727 return; 3728 } 3729 3730 // loop index must be type int or float 3731 if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) { 3732 error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", ""); 3733 return; 3734 } 3735 3736 // init is the form "loop-index = constant" 3737 if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) { 3738 error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); 3739 return; 3740 } 3741 3742 // get the unique id of the loop index 3743 int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); 3744 inductiveLoopIds.insert(loopIndex); 3745 3746 // condition's form must be "loop-index relational-operator constant-expression" 3747 bool badCond = ! loop->getTest(); 3748 if (! badCond) { 3749 TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode(); 3750 badCond = ! binaryCond; 3751 if (! badCond) { 3752 switch (binaryCond->getOp()) { 3753 case EOpGreaterThan: 3754 case EOpGreaterThanEqual: 3755 case EOpLessThan: 3756 case EOpLessThanEqual: 3757 case EOpEqual: 3758 case EOpNotEqual: 3759 break; 3760 default: 3761 badCond = true; 3762 } 3763 } 3764 if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() || 3765 binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex || 3766 ! binaryCond->getRight()->getAsConstantUnion())) 3767 badCond = true; 3768 } 3769 if (badCond) { 3770 error(loc, "inductive-loop condition requires the form \"loop-index <comparison-op> constant-expression\"", "limitations", ""); 3771 return; 3772 } 3773 3774 // loop-index++ 3775 // loop-index-- 3776 // loop-index += constant-expression 3777 // loop-index -= constant-expression 3778 bool badTerminal = ! loop->getTerminal(); 3779 if (! badTerminal) { 3780 TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode(); 3781 TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode(); 3782 if (unaryTerminal || binaryTerminal) { 3783 switch(loop->getTerminal()->getAsOperator()->getOp()) { 3784 case EOpPostDecrement: 3785 case EOpPostIncrement: 3786 case EOpAddAssign: 3787 case EOpSubAssign: 3788 break; 3789 default: 3790 badTerminal = true; 3791 } 3792 } else 3793 badTerminal = true; 3794 if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() || 3795 binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex || 3796 ! binaryTerminal->getRight()->getAsConstantUnion())) 3797 badTerminal = true; 3798 if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() || 3799 unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex)) 3800 badTerminal = true; 3801 } 3802 if (badTerminal) { 3803 error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", ""); 3804 return; 3805 } 3806 3807 // the body 3808 inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable); 3809 } 3810 3811 // Do limit checks for built-in arrays. 3812 void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size) 3813 { 3814 if (identifier.compare("gl_TexCoord") == 0) 3815 limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size"); 3816 else if (identifier.compare("gl_ClipDistance") == 0) 3817 limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size"); 3818 else if (identifier.compare("gl_CullDistance") == 0) 3819 limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistance array size"); 3820 } 3821 3822 // See if the provided value is less than or equal to the symbol indicated by limit, 3823 // which should be a constant in the symbol table. 3824 void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature) 3825 { 3826 TSymbol* symbol = symbolTable.find(limit); 3827 assert(symbol->getAsVariable()); 3828 const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray(); 3829 assert(! constArray.empty()); 3830 if (value > constArray[0].getIConst()) 3831 error(loc, "must be less than or equal to", feature, "%s (%d)", limit, constArray[0].getIConst()); 3832 } 3833 3834 // 3835 // Do any additional error checking, etc., once we know the parsing is done. 3836 // 3837 void TParseContext::finish() 3838 { 3839 TParseContextBase::finish(); 3840 3841 if (parsingBuiltins) 3842 return; 3843 3844 // Check on array indexes for ES 2.0 (version 100) limitations. 3845 for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i) 3846 constantIndexExpressionCheck(needsIndexLimitationChecking[i]); 3847 3848 // Check for stages that are enabled by extension. 3849 // Can't do this at the beginning, it is chicken and egg to add a stage by 3850 // extension. 3851 // Stage-specific features were correctly tested for already, this is just 3852 // about the stage itself. 3853 switch (language) { 3854 case EShLangGeometry: 3855 if (profile == EEsProfile && version == 310) 3856 requireExtensions(getCurrentLoc(), Num_AEP_geometry_shader, AEP_geometry_shader, "geometry shaders"); 3857 break; 3858 case EShLangTessControl: 3859 case EShLangTessEvaluation: 3860 if (profile == EEsProfile && version == 310) 3861 requireExtensions(getCurrentLoc(), Num_AEP_tessellation_shader, AEP_tessellation_shader, "tessellation shaders"); 3862 else if (profile != EEsProfile && version < 400) 3863 requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_tessellation_shader, "tessellation shaders"); 3864 break; 3865 case EShLangCompute: 3866 if (profile != EEsProfile && version < 430) 3867 requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_compute_shader, "compute shaders"); 3868 break; 3869 default: 3870 break; 3871 } 3872 } 3873 3874 // 3875 // Layout qualifier stuff. 3876 // 3877 3878 // Put the id's layout qualification into the public type, for qualifiers not having a number set. 3879 // This is before we know any type information for error checking. 3880 void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id) 3881 { 3882 std::transform(id.begin(), id.end(), id.begin(), ::tolower); 3883 3884 if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) { 3885 publicType.qualifier.layoutMatrix = ElmColumnMajor; 3886 return; 3887 } 3888 if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) { 3889 publicType.qualifier.layoutMatrix = ElmRowMajor; 3890 return; 3891 } 3892 if (id == TQualifier::getLayoutPackingString(ElpPacked)) { 3893 if (spvVersion.spv != 0) 3894 spvRemoved(loc, "packed"); 3895 publicType.qualifier.layoutPacking = ElpPacked; 3896 return; 3897 } 3898 if (id == TQualifier::getLayoutPackingString(ElpShared)) { 3899 if (spvVersion.spv != 0) 3900 spvRemoved(loc, "shared"); 3901 publicType.qualifier.layoutPacking = ElpShared; 3902 return; 3903 } 3904 if (id == TQualifier::getLayoutPackingString(ElpStd140)) { 3905 publicType.qualifier.layoutPacking = ElpStd140; 3906 return; 3907 } 3908 if (id == TQualifier::getLayoutPackingString(ElpStd430)) { 3909 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430"); 3910 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430"); 3911 profileRequires(loc, EEsProfile, 310, nullptr, "std430"); 3912 publicType.qualifier.layoutPacking = ElpStd430; 3913 return; 3914 } 3915 // TODO: compile-time performance: may need to stop doing linear searches 3916 for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) { 3917 if (id == TQualifier::getLayoutFormatString(format)) { 3918 if ((format > ElfEsFloatGuard && format < ElfFloatGuard) || 3919 (format > ElfEsIntGuard && format < ElfIntGuard) || 3920 (format > ElfEsUintGuard && format < ElfCount)) 3921 requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format"); 3922 profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "image load store"); 3923 profileRequires(loc, EEsProfile, 310, E_GL_ARB_shader_image_load_store, "image load store"); 3924 publicType.qualifier.layoutFormat = format; 3925 return; 3926 } 3927 } 3928 if (id == "push_constant") { 3929 requireVulkan(loc, "push_constant"); 3930 publicType.qualifier.layoutPushConstant = true; 3931 return; 3932 } 3933 if (language == EShLangGeometry || language == EShLangTessEvaluation) { 3934 if (id == TQualifier::getGeometryString(ElgTriangles)) { 3935 publicType.shaderQualifiers.geometry = ElgTriangles; 3936 return; 3937 } 3938 if (language == EShLangGeometry) { 3939 if (id == TQualifier::getGeometryString(ElgPoints)) { 3940 publicType.shaderQualifiers.geometry = ElgPoints; 3941 return; 3942 } 3943 if (id == TQualifier::getGeometryString(ElgLineStrip)) { 3944 publicType.shaderQualifiers.geometry = ElgLineStrip; 3945 return; 3946 } 3947 if (id == TQualifier::getGeometryString(ElgLines)) { 3948 publicType.shaderQualifiers.geometry = ElgLines; 3949 return; 3950 } 3951 if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { 3952 publicType.shaderQualifiers.geometry = ElgLinesAdjacency; 3953 return; 3954 } 3955 if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { 3956 publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency; 3957 return; 3958 } 3959 if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { 3960 publicType.shaderQualifiers.geometry = ElgTriangleStrip; 3961 return; 3962 } 3963 #ifdef NV_EXTENSIONS 3964 if (id == "passthrough") { 3965 requireExtensions(loc, 1, &E_SPV_NV_geometry_shader_passthrough, "geometry shader passthrough"); 3966 publicType.qualifier.layoutPassthrough = true; 3967 intermediate.setGeoPassthroughEXT(); 3968 return; 3969 } 3970 #endif 3971 } else { 3972 assert(language == EShLangTessEvaluation); 3973 3974 // input primitive 3975 if (id == TQualifier::getGeometryString(ElgTriangles)) { 3976 publicType.shaderQualifiers.geometry = ElgTriangles; 3977 return; 3978 } 3979 if (id == TQualifier::getGeometryString(ElgQuads)) { 3980 publicType.shaderQualifiers.geometry = ElgQuads; 3981 return; 3982 } 3983 if (id == TQualifier::getGeometryString(ElgIsolines)) { 3984 publicType.shaderQualifiers.geometry = ElgIsolines; 3985 return; 3986 } 3987 3988 // vertex spacing 3989 if (id == TQualifier::getVertexSpacingString(EvsEqual)) { 3990 publicType.shaderQualifiers.spacing = EvsEqual; 3991 return; 3992 } 3993 if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) { 3994 publicType.shaderQualifiers.spacing = EvsFractionalEven; 3995 return; 3996 } 3997 if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) { 3998 publicType.shaderQualifiers.spacing = EvsFractionalOdd; 3999 return; 4000 } 4001 4002 // triangle order 4003 if (id == TQualifier::getVertexOrderString(EvoCw)) { 4004 publicType.shaderQualifiers.order = EvoCw; 4005 return; 4006 } 4007 if (id == TQualifier::getVertexOrderString(EvoCcw)) { 4008 publicType.shaderQualifiers.order = EvoCcw; 4009 return; 4010 } 4011 4012 // point mode 4013 if (id == "point_mode") { 4014 publicType.shaderQualifiers.pointMode = true; 4015 return; 4016 } 4017 } 4018 } 4019 if (language == EShLangFragment) { 4020 if (id == "origin_upper_left") { 4021 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left"); 4022 publicType.shaderQualifiers.originUpperLeft = true; 4023 return; 4024 } 4025 if (id == "pixel_center_integer") { 4026 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer"); 4027 publicType.shaderQualifiers.pixelCenterInteger = true; 4028 return; 4029 } 4030 if (id == "early_fragment_tests") { 4031 profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "early_fragment_tests"); 4032 profileRequires(loc, EEsProfile, 310, nullptr, "early_fragment_tests"); 4033 publicType.shaderQualifiers.earlyFragmentTests = true; 4034 return; 4035 } 4036 if (id == "post_depth_coverage") { 4037 requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage"); 4038 if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) { 4039 publicType.shaderQualifiers.earlyFragmentTests = true; 4040 } 4041 publicType.shaderQualifiers.postDepthCoverage = true; 4042 return; 4043 } 4044 for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) { 4045 if (id == TQualifier::getLayoutDepthString(depth)) { 4046 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier"); 4047 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "depth layout qualifier"); 4048 publicType.shaderQualifiers.layoutDepth = depth; 4049 return; 4050 } 4051 } 4052 if (id.compare(0, 13, "blend_support") == 0) { 4053 bool found = false; 4054 for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { 4055 if (id == TQualifier::getBlendEquationString(be)) { 4056 profileRequires(loc, EEsProfile, 320, E_GL_KHR_blend_equation_advanced, "blend equation"); 4057 profileRequires(loc, ~EEsProfile, 0, E_GL_KHR_blend_equation_advanced, "blend equation"); 4058 intermediate.addBlendEquation(be); 4059 publicType.shaderQualifiers.blendEquation = true; 4060 found = true; 4061 break; 4062 } 4063 } 4064 if (! found) 4065 error(loc, "unknown blend equation", "blend_support", ""); 4066 return; 4067 } 4068 #ifdef NV_EXTENSIONS 4069 if (id == "override_coverage") { 4070 requireExtensions(loc, 1, &E_GL_NV_sample_mask_override_coverage, "sample mask override coverage"); 4071 publicType.shaderQualifiers.layoutOverrideCoverage = true; 4072 return; 4073 } 4074 } 4075 if (language == EShLangVertex || 4076 language == EShLangTessControl || 4077 language == EShLangTessEvaluation || 4078 language == EShLangGeometry ) { 4079 if (id == "viewport_relative") { 4080 requireExtensions(loc, 1, &E_GL_NV_viewport_array2, "view port array2"); 4081 publicType.qualifier.layoutViewportRelative = true; 4082 return; 4083 } 4084 } 4085 #else 4086 } 4087 #endif 4088 error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); 4089 } 4090 4091 // Put the id's layout qualifier value into the public type, for qualifiers having a number set. 4092 // This is before we know any type information for error checking. 4093 void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id, const TIntermTyped* node) 4094 { 4095 const char* feature = "layout-id value"; 4096 const char* nonLiteralFeature = "non-literal layout-id value"; 4097 4098 integerCheck(node, feature); 4099 const TIntermConstantUnion* constUnion = node->getAsConstantUnion(); 4100 int value; 4101 if (constUnion) { 4102 value = constUnion->getConstArray()[0].getIConst(); 4103 if (! constUnion->isLiteral()) { 4104 requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature); 4105 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, nonLiteralFeature); 4106 } 4107 } else { 4108 // grammar should have give out the error message 4109 value = 0; 4110 } 4111 4112 if (value < 0) { 4113 error(loc, "cannot be negative", feature, ""); 4114 return; 4115 } 4116 4117 std::transform(id.begin(), id.end(), id.begin(), ::tolower); 4118 4119 if (id == "offset") { 4120 // "offset" can be for either 4121 // - uniform offsets 4122 // - atomic_uint offsets 4123 const char* feature = "offset"; 4124 if (spvVersion.spv == 0) { 4125 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); 4126 const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters }; 4127 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature); 4128 profileRequires(loc, EEsProfile, 310, nullptr, feature); 4129 } 4130 publicType.qualifier.layoutOffset = value; 4131 return; 4132 } else if (id == "align") { 4133 const char* feature = "uniform buffer-member align"; 4134 if (spvVersion.spv == 0) { 4135 requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); 4136 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); 4137 } 4138 // "The specified alignment must be a power of 2, or a compile-time error results." 4139 if (! IsPow2(value)) 4140 error(loc, "must be a power of 2", "align", ""); 4141 else 4142 publicType.qualifier.layoutAlign = value; 4143 return; 4144 } else if (id == "location") { 4145 profileRequires(loc, EEsProfile, 300, nullptr, "location"); 4146 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 4147 profileRequires(loc, ~EEsProfile, 330, 2, exts, "location"); 4148 if ((unsigned int)value >= TQualifier::layoutLocationEnd) 4149 error(loc, "location is too large", id.c_str(), ""); 4150 else 4151 publicType.qualifier.layoutLocation = value; 4152 return; 4153 } else if (id == "set") { 4154 if ((unsigned int)value >= TQualifier::layoutSetEnd) 4155 error(loc, "set is too large", id.c_str(), ""); 4156 else 4157 publicType.qualifier.layoutSet = value; 4158 if (value != 0) 4159 requireVulkan(loc, "descriptor set"); 4160 return; 4161 } else if (id == "binding") { 4162 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding"); 4163 profileRequires(loc, EEsProfile, 310, nullptr, "binding"); 4164 if ((unsigned int)value >= TQualifier::layoutBindingEnd) 4165 error(loc, "binding is too large", id.c_str(), ""); 4166 else 4167 publicType.qualifier.layoutBinding = value; 4168 return; 4169 } else if (id == "component") { 4170 requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component"); 4171 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "component"); 4172 if ((unsigned)value >= TQualifier::layoutComponentEnd) 4173 error(loc, "component is too large", id.c_str(), ""); 4174 else 4175 publicType.qualifier.layoutComponent = value; 4176 return; 4177 } else if (id.compare(0, 4, "xfb_") == 0) { 4178 // "Any shader making any static use (after preprocessing) of any of these 4179 // *xfb_* qualifiers will cause the shader to be in a transform feedback 4180 // capturing mode and hence responsible for describing the transform feedback 4181 // setup." 4182 intermediate.setXfbMode(); 4183 const char* feature = "transform feedback qualifier"; 4184 requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature); 4185 requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); 4186 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); 4187 if (id == "xfb_buffer") { 4188 // "It is a compile-time error to specify an *xfb_buffer* that is greater than 4189 // the implementation-dependent constant gl_MaxTransformFeedbackBuffers." 4190 if (value >= resources.maxTransformFeedbackBuffers) 4191 error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", resources.maxTransformFeedbackBuffers); 4192 if (value >= (int)TQualifier::layoutXfbBufferEnd) 4193 error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd-1); 4194 else 4195 publicType.qualifier.layoutXfbBuffer = value; 4196 return; 4197 } else if (id == "xfb_offset") { 4198 if (value >= (int)TQualifier::layoutXfbOffsetEnd) 4199 error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd-1); 4200 else 4201 publicType.qualifier.layoutXfbOffset = value; 4202 return; 4203 } else if (id == "xfb_stride") { 4204 // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the 4205 // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." 4206 if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) 4207 error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d", resources.maxTransformFeedbackInterleavedComponents); 4208 else if (value >= (int)TQualifier::layoutXfbStrideEnd) 4209 error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd-1); 4210 if (value < (int)TQualifier::layoutXfbStrideEnd) 4211 publicType.qualifier.layoutXfbStride = value; 4212 return; 4213 } 4214 } 4215 4216 if (id == "input_attachment_index") { 4217 requireVulkan(loc, "input_attachment_index"); 4218 if (value >= (int)TQualifier::layoutAttachmentEnd) 4219 error(loc, "attachment index is too large", id.c_str(), ""); 4220 else 4221 publicType.qualifier.layoutAttachment = value; 4222 return; 4223 } 4224 if (id == "constant_id") { 4225 requireSpv(loc, "constant_id"); 4226 if (value >= (int)TQualifier::layoutSpecConstantIdEnd) { 4227 error(loc, "specialization-constant id is too large", id.c_str(), ""); 4228 } else { 4229 publicType.qualifier.layoutSpecConstantId = value; 4230 publicType.qualifier.specConstant = true; 4231 if (! intermediate.addUsedConstantId(value)) 4232 error(loc, "specialization-constant id already used", id.c_str(), ""); 4233 } 4234 return; 4235 } 4236 if (id == "num_views") { 4237 requireExtensions(loc, Num_OVR_multiview_EXTs, OVR_multiview_EXTs, "num_views"); 4238 publicType.shaderQualifiers.numViews = value; 4239 return; 4240 } 4241 4242 #if NV_EXTENSIONS 4243 if (language == EShLangVertex || 4244 language == EShLangTessControl || 4245 language == EShLangTessEvaluation || 4246 language == EShLangGeometry) { 4247 if (id == "secondary_view_offset") { 4248 requireExtensions(loc, 1, &E_GL_NV_stereo_view_rendering, "stereo view rendering"); 4249 publicType.qualifier.layoutSecondaryViewportRelativeOffset = value; 4250 return; 4251 } 4252 } 4253 #endif 4254 4255 switch (language) { 4256 case EShLangVertex: 4257 break; 4258 4259 case EShLangTessControl: 4260 if (id == "vertices") { 4261 if (value == 0) 4262 error(loc, "must be greater than 0", "vertices", ""); 4263 else 4264 publicType.shaderQualifiers.vertices = value; 4265 return; 4266 } 4267 break; 4268 4269 case EShLangTessEvaluation: 4270 break; 4271 4272 case EShLangGeometry: 4273 if (id == "invocations") { 4274 profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, nullptr, "invocations"); 4275 if (value == 0) 4276 error(loc, "must be at least 1", "invocations", ""); 4277 else 4278 publicType.shaderQualifiers.invocations = value; 4279 return; 4280 } 4281 if (id == "max_vertices") { 4282 publicType.shaderQualifiers.vertices = value; 4283 if (value > resources.maxGeometryOutputVertices) 4284 error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", ""); 4285 return; 4286 } 4287 if (id == "stream") { 4288 requireProfile(loc, ~EEsProfile, "selecting output stream"); 4289 publicType.qualifier.layoutStream = value; 4290 if (value > 0) 4291 intermediate.setMultiStream(); 4292 return; 4293 } 4294 break; 4295 4296 case EShLangFragment: 4297 if (id == "index") { 4298 requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output"); 4299 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 4300 profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output"); 4301 4302 // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1." 4303 if (value < 0 || value > 1) { 4304 value = 0; 4305 error(loc, "value must be 0 or 1", "index", ""); 4306 } 4307 4308 publicType.qualifier.layoutIndex = value; 4309 return; 4310 } 4311 break; 4312 4313 case EShLangCompute: 4314 if (id.compare(0, 11, "local_size_") == 0) { 4315 profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize"); 4316 profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize"); 4317 if (id.size() == 12 && value == 0) { 4318 error(loc, "must be at least 1", id.c_str(), ""); 4319 return; 4320 } 4321 if (id == "local_size_x") { 4322 publicType.shaderQualifiers.localSize[0] = value; 4323 return; 4324 } 4325 if (id == "local_size_y") { 4326 publicType.shaderQualifiers.localSize[1] = value; 4327 return; 4328 } 4329 if (id == "local_size_z") { 4330 publicType.shaderQualifiers.localSize[2] = value; 4331 return; 4332 } 4333 if (spvVersion.spv != 0) { 4334 if (id == "local_size_x_id") { 4335 publicType.shaderQualifiers.localSizeSpecId[0] = value; 4336 return; 4337 } 4338 if (id == "local_size_y_id") { 4339 publicType.shaderQualifiers.localSizeSpecId[1] = value; 4340 return; 4341 } 4342 if (id == "local_size_z_id") { 4343 publicType.shaderQualifiers.localSizeSpecId[2] = value; 4344 return; 4345 } 4346 } 4347 } 4348 break; 4349 4350 default: 4351 break; 4352 } 4353 4354 error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); 4355 } 4356 4357 // Merge any layout qualifier information from src into dst, leaving everything else in dst alone 4358 // 4359 // "More than one layout qualifier may appear in a single declaration. 4360 // Additionally, the same layout-qualifier-name can occur multiple times 4361 // within a layout qualifier or across multiple layout qualifiers in the 4362 // same declaration. When the same layout-qualifier-name occurs 4363 // multiple times, in a single declaration, the last occurrence overrides 4364 // the former occurrence(s). Further, if such a layout-qualifier-name 4365 // will effect subsequent declarations or other observable behavior, it 4366 // is only the last occurrence that will have any effect, behaving as if 4367 // the earlier occurrence(s) within the declaration are not present. 4368 // This is also true for overriding layout-qualifier-names, where one 4369 // overrides the other (e.g., row_major vs. column_major); only the last 4370 // occurrence has any effect." 4371 void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly) 4372 { 4373 if (src.hasMatrix()) 4374 dst.layoutMatrix = src.layoutMatrix; 4375 if (src.hasPacking()) 4376 dst.layoutPacking = src.layoutPacking; 4377 4378 if (src.hasStream()) 4379 dst.layoutStream = src.layoutStream; 4380 4381 if (src.hasFormat()) 4382 dst.layoutFormat = src.layoutFormat; 4383 4384 if (src.hasXfbBuffer()) 4385 dst.layoutXfbBuffer = src.layoutXfbBuffer; 4386 4387 if (src.hasAlign()) 4388 dst.layoutAlign = src.layoutAlign; 4389 4390 if (! inheritOnly) { 4391 if (src.hasLocation()) 4392 dst.layoutLocation = src.layoutLocation; 4393 if (src.hasComponent()) 4394 dst.layoutComponent = src.layoutComponent; 4395 if (src.hasIndex()) 4396 dst.layoutIndex = src.layoutIndex; 4397 4398 if (src.hasOffset()) 4399 dst.layoutOffset = src.layoutOffset; 4400 4401 if (src.hasSet()) 4402 dst.layoutSet = src.layoutSet; 4403 if (src.layoutBinding != TQualifier::layoutBindingEnd) 4404 dst.layoutBinding = src.layoutBinding; 4405 4406 if (src.hasXfbStride()) 4407 dst.layoutXfbStride = src.layoutXfbStride; 4408 if (src.hasXfbOffset()) 4409 dst.layoutXfbOffset = src.layoutXfbOffset; 4410 if (src.hasAttachment()) 4411 dst.layoutAttachment = src.layoutAttachment; 4412 if (src.hasSpecConstantId()) 4413 dst.layoutSpecConstantId = src.layoutSpecConstantId; 4414 4415 if (src.layoutPushConstant) 4416 dst.layoutPushConstant = true; 4417 4418 #ifdef NV_EXTENSIONS 4419 if (src.layoutPassthrough) 4420 dst.layoutPassthrough = true; 4421 if (src.layoutViewportRelative) 4422 dst.layoutViewportRelative = true; 4423 if (src.layoutSecondaryViewportRelativeOffset != -2048) 4424 dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; 4425 #endif 4426 } 4427 } 4428 4429 // Do error layout error checking given a full variable/block declaration. 4430 void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symbol) 4431 { 4432 const TType& type = symbol.getType(); 4433 const TQualifier& qualifier = type.getQualifier(); 4434 4435 // first, cross check WRT to just the type 4436 layoutTypeCheck(loc, type); 4437 4438 // now, any remaining error checking based on the object itself 4439 4440 if (qualifier.hasAnyLocation()) { 4441 switch (qualifier.storage) { 4442 case EvqUniform: 4443 case EvqBuffer: 4444 if (symbol.getAsVariable() == nullptr) 4445 error(loc, "can only be used on variable declaration", "location", ""); 4446 break; 4447 default: 4448 break; 4449 } 4450 } 4451 4452 // user-variable location check, which are required for SPIR-V in/out: 4453 // - variables have it directly, 4454 // - blocks have it on each member (already enforced), so check first one 4455 if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone && 4456 !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) { 4457 4458 switch (qualifier.storage) { 4459 case EvqVaryingIn: 4460 case EvqVaryingOut: 4461 if (type.getBasicType() != EbtBlock || 4462 (!(*type.getStruct())[0].type->getQualifier().hasLocation() && 4463 (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone)) 4464 error(loc, "SPIR-V requires location for user input/output", "location", ""); 4465 break; 4466 default: 4467 break; 4468 } 4469 } 4470 4471 // Check packing and matrix 4472 if (qualifier.hasUniformLayout()) { 4473 switch (qualifier.storage) { 4474 case EvqUniform: 4475 case EvqBuffer: 4476 if (type.getBasicType() != EbtBlock) { 4477 if (qualifier.hasMatrix()) 4478 error(loc, "cannot specify matrix layout on a variable declaration", "layout", ""); 4479 if (qualifier.hasPacking()) 4480 error(loc, "cannot specify packing on a variable declaration", "layout", ""); 4481 // "The offset qualifier can only be used on block members of blocks..." 4482 if (qualifier.hasOffset() && type.getBasicType() != EbtAtomicUint) 4483 error(loc, "cannot specify on a variable declaration", "offset", ""); 4484 // "The align qualifier can only be used on blocks or block members..." 4485 if (qualifier.hasAlign()) 4486 error(loc, "cannot specify on a variable declaration", "align", ""); 4487 if (qualifier.layoutPushConstant) 4488 error(loc, "can only specify on a uniform block", "push_constant", ""); 4489 } 4490 break; 4491 default: 4492 // these were already filtered by layoutTypeCheck() (or its callees) 4493 break; 4494 } 4495 } 4496 } 4497 4498 // "For some blocks declared as arrays, the location can only be applied at the block level: 4499 // When a block is declared as an array where additional locations are needed for each member 4500 // for each block array element, it is a compile-time error to specify locations on the block 4501 // members. That is, when locations would be under specified by applying them on block members, 4502 // they are not allowed on block members. For arrayed interfaces (those generally having an 4503 // extra level of arrayness due to interface expansion), the outer array is stripped before 4504 // applying this rule." 4505 void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation, TArraySizes* arraySizes) 4506 { 4507 if (memberWithLocation && arraySizes != nullptr) { 4508 if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0)) 4509 error(loc, "cannot use in a block array where new locations are needed for each block element", 4510 "location", ""); 4511 } 4512 } 4513 4514 // Do layout error checking with respect to a type. 4515 void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) 4516 { 4517 const TQualifier& qualifier = type.getQualifier(); 4518 4519 // first, intra-layout qualifier-only error checking 4520 layoutQualifierCheck(loc, qualifier); 4521 4522 // now, error checking combining type and qualifier 4523 4524 if (qualifier.hasAnyLocation()) { 4525 if (qualifier.hasLocation()) { 4526 if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) { 4527 if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers) 4528 error(loc, "too large for fragment output", "location", ""); 4529 } 4530 } 4531 if (qualifier.hasComponent()) { 4532 // "It is a compile-time error if this sequence of components gets larger than 3." 4533 if (qualifier.layoutComponent + type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1) > 4) 4534 error(loc, "type overflows the available 4 components", "component", ""); 4535 4536 // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these." 4537 if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct) 4538 error(loc, "cannot apply to a matrix, structure, or block", "component", ""); 4539 4540 // " It is a compile-time error to use component 1 or 3 as the beginning of a double or dvec2." 4541 if (type.getBasicType() == EbtDouble) 4542 if (qualifier.layoutComponent & 1) 4543 error(loc, "doubles cannot start on an odd-numbered component", "component", ""); 4544 } 4545 4546 switch (qualifier.storage) { 4547 case EvqVaryingIn: 4548 case EvqVaryingOut: 4549 if (type.getBasicType() == EbtBlock) 4550 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "location qualifier on in/out block"); 4551 break; 4552 case EvqUniform: 4553 case EvqBuffer: 4554 break; 4555 default: 4556 error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", ""); 4557 break; 4558 } 4559 4560 bool typeCollision; 4561 int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision); 4562 if (repeated >= 0 && ! typeCollision) 4563 error(loc, "overlapping use of location", "location", "%d", repeated); 4564 // "fragment-shader outputs ... if two variables are placed within the same 4565 // location, they must have the same underlying type (floating-point or integer)" 4566 if (typeCollision && language == EShLangFragment && qualifier.isPipeOutput()) 4567 error(loc, "fragment outputs sharing the same location must be the same basic type", "location", "%d", repeated); 4568 } 4569 4570 if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) { 4571 int repeated = intermediate.addXfbBufferOffset(type); 4572 if (repeated >= 0) 4573 error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer); 4574 4575 // "The offset must be a multiple of the size of the first component of the first 4576 // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate 4577 // containing a double, the offset must also be a multiple of 8..." 4578 if (type.containsBasicType(EbtDouble) && ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 8)) 4579 error(loc, "type contains double; xfb_offset must be a multiple of 8", "xfb_offset", ""); 4580 #ifdef AMD_EXTENSIONS 4581 // ..., if applied to an aggregate containing a float16_t, the offset must also be a multiple of 2..." 4582 else if (type.containsBasicType(EbtFloat16) && !IsMultipleOfPow2(qualifier.layoutXfbOffset, 2)) 4583 error(loc, "type contains half float; xfb_offset must be a multiple of 2", "xfb_offset", ""); 4584 #endif 4585 else if (! IsMultipleOfPow2(qualifier.layoutXfbOffset, 4)) 4586 error(loc, "must be a multiple of size of first component", "xfb_offset", ""); 4587 } 4588 4589 if (qualifier.hasXfbStride() && qualifier.hasXfbBuffer()) { 4590 if (! intermediate.setXfbBufferStride(qualifier.layoutXfbBuffer, qualifier.layoutXfbStride)) 4591 error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); 4592 } 4593 4594 if (qualifier.hasBinding()) { 4595 // Binding checking, from the spec: 4596 // 4597 // "If the binding point for any uniform or shader storage block instance is less than zero, or greater than or 4598 // equal to the implementation-dependent maximum number of uniform buffer bindings, a compile-time 4599 // error will occur. When the binding identifier is used with a uniform or shader storage block instanced as 4600 // an array of size N, all elements of the array from binding through binding + N - 1 must be within this 4601 // range." 4602 // 4603 if (! type.isOpaque() && type.getBasicType() != EbtBlock) 4604 error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", ""); 4605 if (type.getBasicType() == EbtSampler) { 4606 int lastBinding = qualifier.layoutBinding; 4607 if (type.isArray()) { 4608 if (type.isImplicitlySizedArray()) { 4609 lastBinding += 1; 4610 warn(loc, "assuming array size of one for compile-time checking of binding numbers for implicitly-sized array", "[]", ""); 4611 } else 4612 lastBinding += type.getCumulativeArraySize(); 4613 } 4614 if (lastBinding >= resources.maxCombinedTextureImageUnits) 4615 error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : ""); 4616 } 4617 if (type.getBasicType() == EbtAtomicUint) { 4618 if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { 4619 error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", ""); 4620 return; 4621 } 4622 } 4623 } 4624 4625 // atomic_uint 4626 if (type.getBasicType() == EbtAtomicUint) { 4627 if (! type.getQualifier().hasBinding()) 4628 error(loc, "layout(binding=X) is required", "atomic_uint", ""); 4629 } 4630 4631 // "The offset qualifier can only be used on block members of blocks..." 4632 if (qualifier.hasOffset()) { 4633 if (type.getBasicType() == EbtBlock) 4634 error(loc, "only applies to block members, not blocks", "offset", ""); 4635 } 4636 4637 // Image format 4638 if (qualifier.hasFormat()) { 4639 if (! type.isImage()) 4640 error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 4641 else { 4642 if (type.getSampler().type == EbtFloat && qualifier.layoutFormat > ElfFloatGuard) 4643 error(loc, "does not apply to floating point images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 4644 if (type.getSampler().type == EbtInt && (qualifier.layoutFormat < ElfFloatGuard || qualifier.layoutFormat > ElfIntGuard)) 4645 error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 4646 if (type.getSampler().type == EbtUint && qualifier.layoutFormat < ElfIntGuard) 4647 error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 4648 4649 if (profile == EEsProfile) { 4650 // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must 4651 // specify either memory qualifier readonly or the memory qualifier writeonly." 4652 if (! (qualifier.layoutFormat == ElfR32f || qualifier.layoutFormat == ElfR32i || qualifier.layoutFormat == ElfR32ui)) { 4653 if (! qualifier.readonly && ! qualifier.writeonly) 4654 error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); 4655 } 4656 } 4657 } 4658 } else if (type.isImage() && ! qualifier.writeonly) { 4659 const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier"; 4660 requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation); 4661 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation); 4662 } 4663 4664 if (qualifier.layoutPushConstant && type.getBasicType() != EbtBlock) 4665 error(loc, "can only be used with a block", "push_constant", ""); 4666 4667 // input attachment 4668 if (type.isSubpass()) { 4669 if (! qualifier.hasAttachment()) 4670 error(loc, "requires an input_attachment_index layout qualifier", "subpass", ""); 4671 } else { 4672 if (qualifier.hasAttachment()) 4673 error(loc, "can only be used with a subpass", "input_attachment_index", ""); 4674 } 4675 4676 // specialization-constant id 4677 if (qualifier.hasSpecConstantId()) { 4678 if (type.getQualifier().storage != EvqConst) 4679 error(loc, "can only be applied to 'const'-qualified scalar", "constant_id", ""); 4680 if (! type.isScalar()) 4681 error(loc, "can only be applied to a scalar", "constant_id", ""); 4682 switch (type.getBasicType()) 4683 { 4684 case EbtInt: 4685 case EbtUint: 4686 case EbtInt64: 4687 case EbtUint64: 4688 #ifdef AMD_EXTENSIONS 4689 case EbtInt16: 4690 case EbtUint16: 4691 #endif 4692 case EbtBool: 4693 case EbtFloat: 4694 case EbtDouble: 4695 #ifdef AMD_EXTENSIONS 4696 case EbtFloat16: 4697 #endif 4698 break; 4699 default: 4700 error(loc, "cannot be applied to this type", "constant_id", ""); 4701 break; 4702 } 4703 } 4704 } 4705 4706 // Do layout error checking that can be done within a layout qualifier proper, not needing to know 4707 // if there are blocks, atomic counters, variables, etc. 4708 void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier) 4709 { 4710 if (qualifier.storage == EvqShared && qualifier.hasLayout()) 4711 error(loc, "cannot apply layout qualifiers to a shared variable", "shared", ""); 4712 4713 // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)." 4714 if (qualifier.hasComponent() && ! qualifier.hasLocation()) 4715 error(loc, "must specify 'location' to use 'component'", "component", ""); 4716 4717 if (qualifier.hasAnyLocation()) { 4718 4719 // "As with input layout qualifiers, all shaders except compute shaders 4720 // allow *location* layout qualifiers on output variable declarations, 4721 // output block declarations, and output block member declarations." 4722 4723 switch (qualifier.storage) { 4724 case EvqVaryingIn: 4725 { 4726 const char* feature = "location qualifier on input"; 4727 if (profile == EEsProfile && version < 310) 4728 requireStage(loc, EShLangVertex, feature); 4729 else 4730 requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); 4731 if (language == EShLangVertex) { 4732 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 4733 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); 4734 profileRequires(loc, EEsProfile, 300, nullptr, feature); 4735 } else { 4736 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); 4737 profileRequires(loc, EEsProfile, 310, nullptr, feature); 4738 } 4739 break; 4740 } 4741 case EvqVaryingOut: 4742 { 4743 const char* feature = "location qualifier on output"; 4744 if (profile == EEsProfile && version < 310) 4745 requireStage(loc, EShLangFragment, feature); 4746 else 4747 requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); 4748 if (language == EShLangFragment) { 4749 const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; 4750 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); 4751 profileRequires(loc, EEsProfile, 300, nullptr, feature); 4752 } else { 4753 profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); 4754 profileRequires(loc, EEsProfile, 310, nullptr, feature); 4755 } 4756 break; 4757 } 4758 case EvqUniform: 4759 case EvqBuffer: 4760 { 4761 const char* feature = "location qualifier on uniform or buffer"; 4762 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); 4763 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); 4764 profileRequires(loc, EEsProfile, 310, nullptr, feature); 4765 break; 4766 } 4767 default: 4768 break; 4769 } 4770 if (qualifier.hasIndex()) { 4771 if (qualifier.storage != EvqVaryingOut) 4772 error(loc, "can only be used on an output", "index", ""); 4773 if (! qualifier.hasLocation()) 4774 error(loc, "can only be used with an explicit location", "index", ""); 4775 } 4776 } 4777 4778 if (qualifier.hasBinding()) { 4779 if (! qualifier.isUniformOrBuffer()) 4780 error(loc, "requires uniform or buffer storage qualifier", "binding", ""); 4781 } 4782 if (qualifier.hasStream()) { 4783 if (qualifier.storage != EvqVaryingOut) 4784 error(loc, "can only be used on an output", "stream", ""); 4785 } 4786 if (qualifier.hasXfb()) { 4787 if (qualifier.storage != EvqVaryingOut) 4788 error(loc, "can only be used on an output", "xfb layout qualifier", ""); 4789 } 4790 if (qualifier.hasUniformLayout()) { 4791 if (! qualifier.isUniformOrBuffer()) { 4792 if (qualifier.hasMatrix() || qualifier.hasPacking()) 4793 error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); 4794 if (qualifier.hasOffset() || qualifier.hasAlign()) 4795 error(loc, "offset/align can only be used on a uniform or buffer", "layout", ""); 4796 } 4797 } 4798 if (qualifier.layoutPushConstant) { 4799 if (qualifier.storage != EvqUniform) 4800 error(loc, "can only be used with a uniform", "push_constant", ""); 4801 if (qualifier.hasSet()) 4802 error(loc, "cannot be used with push_constant", "set", ""); 4803 } 4804 } 4805 4806 // For places that can't have shader-level layout qualifiers 4807 void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQualifiers& shaderQualifiers) 4808 { 4809 const char* message = "can only apply to a standalone qualifier"; 4810 4811 if (shaderQualifiers.geometry != ElgNone) 4812 error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), ""); 4813 if (shaderQualifiers.spacing != EvsNone) 4814 error(loc, message, TQualifier::getVertexSpacingString(shaderQualifiers.spacing), ""); 4815 if (shaderQualifiers.order != EvoNone) 4816 error(loc, message, TQualifier::getVertexOrderString(shaderQualifiers.order), ""); 4817 if (shaderQualifiers.pointMode) 4818 error(loc, message, "point_mode", ""); 4819 if (shaderQualifiers.invocations != TQualifier::layoutNotSet) 4820 error(loc, message, "invocations", ""); 4821 if (shaderQualifiers.earlyFragmentTests) 4822 error(loc, message, "early_fragment_tests", ""); 4823 if (shaderQualifiers.postDepthCoverage) 4824 error(loc, message, "post_depth_coverage", ""); 4825 for (int i = 0; i < 3; ++i) { 4826 if (shaderQualifiers.localSize[i] > 1) 4827 error(loc, message, "local_size", ""); 4828 if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) 4829 error(loc, message, "local_size id", ""); 4830 } 4831 if (shaderQualifiers.vertices != TQualifier::layoutNotSet) { 4832 if (language == EShLangGeometry) 4833 error(loc, message, "max_vertices", ""); 4834 else if (language == EShLangTessControl) 4835 error(loc, message, "vertices", ""); 4836 else 4837 assert(0); 4838 } 4839 if (shaderQualifiers.blendEquation) 4840 error(loc, message, "blend equation", ""); 4841 if (shaderQualifiers.numViews != TQualifier::layoutNotSet) 4842 error(loc, message, "num_views", ""); 4843 } 4844 4845 // Correct and/or advance an object's offset layout qualifier. 4846 void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol) 4847 { 4848 const TQualifier& qualifier = symbol.getType().getQualifier(); 4849 if (symbol.getType().getBasicType() == EbtAtomicUint) { 4850 if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) { 4851 4852 // Set the offset 4853 int offset; 4854 if (qualifier.hasOffset()) 4855 offset = qualifier.layoutOffset; 4856 else 4857 offset = atomicUintOffsets[qualifier.layoutBinding]; 4858 symbol.getWritableType().getQualifier().layoutOffset = offset; 4859 4860 // Check for overlap 4861 int numOffsets = 4; 4862 if (symbol.getType().isArray()) { 4863 if (symbol.getType().isExplicitlySizedArray()) 4864 numOffsets *= symbol.getType().getCumulativeArraySize(); 4865 else { 4866 // "It is a compile-time error to declare an unsized array of atomic_uint." 4867 error(loc, "array must be explicitly sized", "atomic_uint", ""); 4868 } 4869 } 4870 int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets); 4871 if (repeated >= 0) 4872 error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated); 4873 4874 // Bump the default offset 4875 atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets; 4876 } 4877 } 4878 } 4879 4880 // 4881 // Look up a function name in the symbol table, and make sure it is a function. 4882 // 4883 // Return the function symbol if found, otherwise nullptr. 4884 // 4885 const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 4886 { 4887 const TFunction* function = nullptr; 4888 4889 if (symbolTable.isFunctionNameVariable(call.getName())) { 4890 error(loc, "can't use function syntax on variable", call.getName().c_str(), ""); 4891 return nullptr; 4892 } 4893 4894 if (profile == EEsProfile || version < 120) 4895 function = findFunctionExact(loc, call, builtIn); 4896 else if (version < 400) 4897 function = findFunction120(loc, call, builtIn); 4898 else 4899 function = findFunction400(loc, call, builtIn); 4900 4901 return function; 4902 } 4903 4904 // Function finding algorithm for ES and desktop 110. 4905 const TFunction* TParseContext::findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 4906 { 4907 TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); 4908 if (symbol == nullptr) { 4909 error(loc, "no matching overloaded function found", call.getName().c_str(), ""); 4910 4911 return nullptr; 4912 } 4913 4914 return symbol->getAsFunction(); 4915 } 4916 4917 // Function finding algorithm for desktop versions 120 through 330. 4918 const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 4919 { 4920 // first, look for an exact match 4921 TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); 4922 if (symbol) 4923 return symbol->getAsFunction(); 4924 4925 // exact match not found, look through a list of overloaded functions of the same name 4926 4927 // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types 4928 // on input parameters (in or inout or default) must have a conversion from the calling argument type to the 4929 // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion 4930 // from the formal parameter type to the calling argument type. When argument conversions are used to find 4931 // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match 4932 // more than one function." 4933 4934 const TFunction* candidate = nullptr; 4935 TVector<const TFunction*> candidateList; 4936 symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); 4937 4938 for (auto it = candidateList.begin(); it != candidateList.end(); ++it) { 4939 const TFunction& function = *(*it); 4940 4941 // to even be a potential match, number of arguments has to match 4942 if (call.getParamCount() != function.getParamCount()) 4943 continue; 4944 4945 bool possibleMatch = true; 4946 for (int i = 0; i < function.getParamCount(); ++i) { 4947 // same types is easy 4948 if (*function[i].type == *call[i].type) 4949 continue; 4950 4951 // We have a mismatch in type, see if it is implicitly convertible 4952 4953 if (function[i].type->isArray() || call[i].type->isArray() || 4954 ! function[i].type->sameElementShape(*call[i].type)) 4955 possibleMatch = false; 4956 else { 4957 // do direction-specific checks for conversion of basic type 4958 if (function[i].type->getQualifier().isParamInput()) { 4959 if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType())) 4960 possibleMatch = false; 4961 } 4962 if (function[i].type->getQualifier().isParamOutput()) { 4963 if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType())) 4964 possibleMatch = false; 4965 } 4966 } 4967 if (! possibleMatch) 4968 break; 4969 } 4970 if (possibleMatch) { 4971 if (candidate) { 4972 // our second match, meaning ambiguity 4973 error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), ""); 4974 } else 4975 candidate = &function; 4976 } 4977 } 4978 4979 if (candidate == nullptr) 4980 error(loc, "no matching overloaded function found", call.getName().c_str(), ""); 4981 4982 return candidate; 4983 } 4984 4985 // Function finding algorithm for desktop version 400 and above. 4986 // 4987 // "When function calls are resolved, an exact type match for all the arguments 4988 // is sought. If an exact match is found, all other functions are ignored, and 4989 // the exact match is used. If no exact match is found, then the implicit 4990 // conversions in section 4.1.10 Implicit Conversions will be applied to find 4991 // a match. Mismatched types on input parameters (in or inout or default) must 4992 // have a conversion from the calling argument type to the formal parameter type. 4993 // Mismatched types on output parameters (out or inout) must have a conversion 4994 // from the formal parameter type to the calling argument type. 4995 // 4996 // "If implicit conversions can be used to find more than one matching function, 4997 // a single best-matching function is sought. To determine a best match, the 4998 // conversions between calling argument and formal parameter types are compared 4999 // for each function argument and pair of matching functions. After these 5000 // comparisons are performed, each pair of matching functions are compared. 5001 // A function declaration A is considered a better match than function 5002 // declaration B if 5003 // 5004 // * for at least one function argument, the conversion for that argument in A 5005 // is better than the corresponding conversion in B; and 5006 // * there is no function argument for which the conversion in B is better than 5007 // the corresponding conversion in A. 5008 // 5009 // "If a single function declaration is considered a better match than every 5010 // other matching function declaration, it will be used. Otherwise, a 5011 // compile-time semantic error for an ambiguous overloaded function call occurs. 5012 // 5013 // "To determine whether the conversion for a single argument in one match is 5014 // better than that for another match, the following rules are applied, in order: 5015 // 5016 // 1. An exact match is better than a match involving any implicit conversion. 5017 // 2. A match involving an implicit conversion from float to double is better 5018 // than a match involving any other implicit conversion. 5019 // 3. A match involving an implicit conversion from either int or uint to float 5020 // is better than a match involving an implicit conversion from either int 5021 // or uint to double. 5022 // 5023 // "If none of the rules above apply to a particular pair of conversions, neither 5024 // conversion is considered better than the other." 5025 // 5026 const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn) 5027 { 5028 // first, look for an exact match 5029 TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); 5030 if (symbol) 5031 return symbol->getAsFunction(); 5032 5033 // no exact match, use the generic selector, parameterized by the GLSL rules 5034 5035 // create list of candidates to send 5036 TVector<const TFunction*> candidateList; 5037 symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); 5038 5039 // can 'from' convert to 'to'? 5040 const auto convertible = [this](const TType& from, const TType& to, TOperator, int) -> bool { 5041 if (from == to) 5042 return true; 5043 if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) 5044 return false; 5045 return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); 5046 }; 5047 5048 // Is 'to2' a better conversion than 'to1'? 5049 // Ties should not be considered as better. 5050 // Assumes 'convertible' already said true. 5051 const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool { 5052 // 1. exact match 5053 if (from == to2) 5054 return from != to1; 5055 if (from == to1) 5056 return false; 5057 5058 // 2. float -> double is better 5059 if (from.getBasicType() == EbtFloat) { 5060 if (to2.getBasicType() == EbtDouble && to1.getBasicType() != EbtDouble) 5061 return true; 5062 } 5063 5064 // 3. -> float is better than -> double 5065 return to2.getBasicType() == EbtFloat && to1.getBasicType() == EbtDouble; 5066 }; 5067 5068 // for ambiguity reporting 5069 bool tie = false; 5070 5071 // send to the generic selector 5072 const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); 5073 5074 if (bestMatch == nullptr) 5075 error(loc, "no matching overloaded function found", call.getName().c_str(), ""); 5076 else if (tie) 5077 error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); 5078 5079 return bestMatch; 5080 } 5081 5082 // When a declaration includes a type, but not a variable name, it can be 5083 // to establish defaults. 5084 void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType) 5085 { 5086 if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding() && publicType.qualifier.hasOffset()) { 5087 if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { 5088 error(loc, "atomic_uint binding is too large", "binding", ""); 5089 return; 5090 } 5091 atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; 5092 return; 5093 } 5094 5095 if (publicType.qualifier.hasLayout()) 5096 warn(loc, "useless application of layout qualifier", "layout", ""); 5097 } 5098 5099 // 5100 // Do everything necessary to handle a variable (non-block) declaration. 5101 // Either redeclaring a variable, or making a new one, updating the symbol 5102 // table, and all error checking. 5103 // 5104 // Returns a subtree node that computes an initializer, if needed. 5105 // Returns nullptr if there is no code to execute for initialization. 5106 // 5107 // 'publicType' is the type part of the declaration (to the left) 5108 // 'arraySizes' is the arrayness tagged on the identifier (to the right) 5109 // 5110 TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType, TArraySizes* arraySizes, TIntermTyped* initializer) 5111 { 5112 TType type(publicType); // shallow copy; 'type' shares the arrayness and structure definition with 'publicType' 5113 if (type.isImplicitlySizedArray()) { 5114 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b 5115 // of different sizes, for this case sharing the shallow copy of arrayness 5116 // with the publicType oversubscribes it, so get a deep copy of the arrayness. 5117 type.newArraySizes(*publicType.arraySizes); 5118 } 5119 5120 if (voidErrorCheck(loc, identifier, type.getBasicType())) 5121 return nullptr; 5122 5123 if (initializer) 5124 rValueErrorCheck(loc, "initializer", initializer); 5125 else 5126 nonInitConstCheck(loc, identifier, type); 5127 5128 samplerCheck(loc, type, identifier, initializer); 5129 atomicUintCheck(loc, type, identifier); 5130 transparentOpaqueCheck(loc, type, identifier); 5131 5132 if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger)) 5133 error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", ""); 5134 if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.layoutDepth != EldNone) 5135 error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", ""); 5136 5137 // Check for redeclaration of built-ins and/or attempting to declare a reserved name 5138 TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers); 5139 if (symbol == nullptr) 5140 reservedErrorCheck(loc, identifier); 5141 5142 inheritGlobalDefaults(type.getQualifier()); 5143 5144 // Declare the variable 5145 if (arraySizes || type.isArray()) { 5146 // Arrayness is potentially coming both from the type and from the 5147 // variable: "int[] a[];" or just one or the other. 5148 // Merge it all to the type, so all arrayness is part of the type. 5149 arrayDimCheck(loc, &type, arraySizes); 5150 arrayDimMerge(type, arraySizes); 5151 5152 // Check that implicit sizing is only where allowed. 5153 arraySizesCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false); 5154 5155 if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type)) 5156 declareArray(loc, identifier, type, symbol); 5157 5158 if (initializer) { 5159 profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "initializer"); 5160 profileRequires(loc, EEsProfile, 300, nullptr, "initializer"); 5161 } 5162 } else { 5163 // non-array case 5164 if (symbol == nullptr) 5165 symbol = declareNonArray(loc, identifier, type); 5166 else if (type != symbol->getType()) 5167 error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); 5168 } 5169 5170 if (symbol == nullptr) 5171 return nullptr; 5172 5173 // Deal with initializer 5174 TIntermNode* initNode = nullptr; 5175 if (symbol != nullptr && initializer) { 5176 TVariable* variable = symbol->getAsVariable(); 5177 if (! variable) { 5178 error(loc, "initializer requires a variable, not a member", identifier.c_str(), ""); 5179 return nullptr; 5180 } 5181 initNode = executeInitializer(loc, initializer, variable); 5182 } 5183 5184 // look for errors in layout qualifier use 5185 layoutObjectCheck(loc, *symbol); 5186 5187 // fix up 5188 fixOffset(loc, *symbol); 5189 5190 return initNode; 5191 } 5192 5193 // Pick up global defaults from the provide global defaults into dst. 5194 void TParseContext::inheritGlobalDefaults(TQualifier& dst) const 5195 { 5196 if (dst.storage == EvqVaryingOut) { 5197 if (! dst.hasStream() && language == EShLangGeometry) 5198 dst.layoutStream = globalOutputDefaults.layoutStream; 5199 if (! dst.hasXfbBuffer()) 5200 dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; 5201 } 5202 } 5203 5204 // 5205 // Make an internal-only variable whose name is for debug purposes only 5206 // and won't be searched for. Callers will only use the return value to use 5207 // the variable, not the name to look it up. It is okay if the name 5208 // is the same as other names; there won't be any conflict. 5209 // 5210 TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const 5211 { 5212 TString* nameString = NewPoolTString(name); 5213 TVariable* variable = new TVariable(nameString, type); 5214 symbolTable.makeInternalVariable(*variable); 5215 5216 return variable; 5217 } 5218 5219 // 5220 // Declare a non-array variable, the main point being there is no redeclaration 5221 // for resizing allowed. 5222 // 5223 // Return the successfully declared variable. 5224 // 5225 TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type) 5226 { 5227 // make a new variable 5228 TVariable* variable = new TVariable(&identifier, type); 5229 5230 ioArrayCheck(loc, type, identifier); 5231 5232 // add variable to symbol table 5233 if (symbolTable.insert(*variable)) { 5234 if (symbolTable.atGlobalLevel()) 5235 trackLinkage(*variable); 5236 return variable; 5237 } 5238 5239 error(loc, "redefinition", variable->getName().c_str(), ""); 5240 return nullptr; 5241 } 5242 5243 // 5244 // Handle all types of initializers from the grammar. 5245 // 5246 // Returning nullptr just means there is no code to execute to handle the 5247 // initializer, which will, for example, be the case for constant initializers. 5248 // 5249 TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable) 5250 { 5251 // 5252 // Identifier must be of type constant, a global, or a temporary, and 5253 // starting at version 120, desktop allows uniforms to have initializers. 5254 // 5255 TStorageQualifier qualifier = variable->getType().getQualifier().storage; 5256 if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst || 5257 (qualifier == EvqUniform && profile != EEsProfile && version >= 120))) { 5258 error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), ""); 5259 return nullptr; 5260 } 5261 arrayObjectCheck(loc, variable->getType(), "array initializer"); 5262 5263 // 5264 // If the initializer was from braces { ... }, we convert the whole subtree to a 5265 // constructor-style subtree, allowing the rest of the code to operate 5266 // identically for both kinds of initializers. 5267 // 5268 // Type can't be deduced from the initializer list, so a skeletal type to 5269 // follow has to be passed in. Constness and specialization-constness 5270 // should be deduced bottom up, not dictated by the skeletal type. 5271 // 5272 TType skeletalType; 5273 skeletalType.shallowCopy(variable->getType()); 5274 skeletalType.getQualifier().makeTemporary(); 5275 initializer = convertInitializerList(loc, skeletalType, initializer); 5276 if (! initializer) { 5277 // error recovery; don't leave const without constant values 5278 if (qualifier == EvqConst) 5279 variable->getWritableType().getQualifier().makeTemporary(); 5280 return nullptr; 5281 } 5282 5283 // Fix outer arrayness if variable is unsized, getting size from the initializer 5284 if (initializer->getType().isExplicitlySizedArray() && 5285 variable->getType().isImplicitlySizedArray()) 5286 variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize()); 5287 5288 // Inner arrayness can also get set by an initializer 5289 if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() && 5290 initializer->getType().getArraySizes()->getNumDims() == 5291 variable->getType().getArraySizes()->getNumDims()) { 5292 // adopt unsized sizes from the initializer's sizes 5293 for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) { 5294 if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) 5295 variable->getWritableType().getArraySizes().setDimSize(d, initializer->getType().getArraySizes()->getDimSize(d)); 5296 } 5297 } 5298 5299 // Uniforms require a compile-time constant initializer 5300 if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { 5301 error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); 5302 variable->getWritableType().getQualifier().makeTemporary(); 5303 return nullptr; 5304 } 5305 // Global consts require a constant initializer (specialization constant is okay) 5306 if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { 5307 error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); 5308 variable->getWritableType().getQualifier().makeTemporary(); 5309 return nullptr; 5310 } 5311 5312 // Const variables require a constant initializer, depending on version 5313 if (qualifier == EvqConst) { 5314 if (! initializer->getType().getQualifier().isConstant()) { 5315 const char* initFeature = "non-constant initializer"; 5316 requireProfile(loc, ~EEsProfile, initFeature); 5317 profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); 5318 variable->getWritableType().getQualifier().storage = EvqConstReadOnly; 5319 qualifier = EvqConstReadOnly; 5320 } 5321 } else { 5322 // Non-const global variables in ES need a const initializer. 5323 // 5324 // "In declarations of global variables with no storage qualifier or with a const 5325 // qualifier any initializer must be a constant expression." 5326 if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { 5327 const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)"; 5328 if (profile == EEsProfile) { 5329 if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers)) 5330 warn(loc, "not allowed in this version", initFeature, ""); 5331 else 5332 profileRequires(loc, EEsProfile, 0, E_GL_EXT_shader_non_constant_global_initializers, initFeature); 5333 } 5334 } 5335 } 5336 5337 if (qualifier == EvqConst || qualifier == EvqUniform) { 5338 // Compile-time tagging of the variable with its constant value... 5339 5340 initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); 5341 if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) { 5342 error(loc, "non-matching or non-convertible constant type for const initializer", 5343 variable->getType().getStorageQualifierString(), ""); 5344 variable->getWritableType().getQualifier().makeTemporary(); 5345 return nullptr; 5346 } 5347 5348 // We either have a folded constant in getAsConstantUnion, or we have to use 5349 // the initializer's subtree in the AST to represent the computation of a 5350 // specialization constant. 5351 assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant()); 5352 if (initializer->getAsConstantUnion()) 5353 variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); 5354 else { 5355 // It's a specialization constant. 5356 variable->getWritableType().getQualifier().makeSpecConstant(); 5357 5358 // Keep the subtree that computes the specialization constant with the variable. 5359 // Later, a symbol node will adopt the subtree from the variable. 5360 variable->setConstSubtree(initializer); 5361 } 5362 } else { 5363 // normal assigning of a value to a variable... 5364 specializationCheck(loc, initializer->getType(), "initializer"); 5365 TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); 5366 TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc); 5367 if (! initNode) 5368 assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); 5369 5370 return initNode; 5371 } 5372 5373 return nullptr; 5374 } 5375 5376 // 5377 // Reprocess any initializer-list (the "{ ... }" syntax) parts of the 5378 // initializer. 5379 // 5380 // Need to hierarchically assign correct types and implicit 5381 // conversions. Will do this mimicking the same process used for 5382 // creating a constructor-style initializer, ensuring we get the 5383 // same form. However, it has to in parallel walk the 'type' 5384 // passed in, as type cannot be deduced from an initializer list. 5385 // 5386 TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer) 5387 { 5388 // Will operate recursively. Once a subtree is found that is constructor style, 5389 // everything below it is already good: Only the "top part" of the initializer 5390 // can be an initializer list, where "top part" can extend for several (or all) levels. 5391 5392 // see if we have bottomed out in the tree within the initializer-list part 5393 TIntermAggregate* initList = initializer->getAsAggregate(); 5394 if (! initList || initList->getOp() != EOpNull) 5395 return initializer; 5396 5397 // Of the initializer-list set of nodes, need to process bottom up, 5398 // so recurse deep, then process on the way up. 5399 5400 // Go down the tree here... 5401 if (type.isArray()) { 5402 // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate. 5403 // Later on, initializer execution code will deal with array size logic. 5404 TType arrayType; 5405 arrayType.shallowCopy(type); // sharing struct stuff is fine 5406 arrayType.newArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below 5407 5408 // edit array sizes to fill in unsized dimensions 5409 arrayType.changeOuterArraySize((int)initList->getSequence().size()); 5410 TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped(); 5411 if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() && 5412 arrayType.getArraySizes().getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) { 5413 for (int d = 1; d < arrayType.getArraySizes().getNumDims(); ++d) { 5414 if (arrayType.getArraySizes().getDimSize(d) == UnsizedArraySize) 5415 arrayType.getArraySizes().setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1)); 5416 } 5417 } 5418 5419 TType elementType(arrayType, 0); // dereferenced type 5420 for (size_t i = 0; i < initList->getSequence().size(); ++i) { 5421 initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped()); 5422 if (initList->getSequence()[i] == nullptr) 5423 return nullptr; 5424 } 5425 5426 return addConstructor(loc, initList, arrayType); 5427 } else if (type.isStruct()) { 5428 if (type.getStruct()->size() != initList->getSequence().size()) { 5429 error(loc, "wrong number of structure members", "initializer list", ""); 5430 return nullptr; 5431 } 5432 for (size_t i = 0; i < type.getStruct()->size(); ++i) { 5433 initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped()); 5434 if (initList->getSequence()[i] == nullptr) 5435 return nullptr; 5436 } 5437 } else if (type.isMatrix()) { 5438 if (type.getMatrixCols() != (int)initList->getSequence().size()) { 5439 error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str()); 5440 return nullptr; 5441 } 5442 TType vectorType(type, 0); // dereferenced type 5443 for (int i = 0; i < type.getMatrixCols(); ++i) { 5444 initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped()); 5445 if (initList->getSequence()[i] == nullptr) 5446 return nullptr; 5447 } 5448 } else if (type.isVector()) { 5449 if (type.getVectorSize() != (int)initList->getSequence().size()) { 5450 error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str()); 5451 return nullptr; 5452 } 5453 } else { 5454 error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str()); 5455 return nullptr; 5456 } 5457 5458 // Now that the subtree is processed, process this node as if the 5459 // initializer list is a set of arguments to a constructor. 5460 TIntermNode* emulatedConstructorArguments; 5461 if (initList->getSequence().size() == 1) 5462 emulatedConstructorArguments = initList->getSequence()[0]; 5463 else 5464 emulatedConstructorArguments = initList; 5465 return addConstructor(loc, emulatedConstructorArguments, type); 5466 } 5467 5468 // 5469 // Test for the correctness of the parameters passed to various constructor functions 5470 // and also convert them to the right data type, if allowed and required. 5471 // 5472 // 'node' is what to construct from. 5473 // 'type' is what type to construct. 5474 // 5475 // Returns nullptr for an error or the constructed node (aggregate or typed) for no error. 5476 // 5477 TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type) 5478 { 5479 if (node == nullptr || node->getAsTyped() == nullptr) 5480 return nullptr; 5481 rValueErrorCheck(loc, "constructor", node->getAsTyped()); 5482 5483 TIntermAggregate* aggrNode = node->getAsAggregate(); 5484 TOperator op = intermediate.mapTypeToConstructorOp(type); 5485 5486 // Combined texture-sampler constructors are completely semantic checked 5487 // in constructorTextureSamplerError() 5488 if (op == EOpConstructTextureSampler) 5489 return intermediate.setAggregateOperator(aggrNode, op, type, loc); 5490 5491 TTypeList::const_iterator memberTypes; 5492 if (op == EOpConstructStruct) 5493 memberTypes = type.getStruct()->begin(); 5494 5495 TType elementType; 5496 if (type.isArray()) { 5497 TType dereferenced(type, 0); 5498 elementType.shallowCopy(dereferenced); 5499 } else 5500 elementType.shallowCopy(type); 5501 5502 bool singleArg; 5503 if (aggrNode) { 5504 if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) 5505 singleArg = true; 5506 else 5507 singleArg = false; 5508 } else 5509 singleArg = true; 5510 5511 TIntermTyped *newNode; 5512 if (singleArg) { 5513 // If structure constructor or array constructor is being called 5514 // for only one parameter inside the structure, we need to call constructAggregate function once. 5515 if (type.isArray()) 5516 newNode = constructAggregate(node, elementType, 1, node->getLoc()); 5517 else if (op == EOpConstructStruct) 5518 newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); 5519 else 5520 newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false); 5521 5522 if (newNode && (type.isArray() || op == EOpConstructStruct)) 5523 newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); 5524 5525 return newNode; 5526 } 5527 5528 // 5529 // Handle list of arguments. 5530 // 5531 TIntermSequence &sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor 5532 // if the structure constructor contains more than one parameter, then construct 5533 // each parameter 5534 5535 int paramCount = 0; // keeps track of the constructor parameter number being checked 5536 5537 // for each parameter to the constructor call, check to see if the right type is passed or convert them 5538 // to the right type if possible (and allowed). 5539 // for structure constructors, just check if the right type is passed, no conversion is allowed. 5540 for (TIntermSequence::iterator p = sequenceVector.begin(); 5541 p != sequenceVector.end(); p++, paramCount++) { 5542 if (type.isArray()) 5543 newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc()); 5544 else if (op == EOpConstructStruct) 5545 newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc()); 5546 else 5547 newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); 5548 5549 if (newNode) 5550 *p = newNode; 5551 else 5552 return nullptr; 5553 } 5554 5555 return intermediate.setAggregateOperator(aggrNode, op, type, loc); 5556 } 5557 5558 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value 5559 // for the parameter to the constructor (passed to this function). Essentially, it converts 5560 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 5561 // float, then float is converted to int. 5562 // 5563 // Returns nullptr for an error or the constructed node. 5564 // 5565 TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, const TSourceLoc& loc, bool subset) 5566 { 5567 TIntermTyped* newNode; 5568 TOperator basicOp; 5569 5570 // 5571 // First, convert types as needed. 5572 // 5573 switch (op) { 5574 case EOpConstructVec2: 5575 case EOpConstructVec3: 5576 case EOpConstructVec4: 5577 case EOpConstructMat2x2: 5578 case EOpConstructMat2x3: 5579 case EOpConstructMat2x4: 5580 case EOpConstructMat3x2: 5581 case EOpConstructMat3x3: 5582 case EOpConstructMat3x4: 5583 case EOpConstructMat4x2: 5584 case EOpConstructMat4x3: 5585 case EOpConstructMat4x4: 5586 case EOpConstructFloat: 5587 basicOp = EOpConstructFloat; 5588 break; 5589 5590 case EOpConstructDVec2: 5591 case EOpConstructDVec3: 5592 case EOpConstructDVec4: 5593 case EOpConstructDMat2x2: 5594 case EOpConstructDMat2x3: 5595 case EOpConstructDMat2x4: 5596 case EOpConstructDMat3x2: 5597 case EOpConstructDMat3x3: 5598 case EOpConstructDMat3x4: 5599 case EOpConstructDMat4x2: 5600 case EOpConstructDMat4x3: 5601 case EOpConstructDMat4x4: 5602 case EOpConstructDouble: 5603 basicOp = EOpConstructDouble; 5604 break; 5605 5606 #ifdef AMD_EXTENSIONS 5607 case EOpConstructF16Vec2: 5608 case EOpConstructF16Vec3: 5609 case EOpConstructF16Vec4: 5610 case EOpConstructF16Mat2x2: 5611 case EOpConstructF16Mat2x3: 5612 case EOpConstructF16Mat2x4: 5613 case EOpConstructF16Mat3x2: 5614 case EOpConstructF16Mat3x3: 5615 case EOpConstructF16Mat3x4: 5616 case EOpConstructF16Mat4x2: 5617 case EOpConstructF16Mat4x3: 5618 case EOpConstructF16Mat4x4: 5619 case EOpConstructFloat16: 5620 basicOp = EOpConstructFloat16; 5621 break; 5622 #endif 5623 5624 case EOpConstructIVec2: 5625 case EOpConstructIVec3: 5626 case EOpConstructIVec4: 5627 case EOpConstructInt: 5628 basicOp = EOpConstructInt; 5629 break; 5630 5631 case EOpConstructUVec2: 5632 case EOpConstructUVec3: 5633 case EOpConstructUVec4: 5634 case EOpConstructUint: 5635 basicOp = EOpConstructUint; 5636 break; 5637 5638 case EOpConstructI64Vec2: 5639 case EOpConstructI64Vec3: 5640 case EOpConstructI64Vec4: 5641 case EOpConstructInt64: 5642 basicOp = EOpConstructInt64; 5643 break; 5644 5645 case EOpConstructU64Vec2: 5646 case EOpConstructU64Vec3: 5647 case EOpConstructU64Vec4: 5648 case EOpConstructUint64: 5649 basicOp = EOpConstructUint64; 5650 break; 5651 5652 #ifdef AMD_EXTENSIONS 5653 case EOpConstructI16Vec2: 5654 case EOpConstructI16Vec3: 5655 case EOpConstructI16Vec4: 5656 case EOpConstructInt16: 5657 basicOp = EOpConstructInt16; 5658 break; 5659 5660 case EOpConstructU16Vec2: 5661 case EOpConstructU16Vec3: 5662 case EOpConstructU16Vec4: 5663 case EOpConstructUint16: 5664 basicOp = EOpConstructUint16; 5665 break; 5666 #endif 5667 5668 case EOpConstructBVec2: 5669 case EOpConstructBVec3: 5670 case EOpConstructBVec4: 5671 case EOpConstructBool: 5672 basicOp = EOpConstructBool; 5673 break; 5674 5675 default: 5676 error(loc, "unsupported construction", "", ""); 5677 5678 return nullptr; 5679 } 5680 newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc()); 5681 if (newNode == nullptr) { 5682 error(loc, "can't convert", "constructor", ""); 5683 return nullptr; 5684 } 5685 5686 // 5687 // Now, if there still isn't an operation to do the construction, and we need one, add one. 5688 // 5689 5690 // Otherwise, skip out early. 5691 if (subset || (newNode != node && newNode->getType() == type)) 5692 return newNode; 5693 5694 // setAggregateOperator will insert a new node for the constructor, as needed. 5695 return intermediate.setAggregateOperator(newNode, op, type, loc); 5696 } 5697 5698 // This function tests for the type of the parameters to the structure or array constructor. Raises 5699 // an error message if the expected type does not match the parameter passed to the constructor. 5700 // 5701 // Returns nullptr for an error or the input node itself if the expected and the given parameter types match. 5702 // 5703 TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc) 5704 { 5705 TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); 5706 if (! converted || converted->getType() != type) { 5707 error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, 5708 node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str()); 5709 5710 return nullptr; 5711 } 5712 5713 return converted; 5714 } 5715 5716 // 5717 // Do everything needed to add an interface block. 5718 // 5719 void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes) 5720 { 5721 blockStageIoCheck(loc, currentBlockQualifier); 5722 blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr); 5723 if (arraySizes) { 5724 arraySizesCheck(loc, currentBlockQualifier, arraySizes, false, false); 5725 arrayDimCheck(loc, arraySizes, 0); 5726 if (arraySizes->getNumDims() > 1) 5727 requireProfile(loc, ~EEsProfile, "array-of-array of block"); 5728 } 5729 5730 // fix and check for member storage qualifiers and types that don't belong within a block 5731 for (unsigned int member = 0; member < typeList.size(); ++member) { 5732 TType& memberType = *typeList[member].type; 5733 TQualifier& memberQualifier = memberType.getQualifier(); 5734 const TSourceLoc& memberLoc = typeList[member].loc; 5735 globalQualifierFixCheck(memberLoc, memberQualifier); 5736 if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage) 5737 error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), ""); 5738 memberQualifier.storage = currentBlockQualifier.storage; 5739 if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())) 5740 error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), ""); 5741 if (memberType.isArray()) 5742 arraySizesCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, member == typeList.size() - 1); 5743 if (memberQualifier.hasOffset()) { 5744 if (spvVersion.spv == 0) { 5745 requireProfile(memberLoc, ~EEsProfile, "offset on block member"); 5746 profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member"); 5747 } 5748 } 5749 5750 if (memberType.containsOpaque()) 5751 error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), ""); 5752 } 5753 5754 // This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will 5755 // do all the rest. 5756 if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) { 5757 redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes); 5758 return; 5759 } 5760 5761 // Not a redeclaration of a built-in; check that all names are user names. 5762 reservedErrorCheck(loc, *blockName); 5763 if (instanceName) 5764 reservedErrorCheck(loc, *instanceName); 5765 for (unsigned int member = 0; member < typeList.size(); ++member) 5766 reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName()); 5767 5768 // Make default block qualification, and adjust the member qualifications 5769 5770 TQualifier defaultQualification; 5771 switch (currentBlockQualifier.storage) { 5772 case EvqUniform: defaultQualification = globalUniformDefaults; break; 5773 case EvqBuffer: defaultQualification = globalBufferDefaults; break; 5774 case EvqVaryingIn: defaultQualification = globalInputDefaults; break; 5775 case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; 5776 default: defaultQualification.clear(); break; 5777 } 5778 5779 // Special case for "push_constant uniform", which has a default of std430, 5780 // contrary to normal uniform defaults, and can't have a default tracked for it. 5781 if (currentBlockQualifier.layoutPushConstant && !currentBlockQualifier.hasPacking()) 5782 currentBlockQualifier.layoutPacking = ElpStd430; 5783 5784 // fix and check for member layout qualifiers 5785 5786 mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true); 5787 5788 // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." 5789 if (currentBlockQualifier.hasAlign()) { 5790 if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) { 5791 error(loc, "can only be used with std140 or std430 layout packing", "align", ""); 5792 defaultQualification.layoutAlign = -1; 5793 } 5794 } 5795 5796 bool memberWithLocation = false; 5797 bool memberWithoutLocation = false; 5798 for (unsigned int member = 0; member < typeList.size(); ++member) { 5799 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 5800 const TSourceLoc& memberLoc = typeList[member].loc; 5801 if (memberQualifier.hasStream()) { 5802 if (defaultQualification.layoutStream != memberQualifier.layoutStream) 5803 error(memberLoc, "member cannot contradict block", "stream", ""); 5804 } 5805 5806 // "This includes a block's inheritance of the 5807 // current global default buffer, a block member's inheritance of the block's 5808 // buffer, and the requirement that any *xfb_buffer* declared on a block 5809 // member must match the buffer inherited from the block." 5810 if (memberQualifier.hasXfbBuffer()) { 5811 if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer) 5812 error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); 5813 } 5814 5815 if (memberQualifier.hasPacking()) 5816 error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), ""); 5817 if (memberQualifier.hasLocation()) { 5818 const char* feature = "location on block member"; 5819 switch (currentBlockQualifier.storage) { 5820 case EvqVaryingIn: 5821 case EvqVaryingOut: 5822 requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature); 5823 profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); 5824 profileRequires(memberLoc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); 5825 memberWithLocation = true; 5826 break; 5827 default: 5828 error(memberLoc, "can only use in an in/out block", feature, ""); 5829 break; 5830 } 5831 } else 5832 memberWithoutLocation = true; 5833 5834 // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts." 5835 // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." 5836 if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) { 5837 if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) 5838 error(memberLoc, "can only be used with std140 or std430 layout packing", "offset/align", ""); 5839 } 5840 5841 TQualifier newMemberQualification = defaultQualification; 5842 mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false); 5843 memberQualifier = newMemberQualification; 5844 } 5845 5846 layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes); 5847 5848 // Process the members 5849 fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); 5850 fixBlockXfbOffsets(currentBlockQualifier, typeList); 5851 fixBlockUniformOffsets(currentBlockQualifier, typeList); 5852 for (unsigned int member = 0; member < typeList.size(); ++member) 5853 layoutTypeCheck(typeList[member].loc, *typeList[member].type); 5854 5855 // reverse merge, so that currentBlockQualifier now has all layout information 5856 // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) 5857 mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true); 5858 5859 // 5860 // Build and add the interface block as a new type named 'blockName' 5861 // 5862 5863 TType blockType(&typeList, *blockName, currentBlockQualifier); 5864 if (arraySizes) 5865 blockType.newArraySizes(*arraySizes); 5866 else 5867 ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName); 5868 5869 // 5870 // Don't make a user-defined type out of block name; that will cause an error 5871 // if the same block name gets reused in a different interface. 5872 // 5873 // "Block names have no other use within a shader 5874 // beyond interface matching; it is a compile-time error to use a block name at global scope for anything 5875 // other than as a block name (e.g., use of a block name for a global variable name or function name is 5876 // currently reserved)." 5877 // 5878 // Use the symbol table to prevent normal reuse of the block's name, as a variable entry, 5879 // whose type is EbtBlock, but without all the structure; that will come from the type 5880 // the instances point to. 5881 // 5882 TType blockNameType(EbtBlock, blockType.getQualifier().storage); 5883 TVariable* blockNameVar = new TVariable(blockName, blockNameType); 5884 if (! symbolTable.insert(*blockNameVar)) { 5885 TSymbol* existingName = symbolTable.find(*blockName); 5886 if (existingName->getType().getBasicType() == EbtBlock) { 5887 if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { 5888 error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString()); 5889 return; 5890 } 5891 } else { 5892 error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); 5893 return; 5894 } 5895 } 5896 5897 // Add the variable, as anonymous or named instanceName. 5898 // Make an anonymous variable if no name was provided. 5899 if (! instanceName) 5900 instanceName = NewPoolTString(""); 5901 5902 TVariable& variable = *new TVariable(instanceName, blockType); 5903 if (! symbolTable.insert(variable)) { 5904 if (*instanceName == "") 5905 error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), ""); 5906 else 5907 error(loc, "block instance name redefinition", variable.getName().c_str(), ""); 5908 5909 return; 5910 } 5911 5912 // Check for general layout qualifier errors 5913 layoutObjectCheck(loc, variable); 5914 5915 // fix up 5916 if (isIoResizeArray(blockType)) { 5917 ioArraySymbolResizeList.push_back(&variable); 5918 checkIoArraysConsistency(loc, true); 5919 } else 5920 fixIoArraySize(loc, variable.getWritableType()); 5921 5922 // Save it in the AST for linker use. 5923 trackLinkage(variable); 5924 } 5925 5926 // Do all block-declaration checking regarding the combination of in/out/uniform/buffer 5927 // with a particular stage. 5928 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier) 5929 { 5930 switch (qualifier.storage) { 5931 case EvqUniform: 5932 profileRequires(loc, EEsProfile, 300, nullptr, "uniform block"); 5933 profileRequires(loc, ENoProfile, 140, nullptr, "uniform block"); 5934 if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.layoutPushConstant) 5935 error(loc, "requires the 'buffer' storage qualifier", "std430", ""); 5936 break; 5937 case EvqBuffer: 5938 requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block"); 5939 profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block"); 5940 profileRequires(loc, EEsProfile, 310, nullptr, "buffer block"); 5941 break; 5942 case EvqVaryingIn: 5943 profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "input block"); 5944 // It is a compile-time error to have an input block in a vertex shader or an output block in a fragment shader 5945 // "Compute shaders do not permit user-defined input variables..." 5946 requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|EShLangFragmentMask), "input block"); 5947 if (language == EShLangFragment) 5948 profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block"); 5949 break; 5950 case EvqVaryingOut: 5951 profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block"); 5952 requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask), "output block"); 5953 // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins 5954 if (language == EShLangVertex && ! parsingBuiltins) 5955 profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block"); 5956 break; 5957 default: 5958 error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), ""); 5959 break; 5960 } 5961 } 5962 5963 // Do all block-declaration checking regarding its qualifiers. 5964 void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/) 5965 { 5966 // The 4.5 specification says: 5967 // 5968 // interface-block : 5969 // layout-qualifieropt interface-qualifier block-name { member-list } instance-nameopt ; 5970 // 5971 // interface-qualifier : 5972 // in 5973 // out 5974 // patch in 5975 // patch out 5976 // uniform 5977 // buffer 5978 // 5979 // Note however memory qualifiers aren't included, yet the specification also says 5980 // 5981 // "...memory qualifiers may also be used in the declaration of shader storage blocks..." 5982 5983 if (qualifier.isInterpolation()) 5984 error(loc, "cannot use interpolation qualifiers on an interface block", "flat/smooth/noperspective", ""); 5985 if (qualifier.centroid) 5986 error(loc, "cannot use centroid qualifier on an interface block", "centroid", ""); 5987 if (qualifier.sample) 5988 error(loc, "cannot use sample qualifier on an interface block", "sample", ""); 5989 if (qualifier.invariant) 5990 error(loc, "cannot use invariant qualifier on an interface block", "invariant", ""); 5991 if (qualifier.layoutPushConstant) 5992 intermediate.addPushConstantCount(); 5993 } 5994 5995 // 5996 // "For a block, this process applies to the entire block, or until the first member 5997 // is reached that has a location layout qualifier. When a block member is declared with a location 5998 // qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level 5999 // declaration. Subsequent members are again assigned consecutive locations, based on the newest location, 6000 // until the next member declared with a location qualifier. The values used for locations do not have to be 6001 // declared in increasing order." 6002 void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation) 6003 { 6004 // "If a block has no block-level location layout qualifier, it is required that either all or none of its members 6005 // have a location layout qualifier, or a compile-time error results." 6006 if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation) 6007 error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", ""); 6008 else { 6009 if (memberWithLocation) { 6010 // remove any block-level location and make it per *every* member 6011 int nextLocation = 0; // by the rule above, initial value is not relevant 6012 if (qualifier.hasAnyLocation()) { 6013 nextLocation = qualifier.layoutLocation; 6014 qualifier.layoutLocation = TQualifier::layoutLocationEnd; 6015 if (qualifier.hasComponent()) { 6016 // "It is a compile-time error to apply the *component* qualifier to a ... block" 6017 error(loc, "cannot apply to a block", "component", ""); 6018 } 6019 if (qualifier.hasIndex()) { 6020 error(loc, "cannot apply to a block", "index", ""); 6021 } 6022 } 6023 for (unsigned int member = 0; member < typeList.size(); ++member) { 6024 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 6025 const TSourceLoc& memberLoc = typeList[member].loc; 6026 if (! memberQualifier.hasLocation()) { 6027 if (nextLocation >= (int)TQualifier::layoutLocationEnd) 6028 error(memberLoc, "location is too large", "location", ""); 6029 memberQualifier.layoutLocation = nextLocation; 6030 memberQualifier.layoutComponent = TQualifier::layoutComponentEnd; 6031 } 6032 nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(*typeList[member].type); 6033 } 6034 } 6035 } 6036 } 6037 6038 void TParseContext::fixBlockXfbOffsets(TQualifier& qualifier, TTypeList& typeList) 6039 { 6040 // "If a block is qualified with xfb_offset, all its 6041 // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any 6042 // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer 6043 // offsets." 6044 6045 if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset()) 6046 return; 6047 6048 int nextOffset = qualifier.layoutXfbOffset; 6049 for (unsigned int member = 0; member < typeList.size(); ++member) { 6050 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 6051 bool containsDouble = false; 6052 int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, containsDouble); 6053 // see if we need to auto-assign an offset to this member 6054 if (! memberQualifier.hasXfbOffset()) { 6055 // "if applied to an aggregate containing a double, the offset must also be a multiple of 8" 6056 if (containsDouble) 6057 RoundToPow2(nextOffset, 8); 6058 memberQualifier.layoutXfbOffset = nextOffset; 6059 } else 6060 nextOffset = memberQualifier.layoutXfbOffset; 6061 nextOffset += memberSize; 6062 } 6063 6064 // The above gave all block members an offset, so we can take it off the block now, 6065 // which will avoid double counting the offset usage. 6066 qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd; 6067 } 6068 6069 // Calculate and save the offset of each block member, using the recursively 6070 // defined block offset rules and the user-provided offset and align. 6071 // 6072 // Also, compute and save the total size of the block. For the block's size, arrayness 6073 // is not taken into account, as each element is backed by a separate buffer. 6074 // 6075 void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList) 6076 { 6077 if (! qualifier.isUniformOrBuffer()) 6078 return; 6079 if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430) 6080 return; 6081 6082 int offset = 0; 6083 int memberSize; 6084 for (unsigned int member = 0; member < typeList.size(); ++member) { 6085 TQualifier& memberQualifier = typeList[member].type->getQualifier(); 6086 const TSourceLoc& memberLoc = typeList[member].loc; 6087 6088 // "When align is applied to an array, it effects only the start of the array, not the array's internal stride." 6089 6090 // modify just the children's view of matrix layout, if there is one for this member 6091 TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix; 6092 int dummyStride; 6093 int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking == ElpStd140, 6094 subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor); 6095 if (memberQualifier.hasOffset()) { 6096 // "The specified offset must be a multiple 6097 // of the base alignment of the type of the block member it qualifies, or a compile-time error results." 6098 if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) 6099 error(memberLoc, "must be a multiple of the member's alignment", "offset", ""); 6100 6101 // GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous 6102 // member in the block or that lies within the previous member of the block" 6103 if (spvVersion.spv == 0) { 6104 if (memberQualifier.layoutOffset < offset) 6105 error(memberLoc, "cannot lie in previous members", "offset", ""); 6106 6107 // "The offset qualifier forces the qualified member to start at or after the specified 6108 // integral-constant expression, which will be its byte offset from the beginning of the buffer. 6109 // "The actual offset of a member is computed as 6110 // follows: If offset was declared, start with that offset, otherwise start with the next available offset." 6111 offset = std::max(offset, memberQualifier.layoutOffset); 6112 } else { 6113 // TODO: Vulkan: "It is a compile-time error to have any offset, explicit or assigned, 6114 // that lies within another member of the block." 6115 6116 offset = memberQualifier.layoutOffset; 6117 } 6118 } 6119 6120 // "The actual alignment of a member will be the greater of the specified align alignment and the standard 6121 // (e.g., std140) base alignment for the member's type." 6122 if (memberQualifier.hasAlign()) 6123 memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign); 6124 6125 // "If the resulting offset is not a multiple of the actual alignment, 6126 // increase it to the first offset that is a multiple of 6127 // the actual alignment." 6128 RoundToPow2(offset, memberAlignment); 6129 typeList[member].type->getQualifier().layoutOffset = offset; 6130 offset += memberSize; 6131 } 6132 } 6133 6134 // For an identifier that is already declared, add more qualification to it. 6135 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier) 6136 { 6137 TSymbol* symbol = symbolTable.find(identifier); 6138 if (! symbol) { 6139 error(loc, "identifier not previously declared", identifier.c_str(), ""); 6140 return; 6141 } 6142 if (symbol->getAsFunction()) { 6143 error(loc, "cannot re-qualify a function name", identifier.c_str(), ""); 6144 return; 6145 } 6146 6147 if (qualifier.isAuxiliary() || 6148 qualifier.isMemory() || 6149 qualifier.isInterpolation() || 6150 qualifier.hasLayout() || 6151 qualifier.storage != EvqTemporary || 6152 qualifier.precision != EpqNone) { 6153 error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), ""); 6154 return; 6155 } 6156 6157 // For read-only built-ins, add a new symbol for holding the modified qualifier. 6158 // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block) 6159 if (symbol->isReadOnly()) 6160 symbol = symbolTable.copyUp(symbol); 6161 6162 if (qualifier.invariant) { 6163 if (intermediate.inIoAccessed(identifier)) 6164 error(loc, "cannot change qualification after use", "invariant", ""); 6165 symbol->getWritableType().getQualifier().invariant = true; 6166 invariantCheck(loc, symbol->getType().getQualifier()); 6167 } else if (qualifier.noContraction) { 6168 if (intermediate.inIoAccessed(identifier)) 6169 error(loc, "cannot change qualification after use", "precise", ""); 6170 symbol->getWritableType().getQualifier().noContraction = true; 6171 } else if (qualifier.specConstant) { 6172 symbol->getWritableType().getQualifier().makeSpecConstant(); 6173 if (qualifier.hasSpecConstantId()) 6174 symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId; 6175 } else 6176 warn(loc, "unknown requalification", "", ""); 6177 } 6178 6179 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers) 6180 { 6181 for (unsigned int i = 0; i < identifiers.size(); ++i) 6182 addQualifierToExisting(loc, qualifier, *identifiers[i]); 6183 } 6184 6185 // Make sure 'invariant' isn't being applied to a non-allowed object. 6186 void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qualifier) 6187 { 6188 if (! qualifier.invariant) 6189 return; 6190 6191 bool pipeOut = qualifier.isPipeOutput(); 6192 bool pipeIn = qualifier.isPipeInput(); 6193 if (version >= 300 || (profile != EEsProfile && version >= 420)) { 6194 if (! pipeOut) 6195 error(loc, "can only apply to an output", "invariant", ""); 6196 } else { 6197 if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn)) 6198 error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", ""); 6199 } 6200 } 6201 6202 // 6203 // Updating default qualifier for the case of a declaration with just a qualifier, 6204 // no type, block, or identifier. 6205 // 6206 void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType) 6207 { 6208 if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) { 6209 assert(language == EShLangTessControl || language == EShLangGeometry); 6210 const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; 6211 6212 if (publicType.qualifier.storage != EvqVaryingOut) 6213 error(loc, "can only apply to 'out'", id, ""); 6214 if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) 6215 error(loc, "cannot change previously set layout value", id, ""); 6216 6217 if (language == EShLangTessControl) 6218 checkIoArraysConsistency(loc); 6219 } 6220 if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) { 6221 if (publicType.qualifier.storage != EvqVaryingIn) 6222 error(loc, "can only apply to 'in'", "invocations", ""); 6223 if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) 6224 error(loc, "cannot change previously set layout value", "invocations", ""); 6225 } 6226 if (publicType.shaderQualifiers.geometry != ElgNone) { 6227 if (publicType.qualifier.storage == EvqVaryingIn) { 6228 switch (publicType.shaderQualifiers.geometry) { 6229 case ElgPoints: 6230 case ElgLines: 6231 case ElgLinesAdjacency: 6232 case ElgTriangles: 6233 case ElgTrianglesAdjacency: 6234 case ElgQuads: 6235 case ElgIsolines: 6236 if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) { 6237 if (language == EShLangGeometry) 6238 checkIoArraysConsistency(loc); 6239 } else 6240 error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 6241 break; 6242 default: 6243 error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 6244 } 6245 } else if (publicType.qualifier.storage == EvqVaryingOut) { 6246 switch (publicType.shaderQualifiers.geometry) { 6247 case ElgPoints: 6248 case ElgLineStrip: 6249 case ElgTriangleStrip: 6250 if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry)) 6251 error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 6252 break; 6253 default: 6254 error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); 6255 } 6256 } else 6257 error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage)); 6258 } 6259 if (publicType.shaderQualifiers.spacing != EvsNone) { 6260 if (publicType.qualifier.storage == EvqVaryingIn) { 6261 if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing)) 6262 error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); 6263 } else 6264 error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); 6265 } 6266 if (publicType.shaderQualifiers.order != EvoNone) { 6267 if (publicType.qualifier.storage == EvqVaryingIn) { 6268 if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order)) 6269 error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); 6270 } else 6271 error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); 6272 } 6273 if (publicType.shaderQualifiers.pointMode) { 6274 if (publicType.qualifier.storage == EvqVaryingIn) 6275 intermediate.setPointMode(); 6276 else 6277 error(loc, "can only apply to 'in'", "point_mode", ""); 6278 } 6279 for (int i = 0; i < 3; ++i) { 6280 if (publicType.shaderQualifiers.localSize[i] > 1) { 6281 if (publicType.qualifier.storage == EvqVaryingIn) { 6282 if (! intermediate.setLocalSize(i, publicType.shaderQualifiers.localSize[i])) 6283 error(loc, "cannot change previously set size", "local_size", ""); 6284 else { 6285 int max = 0; 6286 switch (i) { 6287 case 0: max = resources.maxComputeWorkGroupSizeX; break; 6288 case 1: max = resources.maxComputeWorkGroupSizeY; break; 6289 case 2: max = resources.maxComputeWorkGroupSizeZ; break; 6290 default: break; 6291 } 6292 if (intermediate.getLocalSize(i) > (unsigned int)max) 6293 error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", ""); 6294 6295 // Fix the existing constant gl_WorkGroupSize with this new information. 6296 TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); 6297 if (workGroupSize != nullptr) 6298 workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i)); 6299 } 6300 } else 6301 error(loc, "can only apply to 'in'", "local_size", ""); 6302 } 6303 if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) { 6304 if (publicType.qualifier.storage == EvqVaryingIn) { 6305 if (! intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i])) 6306 error(loc, "cannot change previously set size", "local_size", ""); 6307 } else 6308 error(loc, "can only apply to 'in'", "local_size id", ""); 6309 // Set the workgroup built-in variable as a specialization constant 6310 TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); 6311 if (workGroupSize != nullptr) 6312 workGroupSize->getWritableType().getQualifier().specConstant = true; 6313 } 6314 } 6315 if (publicType.shaderQualifiers.earlyFragmentTests) { 6316 if (publicType.qualifier.storage == EvqVaryingIn) 6317 intermediate.setEarlyFragmentTests(); 6318 else 6319 error(loc, "can only apply to 'in'", "early_fragment_tests", ""); 6320 } 6321 if (publicType.shaderQualifiers.postDepthCoverage) { 6322 if (publicType.qualifier.storage == EvqVaryingIn) 6323 intermediate.setPostDepthCoverage(); 6324 else 6325 error(loc, "can only apply to 'in'", "post_coverage_coverage", ""); 6326 } 6327 if (publicType.shaderQualifiers.blendEquation) { 6328 if (publicType.qualifier.storage != EvqVaryingOut) 6329 error(loc, "can only apply to 'out'", "blend equation", ""); 6330 } 6331 6332 const TQualifier& qualifier = publicType.qualifier; 6333 6334 if (qualifier.isAuxiliary() || 6335 qualifier.isMemory() || 6336 qualifier.isInterpolation() || 6337 qualifier.precision != EpqNone) 6338 error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", ""); 6339 // "The offset qualifier can only be used on block members of blocks..." 6340 // "The align qualifier can only be used on blocks or block members..." 6341 if (qualifier.hasOffset() || 6342 qualifier.hasAlign()) 6343 error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", ""); 6344 6345 layoutQualifierCheck(loc, qualifier); 6346 6347 switch (qualifier.storage) { 6348 case EvqUniform: 6349 if (qualifier.hasMatrix()) 6350 globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; 6351 if (qualifier.hasPacking()) 6352 globalUniformDefaults.layoutPacking = qualifier.layoutPacking; 6353 break; 6354 case EvqBuffer: 6355 if (qualifier.hasMatrix()) 6356 globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; 6357 if (qualifier.hasPacking()) 6358 globalBufferDefaults.layoutPacking = qualifier.layoutPacking; 6359 break; 6360 case EvqVaryingIn: 6361 break; 6362 case EvqVaryingOut: 6363 if (qualifier.hasStream()) 6364 globalOutputDefaults.layoutStream = qualifier.layoutStream; 6365 if (qualifier.hasXfbBuffer()) 6366 globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer; 6367 if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) { 6368 if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride)) 6369 error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); 6370 } 6371 break; 6372 default: 6373 error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); 6374 return; 6375 } 6376 6377 if (qualifier.hasBinding()) 6378 error(loc, "cannot declare a default, include a type or full declaration", "binding", ""); 6379 if (qualifier.hasAnyLocation()) 6380 error(loc, "cannot declare a default, use a full declaration", "location/component/index", ""); 6381 if (qualifier.hasXfbOffset()) 6382 error(loc, "cannot declare a default, use a full declaration", "xfb_offset", ""); 6383 if (qualifier.layoutPushConstant) 6384 error(loc, "cannot declare a default, can only be used on a block", "push_constant", ""); 6385 if (qualifier.hasSpecConstantId()) 6386 error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", ""); 6387 } 6388 6389 // 6390 // Take the sequence of statements that has been built up since the last case/default, 6391 // put it on the list of top-level nodes for the current (inner-most) switch statement, 6392 // and follow that by the case/default we are on now. (See switch topology comment on 6393 // TIntermSwitch.) 6394 // 6395 void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode) 6396 { 6397 TIntermSequence* switchSequence = switchSequenceStack.back(); 6398 6399 if (statements) { 6400 if (switchSequence->size() == 0) 6401 error(statements->getLoc(), "cannot have statements before first case/default label", "switch", ""); 6402 statements->setOperator(EOpSequence); 6403 switchSequence->push_back(statements); 6404 } 6405 if (branchNode) { 6406 // check all previous cases for the same label (or both are 'default') 6407 for (unsigned int s = 0; s < switchSequence->size(); ++s) { 6408 TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode(); 6409 if (prevBranch) { 6410 TIntermTyped* prevExpression = prevBranch->getExpression(); 6411 TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression(); 6412 if (prevExpression == nullptr && newExpression == nullptr) 6413 error(branchNode->getLoc(), "duplicate label", "default", ""); 6414 else if (prevExpression != nullptr && 6415 newExpression != nullptr && 6416 prevExpression->getAsConstantUnion() && 6417 newExpression->getAsConstantUnion() && 6418 prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() == 6419 newExpression->getAsConstantUnion()->getConstArray()[0].getIConst()) 6420 error(branchNode->getLoc(), "duplicated value", "case", ""); 6421 } 6422 } 6423 switchSequence->push_back(branchNode); 6424 } 6425 } 6426 6427 // 6428 // Turn the top-level node sequence built up of wrapupSwitchSubsequence9) 6429 // into a switch node. 6430 // 6431 TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, TIntermAggregate* lastStatements) 6432 { 6433 profileRequires(loc, EEsProfile, 300, nullptr, "switch statements"); 6434 profileRequires(loc, ENoProfile, 130, nullptr, "switch statements"); 6435 6436 wrapupSwitchSubsequence(lastStatements, nullptr); 6437 6438 if (expression == nullptr || 6439 (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) || 6440 expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) 6441 error(loc, "condition must be a scalar integer expression", "switch", ""); 6442 6443 // If there is nothing to do, drop the switch but still execute the expression 6444 TIntermSequence* switchSequence = switchSequenceStack.back(); 6445 if (switchSequence->size() == 0) 6446 return expression; 6447 6448 if (lastStatements == nullptr) { 6449 // This was originally an ERRROR, because early versions of the specification said 6450 // "it is an error to have no statement between a label and the end of the switch statement." 6451 // The specifications were updated to remove this (being ill-defined what a "statement" was), 6452 // so, this became a warning. However, 3.0 tests still check for the error. 6453 if (profile == EEsProfile && version <= 300 && ! relaxedErrors()) 6454 error(loc, "last case/default label not followed by statements", "switch", ""); 6455 else 6456 warn(loc, "last case/default label not followed by statements", "switch", ""); 6457 6458 // emulate a break for error recovery 6459 lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc)); 6460 lastStatements->setOperator(EOpSequence); 6461 switchSequence->push_back(lastStatements); 6462 } 6463 6464 TIntermAggregate* body = new TIntermAggregate(EOpSequence); 6465 body->getSequence() = *switchSequenceStack.back(); 6466 body->setLoc(loc); 6467 6468 TIntermSwitch* switchNode = new TIntermSwitch(expression, body); 6469 switchNode->setLoc(loc); 6470 6471 return switchNode; 6472 } 6473 6474 } // end namespace glslang 6475