1 // 2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 // Copyright (C) 2016 Google, Inc. 4 // 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions 9 // are met: 10 // 11 // Redistributions of source code must retain the above copyright 12 // notice, this list of conditions and the following disclaimer. 13 // 14 // Redistributions in binary form must reproduce the above 15 // copyright notice, this list of conditions and the following 16 // disclaimer in the documentation and/or other materials provided 17 // with the distribution. 18 // 19 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 20 // contributors may be used to endorse or promote products derived 21 // from this software without specific prior written permission. 22 // 23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 // POSSIBILITY OF SUCH DAMAGE. 35 // 36 37 // Implement the TParseContextBase class. 38 39 #include <cstdarg> 40 41 #include "ParseHelper.h" 42 43 extern int yyparse(glslang::TParseContext*); 44 45 namespace glslang { 46 47 // 48 // Used to output syntax, parsing, and semantic errors. 49 // 50 51 void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason, 52 const char* szToken, 53 const char* szExtraInfoFormat, 54 TPrefixType prefix, va_list args) 55 { 56 const int maxSize = MaxTokenLength + 200; 57 char szExtraInfo[maxSize]; 58 59 safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args); 60 61 infoSink.info.prefix(prefix); 62 infoSink.info.location(loc); 63 infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n"; 64 65 if (prefix == EPrefixError) { 66 ++numErrors; 67 } 68 } 69 70 void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken, 71 const char* szExtraInfoFormat, ...) 72 { 73 if (messages & EShMsgOnlyPreprocessor) 74 return; 75 va_list args; 76 va_start(args, szExtraInfoFormat); 77 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); 78 va_end(args); 79 80 if ((messages & EShMsgCascadingErrors) == 0) 81 currentScanner->setEndOfInput(); 82 } 83 84 void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken, 85 const char* szExtraInfoFormat, ...) 86 { 87 if (suppressWarnings()) 88 return; 89 va_list args; 90 va_start(args, szExtraInfoFormat); 91 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args); 92 va_end(args); 93 } 94 95 void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken, 96 const char* szExtraInfoFormat, ...) 97 { 98 va_list args; 99 va_start(args, szExtraInfoFormat); 100 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); 101 va_end(args); 102 103 if ((messages & EShMsgCascadingErrors) == 0) 104 currentScanner->setEndOfInput(); 105 } 106 107 void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken, 108 const char* szExtraInfoFormat, ...) 109 { 110 va_list args; 111 va_start(args, szExtraInfoFormat); 112 outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args); 113 va_end(args); 114 } 115 116 // 117 // Both test and if necessary, spit out an error, to see if the node is really 118 // an l-value that can be operated on this way. 119 // 120 // Returns true if there was an error. 121 // 122 bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) 123 { 124 TIntermBinary* binaryNode = node->getAsBinaryNode(); 125 126 if (binaryNode) { 127 switch(binaryNode->getOp()) { 128 case EOpIndexDirect: 129 case EOpIndexIndirect: // fall through 130 case EOpIndexDirectStruct: // fall through 131 case EOpVectorSwizzle: 132 case EOpMatrixSwizzle: 133 return lValueErrorCheck(loc, op, binaryNode->getLeft()); 134 default: 135 break; 136 } 137 error(loc, " l-value required", op, "", ""); 138 139 return true; 140 } 141 142 const char* symbol = nullptr; 143 TIntermSymbol* symNode = node->getAsSymbolNode(); 144 if (symNode != nullptr) 145 symbol = symNode->getName().c_str(); 146 147 const char* message = nullptr; 148 switch (node->getQualifier().storage) { 149 case EvqConst: message = "can't modify a const"; break; 150 case EvqConstReadOnly: message = "can't modify a const"; break; 151 case EvqUniform: message = "can't modify a uniform"; break; 152 case EvqBuffer: 153 if (node->getQualifier().readonly) 154 message = "can't modify a readonly buffer"; 155 break; 156 157 default: 158 // 159 // Type that can't be written to? 160 // 161 switch (node->getBasicType()) { 162 case EbtSampler: 163 message = "can't modify a sampler"; 164 break; 165 case EbtAtomicUint: 166 message = "can't modify an atomic_uint"; 167 break; 168 case EbtVoid: 169 message = "can't modify void"; 170 break; 171 default: 172 break; 173 } 174 } 175 176 if (message == nullptr && binaryNode == nullptr && symNode == nullptr) { 177 error(loc, " l-value required", op, "", ""); 178 179 return true; 180 } 181 182 // 183 // Everything else is okay, no error. 184 // 185 if (message == nullptr) 186 return false; 187 188 // 189 // If we get here, we have an error and a message. 190 // 191 if (symNode) 192 error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); 193 else 194 error(loc, " l-value required", op, "(%s)", message); 195 196 return true; 197 } 198 199 // Test for and give an error if the node can't be read from. 200 void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) 201 { 202 if (! node) 203 return; 204 205 TIntermBinary* binaryNode = node->getAsBinaryNode(); 206 if (binaryNode) { 207 switch(binaryNode->getOp()) { 208 case EOpIndexDirect: 209 case EOpIndexIndirect: 210 case EOpIndexDirectStruct: 211 case EOpVectorSwizzle: 212 case EOpMatrixSwizzle: 213 rValueErrorCheck(loc, op, binaryNode->getLeft()); 214 default: 215 break; 216 } 217 218 return; 219 } 220 221 TIntermSymbol* symNode = node->getAsSymbolNode(); 222 if (symNode && symNode->getQualifier().writeonly) 223 error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); 224 } 225 226 // Add 'symbol' to the list of deferred linkage symbols, which 227 // are later processed in finish(), at which point the symbol 228 // must still be valid. 229 // It is okay if the symbol's type will be subsequently edited; 230 // the modifications will be tracked. 231 void TParseContextBase::trackLinkage(TSymbol& symbol) 232 { 233 if (!parsingBuiltins) 234 linkageSymbols.push_back(&symbol); 235 } 236 237 // Make a shared symbol have a non-shared version that can be edited by the current 238 // compile, such that editing its type will not change the shared version and will 239 // effect all nodes already sharing it (non-shallow type), 240 // or adopting its full type after being edited (shallow type). 241 void TParseContextBase::makeEditable(TSymbol*& symbol) 242 { 243 // copyUp() does a deep copy of the type. 244 symbol = symbolTable.copyUp(symbol); 245 246 // Save it (deferred, so it can be edited first) in the AST for linker use. 247 if (symbol) 248 trackLinkage(*symbol); 249 } 250 251 // Return a writable version of the variable 'name'. 252 // 253 // Return nullptr if 'name' is not found. This should mean 254 // something is seriously wrong (e.g., compiler asking self for 255 // built-in that doesn't exist). 256 TVariable* TParseContextBase::getEditableVariable(const char* name) 257 { 258 bool builtIn; 259 TSymbol* symbol = symbolTable.find(name, &builtIn); 260 261 assert(symbol != nullptr); 262 if (symbol == nullptr) 263 return nullptr; 264 265 if (builtIn) 266 makeEditable(symbol); 267 268 return symbol->getAsVariable(); 269 } 270 271 // Select the best matching function for 'call' from 'candidateList'. 272 // 273 // Assumptions 274 // 275 // There is no exact match, so a selection algorithm needs to run. That is, the 276 // language-specific handler should check for exact match first, to 277 // decide what to do, before calling this selector. 278 // 279 // Input 280 // 281 // * list of candidate signatures to select from 282 // * the call 283 // * a predicate function convertible(from, to) that says whether or not type 284 // 'from' can implicitly convert to type 'to' (it includes the case of what 285 // the calling language would consider a matching type with no conversion 286 // needed) 287 // * a predicate function better(from1, from2, to1, to2) that says whether or 288 // not a conversion from <-> to2 is considered better than a conversion 289 // from <-> to1 (both in and out directions need testing, as declared by the 290 // formal parameter) 291 // 292 // Output 293 // 294 // * best matching candidate (or none, if no viable candidates found) 295 // * whether there was a tie for the best match (ambiguous overload selection, 296 // caller's choice for how to report) 297 // 298 const TFunction* TParseContextBase::selectFunction( 299 const TVector<const TFunction*> candidateList, 300 const TFunction& call, 301 std::function<bool(const TType& from, const TType& to, TOperator op, int arg)> convertible, 302 std::function<bool(const TType& from, const TType& to1, const TType& to2)> better, 303 /* output */ bool& tie) 304 { 305 // 306 // Operation 307 // 308 // 1. Prune the input list of candidates down to a list of viable candidates, 309 // where each viable candidate has 310 // 311 // * at least as many parameters as there are calling arguments, with any 312 // remaining parameters being optional or having default values 313 // * each parameter is true under convertible(A, B), where A is the calling 314 // type for in and B is the formal type, and in addition, for out B is the 315 // calling type and A is the formal type 316 // 317 // 2. If there are no viable candidates, return with no match. 318 // 319 // 3. If there is only one viable candidate, it is the best match. 320 // 321 // 4. If there are multiple viable candidates, select the first viable candidate 322 // as the incumbent. Compare the incumbent to the next viable candidate, and if 323 // that candidate is better (bullets below), make it the incumbent. Repeat, with 324 // a linear walk through the viable candidate list. The final incumbent will be 325 // returned as the best match. A viable candidate is better than the incumbent if 326 // 327 // * it has a function argument with a better(...) conversion than the incumbent, 328 // for all directions needed by in and out 329 // * the incumbent has no argument with a better(...) conversion then the 330 // candidate, for either in or out (as needed) 331 // 332 // 5. Check for ambiguity by comparing the best match against all other viable 333 // candidates. If any other viable candidate has a function argument with a 334 // better(...) conversion than the best candidate (for either in or out 335 // directions), return that there was a tie for best. 336 // 337 338 tie = false; 339 340 // 1. prune to viable... 341 TVector<const TFunction*> viableCandidates; 342 for (auto it = candidateList.begin(); it != candidateList.end(); ++it) { 343 const TFunction& candidate = *(*it); 344 345 // to even be a potential match, number of arguments must be >= the number of 346 // fixed (non-default) parameters, and <= the total (including parameter with defaults). 347 if (call.getParamCount() < candidate.getFixedParamCount() || 348 call.getParamCount() > candidate.getParamCount()) 349 continue; 350 351 // see if arguments are convertible 352 bool viable = true; 353 354 // The call can have fewer parameters than the candidate, if some have defaults. 355 const int paramCount = std::min(call.getParamCount(), candidate.getParamCount()); 356 for (int param = 0; param < paramCount; ++param) { 357 if (candidate[param].type->getQualifier().isParamInput()) { 358 if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) { 359 viable = false; 360 break; 361 } 362 } 363 if (candidate[param].type->getQualifier().isParamOutput()) { 364 if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) { 365 viable = false; 366 break; 367 } 368 } 369 } 370 371 if (viable) 372 viableCandidates.push_back(&candidate); 373 } 374 375 // 2. none viable... 376 if (viableCandidates.size() == 0) 377 return nullptr; 378 379 // 3. only one viable... 380 if (viableCandidates.size() == 1) 381 return viableCandidates.front(); 382 383 // 4. find best... 384 const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool { 385 // is call -> can2 better than call -> can1 for any parameter 386 bool hasBetterParam = false; 387 for (int param = 0; param < call.getParamCount(); ++param) { 388 if (better(*call[param].type, *can1[param].type, *can2[param].type)) { 389 hasBetterParam = true; 390 break; 391 } 392 } 393 return hasBetterParam; 394 }; 395 396 const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool { 397 // is call -> can2 equivalent to call -> can1 for all the call parameters? 398 for (int param = 0; param < call.getParamCount(); ++param) { 399 if (better(*call[param].type, *can1[param].type, *can2[param].type) || 400 better(*call[param].type, *can2[param].type, *can1[param].type)) 401 return false; 402 } 403 return true; 404 }; 405 406 const TFunction* incumbent = viableCandidates.front(); 407 for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) { 408 const TFunction& candidate = *(*it); 409 if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent)) 410 incumbent = &candidate; 411 } 412 413 // 5. ambiguity... 414 for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) { 415 if (incumbent == *it) 416 continue; 417 const TFunction& candidate = *(*it); 418 419 // In the case of default parameters, it may have an identical initial set, which is 420 // also ambiguous 421 if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate)) 422 tie = true; 423 } 424 425 return incumbent; 426 } 427 428 // 429 // Look at a '.' field selector string and change it into numerical selectors 430 // for a vector or scalar. 431 // 432 // Always return some form of swizzle, so the result is always usable. 433 // 434 void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize, 435 TSwizzleSelectors<TVectorSelector>& selector) 436 { 437 // Too long? 438 if (compString.size() > MaxSwizzleSelectors) 439 error(loc, "vector swizzle too long", compString.c_str(), ""); 440 441 // Use this to test that all swizzle characters are from the same swizzle-namespace-set 442 enum { 443 exyzw, 444 ergba, 445 estpq, 446 } fieldSet[MaxSwizzleSelectors]; 447 448 // Decode the swizzle string. 449 int size = std::min(MaxSwizzleSelectors, (int)compString.size()); 450 for (int i = 0; i < size; ++i) { 451 switch (compString[i]) { 452 case 'x': 453 selector.push_back(0); 454 fieldSet[i] = exyzw; 455 break; 456 case 'r': 457 selector.push_back(0); 458 fieldSet[i] = ergba; 459 break; 460 case 's': 461 selector.push_back(0); 462 fieldSet[i] = estpq; 463 break; 464 465 case 'y': 466 selector.push_back(1); 467 fieldSet[i] = exyzw; 468 break; 469 case 'g': 470 selector.push_back(1); 471 fieldSet[i] = ergba; 472 break; 473 case 't': 474 selector.push_back(1); 475 fieldSet[i] = estpq; 476 break; 477 478 case 'z': 479 selector.push_back(2); 480 fieldSet[i] = exyzw; 481 break; 482 case 'b': 483 selector.push_back(2); 484 fieldSet[i] = ergba; 485 break; 486 case 'p': 487 selector.push_back(2); 488 fieldSet[i] = estpq; 489 break; 490 491 case 'w': 492 selector.push_back(3); 493 fieldSet[i] = exyzw; 494 break; 495 case 'a': 496 selector.push_back(3); 497 fieldSet[i] = ergba; 498 break; 499 case 'q': 500 selector.push_back(3); 501 fieldSet[i] = estpq; 502 break; 503 504 default: 505 error(loc, "unknown swizzle selection", compString.c_str(), ""); 506 break; 507 } 508 } 509 510 // Additional error checking. 511 for (int i = 0; i < selector.size(); ++i) { 512 if (selector[i] >= vecSize) { 513 error(loc, "vector swizzle selection out of range", compString.c_str(), ""); 514 selector.resize(i); 515 break; 516 } 517 518 if (i > 0 && fieldSet[i] != fieldSet[i-1]) { 519 error(loc, "vector swizzle selectors not from the same set", compString.c_str(), ""); 520 selector.resize(i); 521 break; 522 } 523 } 524 525 // Ensure it is valid. 526 if (selector.size() == 0) 527 selector.push_back(0); 528 } 529 530 // 531 // Make the passed-in variable information become a member of the 532 // global uniform block. If this doesn't exist yet, make it. 533 // 534 void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) 535 { 536 // Make the global block, if not yet made. 537 if (globalUniformBlock == nullptr) { 538 TQualifier blockQualifier; 539 blockQualifier.clear(); 540 blockQualifier.storage = EvqUniform; 541 TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier); 542 setUniformBlockDefaults(blockType); 543 globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true); 544 firstNewMember = 0; 545 } 546 547 // Add the requested member as a member to the global block. 548 TType* type = new TType; 549 type->shallowCopy(memberType); 550 type->setFieldName(memberName); 551 if (typeList) 552 type->setStruct(typeList); 553 TTypeLoc typeLoc = {type, loc}; 554 globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc); 555 556 // Insert into the symbol table. 557 if (firstNewMember == 0) { 558 // This is the first request; we need a normal symbol table insert 559 if (symbolTable.insert(*globalUniformBlock)) 560 trackLinkage(*globalUniformBlock); 561 else 562 error(loc, "failed to insert the global constant buffer", "uniform", ""); 563 } else { 564 // This is a follow-on request; we need to amend the first insert 565 symbolTable.amend(*globalUniformBlock, firstNewMember); 566 } 567 568 ++firstNewMember; 569 } 570 571 void TParseContextBase::finish() 572 { 573 if (parsingBuiltins) 574 return; 575 576 // Transfer the linkage symbols to AST nodes 577 TIntermAggregate* linkage = new TIntermAggregate; 578 for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i) 579 intermediate.addSymbolLinkageNode(linkage, **i); 580 intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable); 581 } 582 583 } // end namespace glslang 584