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