1 // 2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include "compiler/translator/ParseContext.h" 8 9 #include <stdarg.h> 10 #include <stdio.h> 11 12 #include "compiler/translator/glslang.h" 13 #include "compiler/preprocessor/SourceLocation.h" 14 15 /////////////////////////////////////////////////////////////////////// 16 // 17 // Sub- vector and matrix fields 18 // 19 //////////////////////////////////////////////////////////////////////// 20 21 // 22 // Look at a '.' field selector string and change it into offsets 23 // for a vector. 24 // 25 bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line) 26 { 27 fields.num = (int) compString.size(); 28 if (fields.num > 4) { 29 error(line, "illegal vector field selection", compString.c_str()); 30 return false; 31 } 32 33 enum { 34 exyzw, 35 ergba, 36 estpq 37 } fieldSet[4]; 38 39 for (int i = 0; i < fields.num; ++i) { 40 switch (compString[i]) { 41 case 'x': 42 fields.offsets[i] = 0; 43 fieldSet[i] = exyzw; 44 break; 45 case 'r': 46 fields.offsets[i] = 0; 47 fieldSet[i] = ergba; 48 break; 49 case 's': 50 fields.offsets[i] = 0; 51 fieldSet[i] = estpq; 52 break; 53 case 'y': 54 fields.offsets[i] = 1; 55 fieldSet[i] = exyzw; 56 break; 57 case 'g': 58 fields.offsets[i] = 1; 59 fieldSet[i] = ergba; 60 break; 61 case 't': 62 fields.offsets[i] = 1; 63 fieldSet[i] = estpq; 64 break; 65 case 'z': 66 fields.offsets[i] = 2; 67 fieldSet[i] = exyzw; 68 break; 69 case 'b': 70 fields.offsets[i] = 2; 71 fieldSet[i] = ergba; 72 break; 73 case 'p': 74 fields.offsets[i] = 2; 75 fieldSet[i] = estpq; 76 break; 77 78 case 'w': 79 fields.offsets[i] = 3; 80 fieldSet[i] = exyzw; 81 break; 82 case 'a': 83 fields.offsets[i] = 3; 84 fieldSet[i] = ergba; 85 break; 86 case 'q': 87 fields.offsets[i] = 3; 88 fieldSet[i] = estpq; 89 break; 90 default: 91 error(line, "illegal vector field selection", compString.c_str()); 92 return false; 93 } 94 } 95 96 for (int i = 0; i < fields.num; ++i) { 97 if (fields.offsets[i] >= vecSize) { 98 error(line, "vector field selection out of range", compString.c_str()); 99 return false; 100 } 101 102 if (i > 0) { 103 if (fieldSet[i] != fieldSet[i-1]) { 104 error(line, "illegal - vector component fields not from the same set", compString.c_str()); 105 return false; 106 } 107 } 108 } 109 110 return true; 111 } 112 113 114 // 115 // Look at a '.' field selector string and change it into offsets 116 // for a matrix. 117 // 118 bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, const TSourceLoc& line) 119 { 120 fields.wholeRow = false; 121 fields.wholeCol = false; 122 fields.row = -1; 123 fields.col = -1; 124 125 if (compString.size() != 2) { 126 error(line, "illegal length of matrix field selection", compString.c_str()); 127 return false; 128 } 129 130 if (compString[0] == '_') { 131 if (compString[1] < '0' || compString[1] > '3') { 132 error(line, "illegal matrix field selection", compString.c_str()); 133 return false; 134 } 135 fields.wholeCol = true; 136 fields.col = compString[1] - '0'; 137 } else if (compString[1] == '_') { 138 if (compString[0] < '0' || compString[0] > '3') { 139 error(line, "illegal matrix field selection", compString.c_str()); 140 return false; 141 } 142 fields.wholeRow = true; 143 fields.row = compString[0] - '0'; 144 } else { 145 if (compString[0] < '0' || compString[0] > '3' || 146 compString[1] < '0' || compString[1] > '3') { 147 error(line, "illegal matrix field selection", compString.c_str()); 148 return false; 149 } 150 fields.row = compString[0] - '0'; 151 fields.col = compString[1] - '0'; 152 } 153 154 if (fields.row >= matRows || fields.col >= matCols) { 155 error(line, "matrix field selection out of range", compString.c_str()); 156 return false; 157 } 158 159 return true; 160 } 161 162 /////////////////////////////////////////////////////////////////////// 163 // 164 // Errors 165 // 166 //////////////////////////////////////////////////////////////////////// 167 168 // 169 // Track whether errors have occurred. 170 // 171 void TParseContext::recover() 172 { 173 } 174 175 // 176 // Used by flex/bison to output all syntax and parsing errors. 177 // 178 void TParseContext::error(const TSourceLoc& loc, 179 const char* reason, const char* token, 180 const char* extraInfo) 181 { 182 pp::SourceLocation srcLoc; 183 srcLoc.file = loc.first_file; 184 srcLoc.line = loc.first_line; 185 diagnostics.writeInfo(pp::Diagnostics::PP_ERROR, 186 srcLoc, reason, token, extraInfo); 187 188 } 189 190 void TParseContext::warning(const TSourceLoc& loc, 191 const char* reason, const char* token, 192 const char* extraInfo) { 193 pp::SourceLocation srcLoc; 194 srcLoc.file = loc.first_file; 195 srcLoc.line = loc.first_line; 196 diagnostics.writeInfo(pp::Diagnostics::PP_WARNING, 197 srcLoc, reason, token, extraInfo); 198 } 199 200 void TParseContext::trace(const char* str) 201 { 202 diagnostics.writeDebug(str); 203 } 204 205 // 206 // Same error message for all places assignments don't work. 207 // 208 void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right) 209 { 210 std::stringstream extraInfoStream; 211 extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; 212 std::string extraInfo = extraInfoStream.str(); 213 error(line, "", op, extraInfo.c_str()); 214 } 215 216 // 217 // Same error message for all places unary operations don't work. 218 // 219 void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand) 220 { 221 std::stringstream extraInfoStream; 222 extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand 223 << " (or there is no acceptable conversion)"; 224 std::string extraInfo = extraInfoStream.str(); 225 error(line, " wrong operand type", op, extraInfo.c_str()); 226 } 227 228 // 229 // Same error message for all binary operations don't work. 230 // 231 void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right) 232 { 233 std::stringstream extraInfoStream; 234 extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left 235 << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)"; 236 std::string extraInfo = extraInfoStream.str(); 237 error(line, " wrong operand types ", op, extraInfo.c_str()); 238 } 239 240 bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){ 241 if (!checksPrecisionErrors) 242 return false; 243 switch( type ){ 244 case EbtFloat: 245 if( precision == EbpUndefined ){ 246 error( line, "No precision specified for (float)", "" ); 247 return true; 248 } 249 break; 250 case EbtInt: 251 if( precision == EbpUndefined ){ 252 error( line, "No precision specified (int)", "" ); 253 return true; 254 } 255 break; 256 default: 257 return false; 258 } 259 return false; 260 } 261 262 // 263 // Both test and if necessary, spit out an error, to see if the node is really 264 // an l-value that can be operated on this way. 265 // 266 // Returns true if the was an error. 267 // 268 bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node) 269 { 270 TIntermSymbol* symNode = node->getAsSymbolNode(); 271 TIntermBinary* binaryNode = node->getAsBinaryNode(); 272 273 if (binaryNode) { 274 bool errorReturn; 275 276 switch(binaryNode->getOp()) { 277 case EOpIndexDirect: 278 case EOpIndexIndirect: 279 case EOpIndexDirectStruct: 280 case EOpIndexDirectInterfaceBlock: 281 return lValueErrorCheck(line, op, binaryNode->getLeft()); 282 case EOpVectorSwizzle: 283 errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); 284 if (!errorReturn) { 285 int offset[4] = {0,0,0,0}; 286 287 TIntermTyped* rightNode = binaryNode->getRight(); 288 TIntermAggregate *aggrNode = rightNode->getAsAggregate(); 289 290 for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 291 p != aggrNode->getSequence().end(); p++) { 292 int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); 293 offset[value]++; 294 if (offset[value] > 1) { 295 error(line, " l-value of swizzle cannot have duplicate components", op); 296 297 return true; 298 } 299 } 300 } 301 302 return errorReturn; 303 default: 304 break; 305 } 306 error(line, " l-value required", op); 307 308 return true; 309 } 310 311 312 const char* symbol = 0; 313 if (symNode != 0) 314 symbol = symNode->getSymbol().c_str(); 315 316 const char* message = 0; 317 switch (node->getQualifier()) { 318 case EvqConst: message = "can't modify a const"; break; 319 case EvqConstReadOnly: message = "can't modify a const"; break; 320 case EvqAttribute: message = "can't modify an attribute"; break; 321 case EvqFragmentIn: message = "can't modify an input"; break; 322 case EvqVertexIn: message = "can't modify an input"; break; 323 case EvqUniform: message = "can't modify a uniform"; break; 324 case EvqVaryingIn: message = "can't modify a varying"; break; 325 case EvqFragCoord: message = "can't modify gl_FragCoord"; break; 326 case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; 327 case EvqPointCoord: message = "can't modify gl_PointCoord"; break; 328 default: 329 330 // 331 // Type that can't be written to? 332 // 333 if (node->getBasicType() == EbtVoid) { 334 message = "can't modify void"; 335 } 336 if (IsSampler(node->getBasicType())) { 337 message = "can't modify a sampler"; 338 } 339 } 340 341 if (message == 0 && binaryNode == 0 && symNode == 0) { 342 error(line, " l-value required", op); 343 344 return true; 345 } 346 347 348 // 349 // Everything else is okay, no error. 350 // 351 if (message == 0) 352 return false; 353 354 // 355 // If we get here, we have an error and a message. 356 // 357 if (symNode) { 358 std::stringstream extraInfoStream; 359 extraInfoStream << "\"" << symbol << "\" (" << message << ")"; 360 std::string extraInfo = extraInfoStream.str(); 361 error(line, " l-value required", op, extraInfo.c_str()); 362 } 363 else { 364 std::stringstream extraInfoStream; 365 extraInfoStream << "(" << message << ")"; 366 std::string extraInfo = extraInfoStream.str(); 367 error(line, " l-value required", op, extraInfo.c_str()); 368 } 369 370 return true; 371 } 372 373 // 374 // Both test, and if necessary spit out an error, to see if the node is really 375 // a constant. 376 // 377 // Returns true if the was an error. 378 // 379 bool TParseContext::constErrorCheck(TIntermTyped* node) 380 { 381 if (node->getQualifier() == EvqConst) 382 return false; 383 384 error(node->getLine(), "constant expression required", ""); 385 386 return true; 387 } 388 389 // 390 // Both test, and if necessary spit out an error, to see if the node is really 391 // an integer. 392 // 393 // Returns true if the was an error. 394 // 395 bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) 396 { 397 if (node->isScalarInt()) 398 return false; 399 400 error(node->getLine(), "integer expression required", token); 401 402 return true; 403 } 404 405 // 406 // Both test, and if necessary spit out an error, to see if we are currently 407 // globally scoped. 408 // 409 // Returns true if the was an error. 410 // 411 bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token) 412 { 413 if (global) 414 return false; 415 416 error(line, "only allowed at global scope", token); 417 418 return true; 419 } 420 421 // 422 // For now, keep it simple: if it starts "gl_", it's reserved, independent 423 // of scope. Except, if the symbol table is at the built-in push-level, 424 // which is when we are parsing built-ins. 425 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a 426 // webgl shader. 427 // 428 // Returns true if there was an error. 429 // 430 bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier) 431 { 432 static const char* reservedErrMsg = "reserved built-in name"; 433 if (!symbolTable.atBuiltInLevel()) { 434 if (identifier.compare(0, 3, "gl_") == 0) { 435 error(line, reservedErrMsg, "gl_"); 436 return true; 437 } 438 if (IsWebGLBasedSpec(shaderSpec)) { 439 if (identifier.compare(0, 6, "webgl_") == 0) { 440 error(line, reservedErrMsg, "webgl_"); 441 return true; 442 } 443 if (identifier.compare(0, 7, "_webgl_") == 0) { 444 error(line, reservedErrMsg, "_webgl_"); 445 return true; 446 } 447 if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) { 448 error(line, reservedErrMsg, "css_"); 449 return true; 450 } 451 } 452 if (identifier.find("__") != TString::npos) { 453 error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str()); 454 return true; 455 } 456 } 457 458 return false; 459 } 460 461 // 462 // Make sure there is enough data provided to the constructor to build 463 // something of the type of the constructor. Also returns the type of 464 // the constructor. 465 // 466 // Returns true if there was an error in construction. 467 // 468 bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type) 469 { 470 *type = function.getReturnType(); 471 472 bool constructingMatrix = false; 473 switch(op) { 474 case EOpConstructMat2: 475 case EOpConstructMat3: 476 case EOpConstructMat4: 477 constructingMatrix = true; 478 break; 479 default: 480 break; 481 } 482 483 // 484 // Note: It's okay to have too many components available, but not okay to have unused 485 // arguments. 'full' will go to true when enough args have been seen. If we loop 486 // again, there is an extra argument, so 'overfull' will become true. 487 // 488 489 size_t size = 0; 490 bool constType = true; 491 bool full = false; 492 bool overFull = false; 493 bool matrixInMatrix = false; 494 bool arrayArg = false; 495 for (size_t i = 0; i < function.getParamCount(); ++i) { 496 const TParameter& param = function.getParam(i); 497 size += param.type->getObjectSize(); 498 499 if (constructingMatrix && param.type->isMatrix()) 500 matrixInMatrix = true; 501 if (full) 502 overFull = true; 503 if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) 504 full = true; 505 if (param.type->getQualifier() != EvqConst) 506 constType = false; 507 if (param.type->isArray()) 508 arrayArg = true; 509 } 510 511 if (constType) 512 type->setQualifier(EvqConst); 513 514 if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) { 515 error(line, "array constructor needs one argument per array element", "constructor"); 516 return true; 517 } 518 519 if (arrayArg && op != EOpConstructStruct) { 520 error(line, "constructing from a non-dereferenced array", "constructor"); 521 return true; 522 } 523 524 if (matrixInMatrix && !type->isArray()) { 525 if (function.getParamCount() != 1) { 526 error(line, "constructing matrix from matrix can only take one argument", "constructor"); 527 return true; 528 } 529 } 530 531 if (overFull) { 532 error(line, "too many arguments", "constructor"); 533 return true; 534 } 535 536 if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) { 537 error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); 538 return true; 539 } 540 541 if (!type->isMatrix() || !matrixInMatrix) { 542 if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || 543 (op == EOpConstructStruct && size < type->getObjectSize())) { 544 error(line, "not enough data provided for construction", "constructor"); 545 return true; 546 } 547 } 548 549 TIntermTyped *typed = node ? node->getAsTyped() : 0; 550 if (typed == 0) { 551 error(line, "constructor argument does not have a type", "constructor"); 552 return true; 553 } 554 if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { 555 error(line, "cannot convert a sampler", "constructor"); 556 return true; 557 } 558 if (typed->getBasicType() == EbtVoid) { 559 error(line, "cannot convert a void", "constructor"); 560 return true; 561 } 562 563 return false; 564 } 565 566 // This function checks to see if a void variable has been declared and raise an error message for such a case 567 // 568 // returns true in case of an error 569 // 570 bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType) 571 { 572 if (pubType.type == EbtVoid) { 573 error(line, "illegal use of type 'void'", identifier.c_str()); 574 return true; 575 } 576 577 return false; 578 } 579 580 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not 581 // 582 // returns true in case of an error 583 // 584 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type) 585 { 586 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { 587 error(line, "boolean expression expected", ""); 588 return true; 589 } 590 591 return false; 592 } 593 594 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not 595 // 596 // returns true in case of an error 597 // 598 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) 599 { 600 if (pType.type != EbtBool || pType.isAggregate()) { 601 error(line, "boolean expression expected", ""); 602 return true; 603 } 604 605 return false; 606 } 607 608 bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason) 609 { 610 if (pType.type == EbtStruct) { 611 if (containsSampler(*pType.userDef)) { 612 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); 613 614 return true; 615 } 616 617 return false; 618 } else if (IsSampler(pType.type)) { 619 error(line, reason, getBasicString(pType.type)); 620 621 return true; 622 } 623 624 return false; 625 } 626 627 bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) 628 { 629 switch (pType.qualifier) 630 { 631 case EvqVaryingIn: 632 case EvqVaryingOut: 633 case EvqAttribute: 634 case EvqVertexIn: 635 case EvqFragmentOut: 636 if (pType.type == EbtStruct) 637 { 638 error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); 639 return true; 640 } 641 642 default: break; 643 } 644 645 if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) 646 return true; 647 648 return false; 649 } 650 651 bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType) 652 { 653 if (pType.layoutQualifier.location != -1) 654 { 655 error(line, "location must only be specified for a single input or output variable", "location"); 656 return true; 657 } 658 659 return false; 660 } 661 662 bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) 663 { 664 if ((qualifier == EvqOut || qualifier == EvqInOut) && 665 type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { 666 error(line, "samplers cannot be output parameters", type.getBasicString()); 667 return true; 668 } 669 670 return false; 671 } 672 673 bool TParseContext::containsSampler(TType& type) 674 { 675 if (IsSampler(type.getBasicType())) 676 return true; 677 678 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) { 679 const TFieldList& fields = type.getStruct()->fields(); 680 for (unsigned int i = 0; i < fields.size(); ++i) { 681 if (containsSampler(*fields[i]->type())) 682 return true; 683 } 684 } 685 686 return false; 687 } 688 689 // 690 // Do size checking for an array type's size. 691 // 692 // Returns true if there was an error. 693 // 694 bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) 695 { 696 TIntermConstantUnion* constant = expr->getAsConstantUnion(); 697 698 if (constant == 0 || !constant->isScalarInt()) 699 { 700 error(line, "array size must be a constant integer expression", ""); 701 return true; 702 } 703 704 unsigned int unsignedSize = 0; 705 706 if (constant->getBasicType() == EbtUInt) 707 { 708 unsignedSize = constant->getUConst(0); 709 size = static_cast<int>(unsignedSize); 710 } 711 else 712 { 713 size = constant->getIConst(0); 714 715 if (size < 0) 716 { 717 error(line, "array size must be non-negative", ""); 718 size = 1; 719 return true; 720 } 721 722 unsignedSize = static_cast<unsigned int>(size); 723 } 724 725 if (size == 0) 726 { 727 error(line, "array size must be greater than zero", ""); 728 size = 1; 729 return true; 730 } 731 732 // The size of arrays is restricted here to prevent issues further down the 733 // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to 734 // 4096 registers so this should be reasonable even for aggressively optimizable code. 735 const unsigned int sizeLimit = 65536; 736 737 if (unsignedSize > sizeLimit) 738 { 739 error(line, "array size too large", ""); 740 size = 1; 741 return true; 742 } 743 744 return false; 745 } 746 747 // 748 // See if this qualifier can be an array. 749 // 750 // Returns true if there is an error. 751 // 752 bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) 753 { 754 if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConst)) { 755 error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); 756 return true; 757 } 758 759 return false; 760 } 761 762 // 763 // See if this type can be an array. 764 // 765 // Returns true if there is an error. 766 // 767 bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type) 768 { 769 // 770 // Can the type be an array? 771 // 772 if (type.array) { 773 error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str()); 774 return true; 775 } 776 777 return false; 778 } 779 780 // 781 // Do all the semantic checking for declaring an array, with and 782 // without a size, and make the right changes to the symbol table. 783 // 784 // size == 0 means no specified size. 785 // 786 // Returns true if there was an error. 787 // 788 bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType &type, TVariable*& variable) 789 { 790 // 791 // Don't check for reserved word use until after we know it's not in the symbol table, 792 // because reserved arrays can be redeclared. 793 // 794 795 bool builtIn = false; 796 bool sameScope = false; 797 TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope); 798 if (symbol == 0 || !sameScope) { 799 if (reservedErrorCheck(line, identifier)) 800 return true; 801 802 variable = new TVariable(&identifier, TType(type)); 803 804 if (type.arraySize) 805 variable->getType().setArraySize(type.arraySize); 806 807 if (! symbolTable.declare(*variable)) { 808 delete variable; 809 error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str()); 810 return true; 811 } 812 } else { 813 if (! symbol->isVariable()) { 814 error(line, "variable expected", identifier.c_str()); 815 return true; 816 } 817 818 variable = static_cast<TVariable*>(symbol); 819 if (! variable->getType().isArray()) { 820 error(line, "redeclaring non-array as array", identifier.c_str()); 821 return true; 822 } 823 if (variable->getType().getArraySize() > 0) { 824 error(line, "redeclaration of array with size", identifier.c_str()); 825 return true; 826 } 827 828 if (! variable->getType().sameElementType(TType(type))) { 829 error(line, "redeclaration of array with a different type", identifier.c_str()); 830 return true; 831 } 832 833 if (type.arraySize) 834 variable->getType().setArraySize(type.arraySize); 835 } 836 837 if (voidErrorCheck(line, identifier, type)) 838 return true; 839 840 return false; 841 } 842 843 // 844 // Enforce non-initializer type/qualifier rules. 845 // 846 // Returns true if there was an error. 847 // 848 bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, const TString& identifier, TPublicType& type, bool array) 849 { 850 if (type.qualifier == EvqConst) 851 { 852 // Make the qualifier make sense. 853 type.qualifier = EvqTemporary; 854 855 if (array) 856 { 857 error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str()); 858 } 859 else if (type.isStructureContainingArrays()) 860 { 861 error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str()); 862 } 863 else 864 { 865 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); 866 } 867 868 return true; 869 } 870 871 return false; 872 } 873 874 // 875 // Do semantic checking for a variable declaration that has no initializer, 876 // and update the symbol table. 877 // 878 // Returns true if there was an error. 879 // 880 bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& type, TVariable*& variable) 881 { 882 if (reservedErrorCheck(line, identifier)) 883 recover(); 884 885 variable = new TVariable(&identifier, TType(type)); 886 887 if (! symbolTable.declare(*variable)) { 888 error(line, "redefinition", variable->getName().c_str()); 889 delete variable; 890 variable = 0; 891 return true; 892 } 893 894 if (voidErrorCheck(line, identifier, type)) 895 return true; 896 897 return false; 898 } 899 900 bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) 901 { 902 if (qualifier != EvqConst && qualifier != EvqTemporary) { 903 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); 904 return true; 905 } 906 if (qualifier == EvqConst && paramQualifier != EvqIn) { 907 error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); 908 return true; 909 } 910 911 if (qualifier == EvqConst) 912 type->setQualifier(EvqConstReadOnly); 913 else 914 type->setQualifier(paramQualifier); 915 916 return false; 917 } 918 919 bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) 920 { 921 const TExtensionBehavior& extBehavior = extensionBehavior(); 922 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); 923 if (iter == extBehavior.end()) { 924 error(line, "extension", extension.c_str(), "is not supported"); 925 return true; 926 } 927 // In GLSL ES, an extension's default behavior is "disable". 928 if (iter->second == EBhDisable || iter->second == EBhUndefined) { 929 error(line, "extension", extension.c_str(), "is disabled"); 930 return true; 931 } 932 if (iter->second == EBhWarn) { 933 warning(line, "extension", extension.c_str(), "is being used"); 934 return false; 935 } 936 937 return false; 938 } 939 940 bool TParseContext::singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier) 941 { 942 if (structQualifierErrorCheck(identifierLocation, publicType)) 943 return true; 944 945 // check for layout qualifier issues 946 const TLayoutQualifier layoutQualifier = publicType.layoutQualifier; 947 948 if (layoutQualifier.matrixPacking != EmpUnspecified) 949 { 950 error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking), "only valid for interface blocks"); 951 return true; 952 } 953 954 if (layoutQualifier.blockStorage != EbsUnspecified) 955 { 956 error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage), "only valid for interface blocks"); 957 return true; 958 } 959 960 if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut && layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier)) 961 { 962 return true; 963 } 964 965 return false; 966 } 967 968 bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier) 969 { 970 if (layoutQualifier.location != -1) 971 { 972 error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs"); 973 return true; 974 } 975 976 return false; 977 } 978 979 bool TParseContext::supportsExtension(const char* extension) 980 { 981 const TExtensionBehavior& extbehavior = extensionBehavior(); 982 TExtensionBehavior::const_iterator iter = extbehavior.find(extension); 983 return (iter != extbehavior.end()); 984 } 985 986 bool TParseContext::isExtensionEnabled(const char* extension) const 987 { 988 const TExtensionBehavior& extbehavior = extensionBehavior(); 989 TExtensionBehavior::const_iterator iter = extbehavior.find(extension); 990 991 if (iter == extbehavior.end()) 992 { 993 return false; 994 } 995 996 return (iter->second == EBhEnable || iter->second == EBhRequire); 997 } 998 999 void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior) 1000 { 1001 pp::SourceLocation srcLoc; 1002 srcLoc.file = loc.first_file; 1003 srcLoc.line = loc.first_line; 1004 directiveHandler.handleExtension(srcLoc, extName, behavior); 1005 } 1006 1007 void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value) 1008 { 1009 pp::SourceLocation srcLoc; 1010 srcLoc.file = loc.first_file; 1011 srcLoc.line = loc.first_line; 1012 directiveHandler.handlePragma(srcLoc, name, value); 1013 } 1014 1015 ///////////////////////////////////////////////////////////////////////////////// 1016 // 1017 // Non-Errors. 1018 // 1019 ///////////////////////////////////////////////////////////////////////////////// 1020 1021 // 1022 // Look up a function name in the symbol table, and make sure it is a function. 1023 // 1024 // Return the function symbol if found, otherwise 0. 1025 // 1026 const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn) 1027 { 1028 // First find by unmangled name to check whether the function name has been 1029 // hidden by a variable name or struct typename. 1030 // If a function is found, check for one with a matching argument list. 1031 const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn); 1032 if (symbol == 0 || symbol->isFunction()) { 1033 symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn); 1034 } 1035 1036 if (symbol == 0) { 1037 error(line, "no matching overloaded function found", call->getName().c_str()); 1038 return 0; 1039 } 1040 1041 if (!symbol->isFunction()) { 1042 error(line, "function name expected", call->getName().c_str()); 1043 return 0; 1044 } 1045 1046 return static_cast<const TFunction*>(symbol); 1047 } 1048 1049 // 1050 // Initializers show up in several places in the grammar. Have one set of 1051 // code to handle them here. 1052 // 1053 bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, 1054 TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) 1055 { 1056 TType type = TType(pType); 1057 1058 if (variable == 0) { 1059 if (reservedErrorCheck(line, identifier)) 1060 return true; 1061 1062 if (voidErrorCheck(line, identifier, pType)) 1063 return true; 1064 1065 // 1066 // add variable to symbol table 1067 // 1068 variable = new TVariable(&identifier, type); 1069 if (! symbolTable.declare(*variable)) { 1070 error(line, "redefinition", variable->getName().c_str()); 1071 return true; 1072 // don't delete variable, it's used by error recovery, and the pool 1073 // pop will take care of the memory 1074 } 1075 } 1076 1077 // 1078 // identifier must be of type constant, a global, or a temporary 1079 // 1080 TQualifier qualifier = variable->getType().getQualifier(); 1081 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) { 1082 error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); 1083 return true; 1084 } 1085 // 1086 // test for and propagate constant 1087 // 1088 1089 if (qualifier == EvqConst) { 1090 if (qualifier != initializer->getType().getQualifier()) { 1091 std::stringstream extraInfoStream; 1092 extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; 1093 std::string extraInfo = extraInfoStream.str(); 1094 error(line, " assigning non-constant to", "=", extraInfo.c_str()); 1095 variable->getType().setQualifier(EvqTemporary); 1096 return true; 1097 } 1098 if (type != initializer->getType()) { 1099 error(line, " non-matching types for const initializer ", 1100 variable->getType().getQualifierString()); 1101 variable->getType().setQualifier(EvqTemporary); 1102 return true; 1103 } 1104 if (initializer->getAsConstantUnion()) { 1105 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); 1106 } else if (initializer->getAsSymbolNode()) { 1107 const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0); 1108 const TVariable* tVar = static_cast<const TVariable*>(symbol); 1109 1110 ConstantUnion* constArray = tVar->getConstPointer(); 1111 variable->shareConstPointer(constArray); 1112 } else { 1113 std::stringstream extraInfoStream; 1114 extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; 1115 std::string extraInfo = extraInfoStream.str(); 1116 error(line, " cannot assign to", "=", extraInfo.c_str()); 1117 variable->getType().setQualifier(EvqTemporary); 1118 return true; 1119 } 1120 } 1121 1122 if (qualifier != EvqConst) { 1123 TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); 1124 intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); 1125 if (intermNode == 0) { 1126 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); 1127 return true; 1128 } 1129 } else 1130 intermNode = 0; 1131 1132 return false; 1133 } 1134 1135 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) 1136 { 1137 ASSERT(aggrNode != NULL); 1138 if (!aggrNode->isConstructor()) 1139 return false; 1140 1141 bool allConstant = true; 1142 1143 // check if all the child nodes are constants so that they can be inserted into 1144 // the parent node 1145 TIntermSequence &sequence = aggrNode->getSequence() ; 1146 for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { 1147 if (!(*p)->getAsTyped()->getAsConstantUnion()) 1148 return false; 1149 } 1150 1151 return allConstant; 1152 } 1153 1154 TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQualifier layoutQualifier, const TPublicType& typeSpecifier) 1155 { 1156 TPublicType returnType = typeSpecifier; 1157 returnType.qualifier = qualifier; 1158 returnType.layoutQualifier = layoutQualifier; 1159 1160 if (typeSpecifier.array) 1161 { 1162 error(typeSpecifier.line, "not supported", "first-class array"); 1163 recover(); 1164 returnType.setArray(false); 1165 } 1166 1167 if (shaderVersion < 300) 1168 { 1169 if (qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) 1170 { 1171 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); 1172 recover(); 1173 } 1174 1175 if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) && 1176 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) 1177 { 1178 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); 1179 recover(); 1180 } 1181 } 1182 else 1183 { 1184 switch (qualifier) 1185 { 1186 case EvqSmoothIn: 1187 case EvqSmoothOut: 1188 case EvqVertexOut: 1189 case EvqFragmentIn: 1190 case EvqCentroidOut: 1191 case EvqCentroidIn: 1192 if (typeSpecifier.type == EbtBool) 1193 { 1194 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier)); 1195 recover(); 1196 } 1197 if (typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt) 1198 { 1199 error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier)); 1200 recover(); 1201 } 1202 break; 1203 1204 case EvqVertexIn: 1205 case EvqFragmentOut: 1206 case EvqFlatIn: 1207 case EvqFlatOut: 1208 if (typeSpecifier.type == EbtBool) 1209 { 1210 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier)); 1211 recover(); 1212 } 1213 break; 1214 1215 default: break; 1216 } 1217 } 1218 1219 return returnType; 1220 } 1221 1222 TIntermAggregate* TParseContext::parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier) 1223 { 1224 TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); 1225 TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation); 1226 1227 if (identifier != "") 1228 { 1229 if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) 1230 recover(); 1231 1232 // this error check can mutate the type 1233 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false)) 1234 recover(); 1235 1236 TVariable* variable = 0; 1237 1238 if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable)) 1239 recover(); 1240 1241 if (variable && symbol) 1242 { 1243 symbol->setId(variable->getUniqueId()); 1244 } 1245 } 1246 1247 return aggregate; 1248 } 1249 1250 TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression) 1251 { 1252 if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) 1253 recover(); 1254 1255 // this error check can mutate the type 1256 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true)) 1257 recover(); 1258 1259 if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType)) 1260 { 1261 recover(); 1262 } 1263 1264 TPublicType arrayType = publicType; 1265 1266 int size; 1267 if (arraySizeErrorCheck(identifierLocation, indexExpression, size)) 1268 { 1269 recover(); 1270 } 1271 else 1272 { 1273 arrayType.setArray(true, size); 1274 } 1275 1276 TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(arrayType), identifierLocation); 1277 TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation); 1278 TVariable* variable = 0; 1279 1280 if (arrayErrorCheck(identifierLocation, identifier, arrayType, variable)) 1281 recover(); 1282 1283 if (variable && symbol) 1284 { 1285 symbol->setId(variable->getUniqueId()); 1286 } 1287 1288 return aggregate; 1289 } 1290 1291 TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer) 1292 { 1293 if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) 1294 recover(); 1295 1296 TIntermNode* intermNode; 1297 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode)) 1298 { 1299 // 1300 // Build intermediate representation 1301 // 1302 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : NULL; 1303 } 1304 else 1305 { 1306 recover(); 1307 return NULL; 1308 } 1309 } 1310 1311 TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) 1312 { 1313 if (publicType.type == EbtInvariant && !identifierSymbol) 1314 { 1315 error(identifierLocation, "undeclared identifier declared as invariant", identifier.c_str()); 1316 recover(); 1317 } 1318 1319 TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); 1320 TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); 1321 1322 if (structQualifierErrorCheck(identifierLocation, publicType)) 1323 recover(); 1324 1325 if (locationDeclaratorListCheck(identifierLocation, publicType)) 1326 recover(); 1327 1328 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false)) 1329 recover(); 1330 1331 TVariable* variable = 0; 1332 if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable)) 1333 recover(); 1334 if (symbol && variable) 1335 symbol->setId(variable->getUniqueId()); 1336 1337 return intermAggregate; 1338 } 1339 1340 TIntermAggregate* TParseContext::parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression) 1341 { 1342 if (structQualifierErrorCheck(identifierLocation, publicType)) 1343 recover(); 1344 1345 if (locationDeclaratorListCheck(identifierLocation, publicType)) 1346 recover(); 1347 1348 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true)) 1349 recover(); 1350 1351 if (arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType)) 1352 { 1353 recover(); 1354 } 1355 else if (indexExpression) 1356 { 1357 int size; 1358 if (arraySizeErrorCheck(arrayLocation, indexExpression, size)) 1359 recover(); 1360 TPublicType arrayType(publicType); 1361 arrayType.setArray(true, size); 1362 TVariable* variable = NULL; 1363 if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable)) 1364 recover(); 1365 TType type = TType(arrayType); 1366 type.setArraySize(size); 1367 1368 return intermediate.growAggregate(declaratorList, intermediate.addSymbol(variable ? variable->getUniqueId() : 0, identifier, type, identifierLocation), identifierLocation); 1369 } 1370 else 1371 { 1372 TPublicType arrayType(publicType); 1373 arrayType.setArray(true); 1374 TVariable* variable = NULL; 1375 if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable)) 1376 recover(); 1377 } 1378 1379 return NULL; 1380 } 1381 1382 TIntermAggregate* TParseContext::parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer) 1383 { 1384 if (structQualifierErrorCheck(identifierLocation, publicType)) 1385 recover(); 1386 1387 if (locationDeclaratorListCheck(identifierLocation, publicType)) 1388 recover(); 1389 1390 TIntermNode* intermNode; 1391 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode)) 1392 { 1393 // 1394 // build the intermediate representation 1395 // 1396 if (intermNode) 1397 { 1398 return intermediate.growAggregate(declaratorList, intermNode, initLocation); 1399 } 1400 else 1401 { 1402 return declaratorList; 1403 } 1404 } 1405 else 1406 { 1407 recover(); 1408 return NULL; 1409 } 1410 } 1411 1412 void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) 1413 { 1414 if (typeQualifier.qualifier != EvqUniform) 1415 { 1416 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform"); 1417 recover(); 1418 return; 1419 } 1420 1421 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; 1422 ASSERT(!layoutQualifier.isEmpty()); 1423 1424 if (shaderVersion < 300) 1425 { 1426 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout"); 1427 recover(); 1428 return; 1429 } 1430 1431 if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier)) 1432 { 1433 recover(); 1434 return; 1435 } 1436 1437 if (layoutQualifier.matrixPacking != EmpUnspecified) 1438 { 1439 defaultMatrixPacking = layoutQualifier.matrixPacking; 1440 } 1441 1442 if (layoutQualifier.blockStorage != EbsUnspecified) 1443 { 1444 defaultBlockStorage = layoutQualifier.blockStorage; 1445 } 1446 } 1447 1448 TFunction *TParseContext::addConstructorFunc(TPublicType publicType) 1449 { 1450 TOperator op = EOpNull; 1451 if (publicType.userDef) 1452 { 1453 op = EOpConstructStruct; 1454 } 1455 else 1456 { 1457 switch (publicType.type) 1458 { 1459 case EbtFloat: 1460 if (publicType.isMatrix()) 1461 { 1462 // TODO: non-square matrices 1463 switch(publicType.getCols()) 1464 { 1465 case 2: op = EOpConstructMat2; break; 1466 case 3: op = EOpConstructMat3; break; 1467 case 4: op = EOpConstructMat4; break; 1468 } 1469 } 1470 else 1471 { 1472 switch(publicType.getNominalSize()) 1473 { 1474 case 1: op = EOpConstructFloat; break; 1475 case 2: op = EOpConstructVec2; break; 1476 case 3: op = EOpConstructVec3; break; 1477 case 4: op = EOpConstructVec4; break; 1478 } 1479 } 1480 break; 1481 1482 case EbtInt: 1483 switch(publicType.getNominalSize()) 1484 { 1485 case 1: op = EOpConstructInt; break; 1486 case 2: op = EOpConstructIVec2; break; 1487 case 3: op = EOpConstructIVec3; break; 1488 case 4: op = EOpConstructIVec4; break; 1489 } 1490 break; 1491 1492 case EbtUInt: 1493 switch(publicType.getNominalSize()) 1494 { 1495 case 1: op = EOpConstructUInt; break; 1496 case 2: op = EOpConstructUVec2; break; 1497 case 3: op = EOpConstructUVec3; break; 1498 case 4: op = EOpConstructUVec4; break; 1499 } 1500 break; 1501 1502 case EbtBool: 1503 switch(publicType.getNominalSize()) 1504 { 1505 case 1: op = EOpConstructBool; break; 1506 case 2: op = EOpConstructBVec2; break; 1507 case 3: op = EOpConstructBVec3; break; 1508 case 4: op = EOpConstructBVec4; break; 1509 } 1510 break; 1511 1512 default: break; 1513 } 1514 1515 if (op == EOpNull) 1516 { 1517 error(publicType.line, "cannot construct this type", getBasicString(publicType.type)); 1518 recover(); 1519 publicType.type = EbtFloat; 1520 op = EOpConstructFloat; 1521 } 1522 } 1523 1524 TString tempString; 1525 TType type(publicType); 1526 return new TFunction(&tempString, type, op); 1527 } 1528 1529 // This function is used to test for the correctness of the parameters passed to various constructor functions 1530 // and also convert them to the right datatype if it is allowed and required. 1531 // 1532 // Returns 0 for an error or the constructed node (aggregate or typed) for no error. 1533 // 1534 TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) 1535 { 1536 if (node == 0) 1537 return 0; 1538 1539 TIntermAggregate* aggrNode = node->getAsAggregate(); 1540 1541 TFieldList::const_iterator memberTypes; 1542 if (op == EOpConstructStruct) 1543 memberTypes = type->getStruct()->fields().begin(); 1544 1545 TType elementType = *type; 1546 if (type->isArray()) 1547 elementType.clearArrayness(); 1548 1549 bool singleArg; 1550 if (aggrNode) { 1551 if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) 1552 singleArg = true; 1553 else 1554 singleArg = false; 1555 } else 1556 singleArg = true; 1557 1558 TIntermTyped *newNode; 1559 if (singleArg) { 1560 // If structure constructor or array constructor is being called 1561 // for only one parameter inside the structure, we need to call constructStruct function once. 1562 if (type->isArray()) 1563 newNode = constructStruct(node, &elementType, 1, node->getLine(), false); 1564 else if (op == EOpConstructStruct) 1565 newNode = constructStruct(node, (*memberTypes)->type(), 1, node->getLine(), false); 1566 else 1567 newNode = constructBuiltIn(type, op, node, node->getLine(), false); 1568 1569 if (newNode && newNode->getAsAggregate()) { 1570 TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); 1571 if (constConstructor) 1572 return constConstructor; 1573 } 1574 1575 return newNode; 1576 } 1577 1578 // 1579 // Handle list of arguments. 1580 // 1581 TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor 1582 // if the structure constructor contains more than one parameter, then construct 1583 // each parameter 1584 1585 int paramCount = 0; // keeps a track of the constructor parameter number being checked 1586 1587 // for each parameter to the constructor call, check to see if the right type is passed or convert them 1588 // to the right type if possible (and allowed). 1589 // for structure constructors, just check if the right type is passed, no conversion is allowed. 1590 1591 for (TIntermSequence::iterator p = sequenceVector.begin(); 1592 p != sequenceVector.end(); p++, paramCount++) { 1593 if (type->isArray()) 1594 newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); 1595 else if (op == EOpConstructStruct) 1596 newNode = constructStruct(*p, (memberTypes[paramCount])->type(), paramCount+1, node->getLine(), true); 1597 else 1598 newNode = constructBuiltIn(type, op, *p, node->getLine(), true); 1599 1600 if (newNode) { 1601 *p = newNode; 1602 } 1603 } 1604 1605 TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); 1606 TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); 1607 if (constConstructor) 1608 return constConstructor; 1609 1610 return constructor; 1611 } 1612 1613 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) 1614 { 1615 bool canBeFolded = areAllChildConst(aggrNode); 1616 aggrNode->setType(type); 1617 if (canBeFolded) { 1618 bool returnVal = false; 1619 ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; 1620 if (aggrNode->getSequence().size() == 1) { 1621 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true); 1622 } 1623 else { 1624 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type); 1625 } 1626 if (returnVal) 1627 return 0; 1628 1629 return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); 1630 } 1631 1632 return 0; 1633 } 1634 1635 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value 1636 // for the parameter to the constructor (passed to this function). Essentially, it converts 1637 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 1638 // float, then float is converted to int. 1639 // 1640 // Returns 0 for an error or the constructed node. 1641 // 1642 TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) 1643 { 1644 TIntermTyped* newNode; 1645 TOperator basicOp; 1646 1647 // 1648 // First, convert types as needed. 1649 // 1650 switch (op) { 1651 case EOpConstructVec2: 1652 case EOpConstructVec3: 1653 case EOpConstructVec4: 1654 case EOpConstructMat2: 1655 case EOpConstructMat3: 1656 case EOpConstructMat4: 1657 case EOpConstructFloat: 1658 basicOp = EOpConstructFloat; 1659 break; 1660 1661 case EOpConstructIVec2: 1662 case EOpConstructIVec3: 1663 case EOpConstructIVec4: 1664 case EOpConstructInt: 1665 basicOp = EOpConstructInt; 1666 break; 1667 1668 case EOpConstructUVec2: 1669 case EOpConstructUVec3: 1670 case EOpConstructUVec4: 1671 case EOpConstructUInt: 1672 basicOp = EOpConstructUInt; 1673 break; 1674 1675 case EOpConstructBVec2: 1676 case EOpConstructBVec3: 1677 case EOpConstructBVec4: 1678 case EOpConstructBool: 1679 basicOp = EOpConstructBool; 1680 break; 1681 1682 default: 1683 error(line, "unsupported construction", ""); 1684 recover(); 1685 1686 return 0; 1687 } 1688 newNode = intermediate.addUnaryMath(basicOp, node, node->getLine()); 1689 if (newNode == 0) { 1690 error(line, "can't convert", "constructor"); 1691 return 0; 1692 } 1693 1694 // 1695 // Now, if there still isn't an operation to do the construction, and we need one, add one. 1696 // 1697 1698 // Otherwise, skip out early. 1699 if (subset || (newNode != node && newNode->getType() == *type)) 1700 return newNode; 1701 1702 // setAggregateOperator will insert a new node for the constructor, as needed. 1703 return intermediate.setAggregateOperator(newNode, op, line); 1704 } 1705 1706 // This function tests for the type of the parameters to the structures constructors. Raises 1707 // an error message if the expected type does not match the parameter passed to the constructor. 1708 // 1709 // Returns 0 for an error or the input node itself if the expected and the given parameter types match. 1710 // 1711 TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) 1712 { 1713 if (*type == node->getAsTyped()->getType()) { 1714 if (subset) 1715 return node->getAsTyped(); 1716 else 1717 return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); 1718 } else { 1719 std::stringstream extraInfoStream; 1720 extraInfoStream << "cannot convert parameter " << paramCount 1721 << " from '" << node->getAsTyped()->getType().getBasicString() 1722 << "' to '" << type->getBasicString() << "'"; 1723 std::string extraInfo = extraInfoStream.str(); 1724 error(line, "", "constructor", extraInfo.c_str()); 1725 recover(); 1726 } 1727 1728 return 0; 1729 } 1730 1731 // 1732 // This function returns the tree representation for the vector field(s) being accessed from contant vector. 1733 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is 1734 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol 1735 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 1736 // a constant matrix. 1737 // 1738 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) 1739 { 1740 TIntermTyped* typedNode; 1741 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1742 1743 ConstantUnion *unionArray; 1744 if (tempConstantNode) { 1745 unionArray = tempConstantNode->getUnionArrayPointer(); 1746 1747 if (!unionArray) { 1748 return node; 1749 } 1750 } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error 1751 error(line, "Cannot offset into the vector", "Error"); 1752 recover(); 1753 1754 return 0; 1755 } 1756 1757 ConstantUnion* constArray = new ConstantUnion[fields.num]; 1758 1759 for (int i = 0; i < fields.num; i++) { 1760 if (fields.offsets[i] >= node->getType().getNominalSize()) { 1761 std::stringstream extraInfoStream; 1762 extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; 1763 std::string extraInfo = extraInfoStream.str(); 1764 error(line, "", "[", extraInfo.c_str()); 1765 recover(); 1766 fields.offsets[i] = 0; 1767 } 1768 1769 constArray[i] = unionArray[fields.offsets[i]]; 1770 1771 } 1772 typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); 1773 return typedNode; 1774 } 1775 1776 // 1777 // This function returns the column being accessed from a constant matrix. The values are retrieved from 1778 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 1779 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 1780 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) 1781 // 1782 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) 1783 { 1784 TIntermTyped* typedNode; 1785 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1786 1787 if (index >= node->getType().getCols()) { 1788 std::stringstream extraInfoStream; 1789 extraInfoStream << "matrix field selection out of range '" << index << "'"; 1790 std::string extraInfo = extraInfoStream.str(); 1791 error(line, "", "[", extraInfo.c_str()); 1792 recover(); 1793 index = 0; 1794 } 1795 1796 if (tempConstantNode) { 1797 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); 1798 int size = tempConstantNode->getType().getCols(); 1799 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); 1800 } else { 1801 error(line, "Cannot offset into the matrix", "Error"); 1802 recover(); 1803 1804 return 0; 1805 } 1806 1807 return typedNode; 1808 } 1809 1810 1811 // 1812 // This function returns an element of an array accessed from a constant array. The values are retrieved from 1813 // the symbol table and parse-tree is built for the type of the element. The input 1814 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a 1815 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) 1816 // 1817 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) 1818 { 1819 TIntermTyped* typedNode; 1820 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1821 TType arrayElementType = node->getType(); 1822 arrayElementType.clearArrayness(); 1823 1824 if (index >= node->getType().getArraySize()) { 1825 std::stringstream extraInfoStream; 1826 extraInfoStream << "array field selection out of range '" << index << "'"; 1827 std::string extraInfo = extraInfoStream.str(); 1828 error(line, "", "[", extraInfo.c_str()); 1829 recover(); 1830 index = 0; 1831 } 1832 1833 if (tempConstantNode) { 1834 size_t arrayElementSize = arrayElementType.getObjectSize(); 1835 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); 1836 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); 1837 } else { 1838 error(line, "Cannot offset into the array", "Error"); 1839 recover(); 1840 1841 return 0; 1842 } 1843 1844 return typedNode; 1845 } 1846 1847 1848 // 1849 // This function returns the value of a particular field inside a constant structure from the symbol table. 1850 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr 1851 // function and returns the parse-tree with the values of the embedded/nested struct. 1852 // 1853 TIntermTyped* TParseContext::addConstStruct(const TString &identifier, TIntermTyped *node, const TSourceLoc& line) 1854 { 1855 const TFieldList& fields = node->getType().getStruct()->fields(); 1856 size_t instanceSize = 0; 1857 1858 for (size_t index = 0; index < fields.size(); ++index) { 1859 if (fields[index]->name() == identifier) { 1860 break; 1861 } else { 1862 instanceSize += fields[index]->type()->getObjectSize(); 1863 } 1864 } 1865 1866 TIntermTyped *typedNode; 1867 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); 1868 if (tempConstantNode) { 1869 ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); 1870 1871 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function 1872 } else { 1873 error(line, "Cannot offset into the structure", "Error"); 1874 recover(); 1875 1876 return 0; 1877 } 1878 1879 return typedNode; 1880 } 1881 1882 // 1883 // Interface/uniform blocks 1884 // 1885 TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, 1886 const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine) 1887 { 1888 if (reservedErrorCheck(nameLine, blockName)) 1889 recover(); 1890 1891 if (typeQualifier.qualifier != EvqUniform) 1892 { 1893 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform"); 1894 recover(); 1895 } 1896 1897 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; 1898 if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier)) 1899 { 1900 recover(); 1901 } 1902 1903 if (blockLayoutQualifier.matrixPacking == EmpUnspecified) 1904 { 1905 blockLayoutQualifier.matrixPacking = defaultMatrixPacking; 1906 } 1907 1908 if (blockLayoutQualifier.blockStorage == EbsUnspecified) 1909 { 1910 blockLayoutQualifier.blockStorage = defaultBlockStorage; 1911 } 1912 1913 TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName); 1914 if (!symbolTable.declare(*blockNameSymbol)) { 1915 error(nameLine, "redefinition", blockName.c_str(), "interface block name"); 1916 recover(); 1917 } 1918 1919 // check for sampler types and apply layout qualifiers 1920 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) { 1921 TField* field = (*fieldList)[memberIndex]; 1922 TType* fieldType = field->type(); 1923 if (IsSampler(fieldType->getBasicType())) { 1924 error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks"); 1925 recover(); 1926 } 1927 1928 const TQualifier qualifier = fieldType->getQualifier(); 1929 switch (qualifier) 1930 { 1931 case EvqGlobal: 1932 case EvqUniform: 1933 break; 1934 default: 1935 error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier)); 1936 recover(); 1937 break; 1938 } 1939 1940 // check layout qualifiers 1941 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); 1942 if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier)) 1943 { 1944 recover(); 1945 } 1946 1947 if (fieldLayoutQualifier.blockStorage != EbsUnspecified) 1948 { 1949 error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here"); 1950 recover(); 1951 } 1952 1953 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified) 1954 { 1955 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking; 1956 } 1957 else if (!fieldType->isMatrix()) 1958 { 1959 error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types"); 1960 recover(); 1961 } 1962 1963 fieldType->setLayoutQualifier(fieldLayoutQualifier); 1964 } 1965 1966 // add array index 1967 int arraySize = 0; 1968 if (arrayIndex != NULL) 1969 { 1970 if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize)) 1971 recover(); 1972 } 1973 1974 TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier); 1975 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize); 1976 1977 TString symbolName = ""; 1978 int symbolId = 0; 1979 1980 if (!instanceName) 1981 { 1982 // define symbols for the members of the interface block 1983 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) 1984 { 1985 TField* field = (*fieldList)[memberIndex]; 1986 TType* fieldType = field->type(); 1987 1988 // set parent pointer of the field variable 1989 fieldType->setInterfaceBlock(interfaceBlock); 1990 1991 TVariable* fieldVariable = new TVariable(&field->name(), *fieldType); 1992 fieldVariable->setQualifier(typeQualifier.qualifier); 1993 1994 if (!symbolTable.declare(*fieldVariable)) { 1995 error(field->line(), "redefinition", field->name().c_str(), "interface block member name"); 1996 recover(); 1997 } 1998 } 1999 } 2000 else 2001 { 2002 // add a symbol for this interface block 2003 TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false); 2004 instanceTypeDef->setQualifier(typeQualifier.qualifier); 2005 2006 if (!symbolTable.declare(*instanceTypeDef)) { 2007 error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name"); 2008 recover(); 2009 } 2010 2011 symbolId = instanceTypeDef->getUniqueId(); 2012 symbolName = instanceTypeDef->getName(); 2013 } 2014 2015 TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine); 2016 aggregate->setOp(EOpDeclaration); 2017 2018 exitStructDeclaration(); 2019 return aggregate; 2020 } 2021 2022 bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) 2023 { 2024 ++structNestingLevel; 2025 2026 // Embedded structure definitions are not supported per GLSL ES spec. 2027 // They aren't allowed in GLSL either, but we need to detect this here 2028 // so we don't rely on the GLSL compiler to catch it. 2029 if (structNestingLevel > 1) { 2030 error(line, "", "Embedded struct definitions are not allowed"); 2031 return true; 2032 } 2033 2034 return false; 2035 } 2036 2037 void TParseContext::exitStructDeclaration() 2038 { 2039 --structNestingLevel; 2040 } 2041 2042 namespace { 2043 2044 const int kWebGLMaxStructNesting = 4; 2045 2046 } // namespace 2047 2048 bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) 2049 { 2050 if (!IsWebGLBasedSpec(shaderSpec)) { 2051 return false; 2052 } 2053 2054 if (field.type()->getBasicType() != EbtStruct) { 2055 return false; 2056 } 2057 2058 // We're already inside a structure definition at this point, so add 2059 // one to the field's struct nesting. 2060 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { 2061 std::stringstream reasonStream; 2062 reasonStream << "Reference of struct type " 2063 << field.type()->getStruct()->name().c_str() 2064 << " exceeds maximum allowed nesting level of " 2065 << kWebGLMaxStructNesting; 2066 std::string reason = reasonStream.str(); 2067 error(line, reason.c_str(), field.name().c_str(), ""); 2068 return true; 2069 } 2070 2071 return false; 2072 } 2073 2074 // 2075 // Parse an array index expression 2076 // 2077 TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) 2078 { 2079 TIntermTyped *indexedExpression = NULL; 2080 2081 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) 2082 { 2083 if (baseExpression->getAsSymbolNode()) 2084 { 2085 error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); 2086 } 2087 else 2088 { 2089 error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); 2090 } 2091 recover(); 2092 } 2093 2094 if (indexExpression->getQualifier() == EvqConst) 2095 { 2096 int index = indexExpression->getAsConstantUnion()->getIConst(0); 2097 if (index < 0) 2098 { 2099 std::stringstream infoStream; 2100 infoStream << index; 2101 std::string info = infoStream.str(); 2102 error(location, "negative index", info.c_str()); 2103 recover(); 2104 index = 0; 2105 } 2106 if (baseExpression->getType().getQualifier() == EvqConst) 2107 { 2108 if (baseExpression->isArray()) 2109 { 2110 // constant folding for arrays 2111 indexedExpression = addConstArrayNode(index, baseExpression, location); 2112 } 2113 else if (baseExpression->isVector()) 2114 { 2115 // constant folding for vectors 2116 TVectorFields fields; 2117 fields.num = 1; 2118 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array 2119 indexedExpression = addConstVectorNode(fields, baseExpression, location); 2120 } 2121 else if (baseExpression->isMatrix()) 2122 { 2123 // constant folding for matrices 2124 indexedExpression = addConstMatrixNode(index, baseExpression, location); 2125 } 2126 } 2127 else 2128 { 2129 if (baseExpression->isArray()) 2130 { 2131 if (index >= baseExpression->getType().getArraySize()) 2132 { 2133 std::stringstream extraInfoStream; 2134 extraInfoStream << "array index out of range '" << index << "'"; 2135 std::string extraInfo = extraInfoStream.str(); 2136 error(location, "", "[", extraInfo.c_str()); 2137 recover(); 2138 index = baseExpression->getType().getArraySize() - 1; 2139 } 2140 else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) 2141 { 2142 error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); 2143 recover(); 2144 index = 0; 2145 } 2146 } 2147 else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) 2148 { 2149 std::stringstream extraInfoStream; 2150 extraInfoStream << "field selection out of range '" << index << "'"; 2151 std::string extraInfo = extraInfoStream.str(); 2152 error(location, "", "[", extraInfo.c_str()); 2153 recover(); 2154 index = baseExpression->getType().getNominalSize() - 1; 2155 } 2156 2157 indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); 2158 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); 2159 } 2160 } 2161 else 2162 { 2163 if (baseExpression->isInterfaceBlock()) 2164 { 2165 error(location, "", "[", "array indexes for interface blocks arrays must be constant integral expressions"); 2166 recover(); 2167 } 2168 else if (baseExpression->getQualifier() == EvqFragmentOut) 2169 { 2170 error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions"); 2171 recover(); 2172 } 2173 2174 indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); 2175 } 2176 2177 if (indexedExpression == 0) 2178 { 2179 ConstantUnion *unionArray = new ConstantUnion[1]; 2180 unionArray->setFConst(0.0f); 2181 indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); 2182 } 2183 else if (baseExpression->isArray()) 2184 { 2185 const TType &baseType = baseExpression->getType(); 2186 if (baseType.getStruct()) 2187 { 2188 TType copyOfType(baseType.getStruct()); 2189 indexedExpression->setType(copyOfType); 2190 } 2191 else if (baseType.isInterfaceBlock()) 2192 { 2193 TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(), baseType.getLayoutQualifier(), 0); 2194 indexedExpression->setType(copyOfType); 2195 } 2196 else 2197 { 2198 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->getSecondarySize())); 2199 } 2200 2201 if (baseExpression->getType().getQualifier() == EvqConst) 2202 { 2203 indexedExpression->getTypePointer()->setQualifier(EvqConst); 2204 } 2205 } 2206 else if (baseExpression->isMatrix()) 2207 { 2208 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; 2209 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getRows())); 2210 } 2211 else if (baseExpression->isVector()) 2212 { 2213 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; 2214 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); 2215 } 2216 else 2217 { 2218 indexedExpression->setType(baseExpression->getType()); 2219 } 2220 2221 return indexedExpression; 2222 } 2223 2224 TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc& dotLocation, const TString &fieldString, const TSourceLoc& fieldLocation) 2225 { 2226 TIntermTyped *indexedExpression = NULL; 2227 2228 if (baseExpression->isArray()) 2229 { 2230 error(fieldLocation, "cannot apply dot operator to an array", "."); 2231 recover(); 2232 } 2233 2234 if (baseExpression->isVector()) 2235 { 2236 TVectorFields fields; 2237 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation)) 2238 { 2239 fields.num = 1; 2240 fields.offsets[0] = 0; 2241 recover(); 2242 } 2243 2244 if (baseExpression->getType().getQualifier() == EvqConst) 2245 { 2246 // constant folding for vector fields 2247 indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation); 2248 if (indexedExpression == 0) 2249 { 2250 recover(); 2251 indexedExpression = baseExpression; 2252 } 2253 else 2254 { 2255 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, (int) (fieldString).size())); 2256 } 2257 } 2258 else 2259 { 2260 TString vectorString = fieldString; 2261 TIntermTyped* index = intermediate.addSwizzle(fields, fieldLocation); 2262 indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation); 2263 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, (int) vectorString.size())); 2264 } 2265 } 2266 else if (baseExpression->isMatrix()) 2267 { 2268 TMatrixFields fields; 2269 if (!parseMatrixFields(fieldString, baseExpression->getCols(), baseExpression->getRows(), fields, fieldLocation)) 2270 { 2271 fields.wholeRow = false; 2272 fields.wholeCol = false; 2273 fields.row = 0; 2274 fields.col = 0; 2275 recover(); 2276 } 2277 2278 if (fields.wholeRow || fields.wholeCol) 2279 { 2280 error(dotLocation, " non-scalar fields not implemented yet", "."); 2281 recover(); 2282 ConstantUnion *unionArray = new ConstantUnion[1]; 2283 unionArray->setIConst(0); 2284 TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation); 2285 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation); 2286 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),EvqTemporary, baseExpression->getCols(), baseExpression->getRows())); 2287 } 2288 else 2289 { 2290 ConstantUnion *unionArray = new ConstantUnion[1]; 2291 unionArray->setIConst(fields.col * baseExpression->getRows() + fields.row); 2292 TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation); 2293 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation); 2294 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision())); 2295 } 2296 } 2297 else if (baseExpression->getBasicType() == EbtStruct) 2298 { 2299 bool fieldFound = false; 2300 const TFieldList& fields = baseExpression->getType().getStruct()->fields(); 2301 if (fields.empty()) 2302 { 2303 error(dotLocation, "structure has no fields", "Internal Error"); 2304 recover(); 2305 indexedExpression = baseExpression; 2306 } 2307 else 2308 { 2309 unsigned int i; 2310 for (i = 0; i < fields.size(); ++i) 2311 { 2312 if (fields[i]->name() == fieldString) 2313 { 2314 fieldFound = true; 2315 break; 2316 } 2317 } 2318 if (fieldFound) 2319 { 2320 if (baseExpression->getType().getQualifier() == EvqConst) 2321 { 2322 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation); 2323 if (indexedExpression == 0) 2324 { 2325 recover(); 2326 indexedExpression = baseExpression; 2327 } 2328 else 2329 { 2330 indexedExpression->setType(*fields[i]->type()); 2331 // change the qualifier of the return type, not of the structure field 2332 // as the structure definition is shared between various structures. 2333 indexedExpression->getTypePointer()->setQualifier(EvqConst); 2334 } 2335 } 2336 else 2337 { 2338 ConstantUnion *unionArray = new ConstantUnion[1]; 2339 unionArray->setIConst(i); 2340 TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation); 2341 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation); 2342 indexedExpression->setType(*fields[i]->type()); 2343 } 2344 } 2345 else 2346 { 2347 error(dotLocation, " no such field in structure", fieldString.c_str()); 2348 recover(); 2349 indexedExpression = baseExpression; 2350 } 2351 } 2352 } 2353 else if (baseExpression->isInterfaceBlock()) 2354 { 2355 bool fieldFound = false; 2356 const TFieldList& fields = baseExpression->getType().getInterfaceBlock()->fields(); 2357 if (fields.empty()) 2358 { 2359 error(dotLocation, "interface block has no fields", "Internal Error"); 2360 recover(); 2361 indexedExpression = baseExpression; 2362 } 2363 else 2364 { 2365 unsigned int i; 2366 for (i = 0; i < fields.size(); ++i) 2367 { 2368 if (fields[i]->name() == fieldString) 2369 { 2370 fieldFound = true; 2371 break; 2372 } 2373 } 2374 if (fieldFound) 2375 { 2376 ConstantUnion *unionArray = new ConstantUnion[1]; 2377 unionArray->setIConst(i); 2378 TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation); 2379 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, dotLocation); 2380 indexedExpression->setType(*fields[i]->type()); 2381 } 2382 else 2383 { 2384 error(dotLocation, " no such field in interface block", fieldString.c_str()); 2385 recover(); 2386 indexedExpression = baseExpression; 2387 } 2388 } 2389 } 2390 else 2391 { 2392 if (shaderVersion < 300) 2393 { 2394 error(dotLocation, " field selection requires structure, vector, or matrix on left hand side", fieldString.c_str()); 2395 } 2396 else 2397 { 2398 error(dotLocation, " field selection requires structure, vector, matrix, or interface block on left hand side", fieldString.c_str()); 2399 } 2400 recover(); 2401 indexedExpression = baseExpression; 2402 } 2403 2404 return indexedExpression; 2405 } 2406 2407 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine) 2408 { 2409 TLayoutQualifier qualifier; 2410 2411 qualifier.location = -1; 2412 qualifier.matrixPacking = EmpUnspecified; 2413 qualifier.blockStorage = EbsUnspecified; 2414 2415 if (qualifierType == "shared") 2416 { 2417 qualifier.blockStorage = EbsShared; 2418 } 2419 else if (qualifierType == "packed") 2420 { 2421 qualifier.blockStorage = EbsPacked; 2422 } 2423 else if (qualifierType == "std140") 2424 { 2425 qualifier.blockStorage = EbsStd140; 2426 } 2427 else if (qualifierType == "row_major") 2428 { 2429 qualifier.matrixPacking = EmpRowMajor; 2430 } 2431 else if (qualifierType == "column_major") 2432 { 2433 qualifier.matrixPacking = EmpColumnMajor; 2434 } 2435 else if (qualifierType == "location") 2436 { 2437 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument"); 2438 recover(); 2439 } 2440 else 2441 { 2442 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); 2443 recover(); 2444 } 2445 2446 return qualifier; 2447 } 2448 2449 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine) 2450 { 2451 TLayoutQualifier qualifier; 2452 2453 qualifier.location = -1; 2454 qualifier.matrixPacking = EmpUnspecified; 2455 qualifier.blockStorage = EbsUnspecified; 2456 2457 if (qualifierType != "location") 2458 { 2459 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments"); 2460 recover(); 2461 } 2462 else 2463 { 2464 // must check that location is non-negative 2465 if (intValue < 0) 2466 { 2467 error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative"); 2468 recover(); 2469 } 2470 else 2471 { 2472 qualifier.location = intValue; 2473 } 2474 } 2475 2476 return qualifier; 2477 } 2478 2479 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier) 2480 { 2481 TLayoutQualifier joinedQualifier = leftQualifier; 2482 2483 if (rightQualifier.location != -1) 2484 { 2485 joinedQualifier.location = rightQualifier.location; 2486 } 2487 if (rightQualifier.matrixPacking != EmpUnspecified) 2488 { 2489 joinedQualifier.matrixPacking = rightQualifier.matrixPacking; 2490 } 2491 if (rightQualifier.blockStorage != EbsUnspecified) 2492 { 2493 joinedQualifier.blockStorage = rightQualifier.blockStorage; 2494 } 2495 2496 return joinedQualifier; 2497 } 2498 2499 TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, 2500 const TSourceLoc &storageLoc, TQualifier storageQualifier) 2501 { 2502 TQualifier mergedQualifier = EvqSmoothIn; 2503 2504 if (storageQualifier == EvqFragmentIn) { 2505 if (interpolationQualifier == EvqSmooth) 2506 mergedQualifier = EvqSmoothIn; 2507 else if (interpolationQualifier == EvqFlat) 2508 mergedQualifier = EvqFlatIn; 2509 else UNREACHABLE(); 2510 } 2511 else if (storageQualifier == EvqCentroidIn) { 2512 if (interpolationQualifier == EvqSmooth) 2513 mergedQualifier = EvqCentroidIn; 2514 else if (interpolationQualifier == EvqFlat) 2515 mergedQualifier = EvqFlatIn; 2516 else UNREACHABLE(); 2517 } 2518 else if (storageQualifier == EvqVertexOut) { 2519 if (interpolationQualifier == EvqSmooth) 2520 mergedQualifier = EvqSmoothOut; 2521 else if (interpolationQualifier == EvqFlat) 2522 mergedQualifier = EvqFlatOut; 2523 else UNREACHABLE(); 2524 } 2525 else if (storageQualifier == EvqCentroidOut) { 2526 if (interpolationQualifier == EvqSmooth) 2527 mergedQualifier = EvqCentroidOut; 2528 else if (interpolationQualifier == EvqFlat) 2529 mergedQualifier = EvqFlatOut; 2530 else UNREACHABLE(); 2531 } 2532 else { 2533 error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString(interpolationQualifier)); 2534 recover(); 2535 2536 mergedQualifier = storageQualifier; 2537 } 2538 2539 TPublicType type; 2540 type.setBasic(EbtVoid, mergedQualifier, storageLoc); 2541 return type; 2542 } 2543 2544 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList) 2545 { 2546 if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier)) { 2547 recover(); 2548 } 2549 2550 for (unsigned int i = 0; i < fieldList->size(); ++i) { 2551 // 2552 // Careful not to replace already known aspects of type, like array-ness 2553 // 2554 TType* type = (*fieldList)[i]->type(); 2555 type->setBasicType(typeSpecifier.type); 2556 type->setPrimarySize(typeSpecifier.primarySize); 2557 type->setSecondarySize(typeSpecifier.secondarySize); 2558 type->setPrecision(typeSpecifier.precision); 2559 type->setQualifier(typeSpecifier.qualifier); 2560 type->setLayoutQualifier(typeSpecifier.layoutQualifier); 2561 2562 // don't allow arrays of arrays 2563 if (type->isArray()) { 2564 if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier)) 2565 recover(); 2566 } 2567 if (typeSpecifier.array) 2568 type->setArraySize(typeSpecifier.arraySize); 2569 if (typeSpecifier.userDef) { 2570 type->setStruct(typeSpecifier.userDef->getStruct()); 2571 } 2572 2573 if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i])) { 2574 recover(); 2575 } 2576 } 2577 2578 return fieldList; 2579 } 2580 2581 TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList) 2582 { 2583 TStructure* structure = new TStructure(structName, fieldList); 2584 TType* structureType = new TType(structure); 2585 2586 structure->setUniqueId(TSymbolTable::nextUniqueId()); 2587 2588 if (!structName->empty()) 2589 { 2590 if (reservedErrorCheck(nameLine, *structName)) 2591 { 2592 recover(); 2593 } 2594 TVariable* userTypeDef = new TVariable(structName, *structureType, true); 2595 if (!symbolTable.declare(*userTypeDef)) { 2596 error(nameLine, "redefinition", structName->c_str(), "struct"); 2597 recover(); 2598 } 2599 } 2600 2601 // ensure we do not specify any storage qualifiers on the struct members 2602 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++) 2603 { 2604 const TField &field = *(*fieldList)[typeListIndex]; 2605 const TQualifier qualifier = field.type()->getQualifier(); 2606 switch (qualifier) 2607 { 2608 case EvqGlobal: 2609 case EvqTemporary: 2610 break; 2611 default: 2612 error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier)); 2613 recover(); 2614 break; 2615 } 2616 } 2617 2618 TPublicType publicType; 2619 publicType.setBasic(EbtStruct, EvqTemporary, structLine); 2620 publicType.userDef = structureType; 2621 exitStructDeclaration(); 2622 2623 return publicType; 2624 } 2625 2626 // 2627 // Parse an array of strings using yyparse. 2628 // 2629 // Returns 0 for success. 2630 // 2631 int PaParseStrings(size_t count, const char* const string[], const int length[], 2632 TParseContext* context) { 2633 if ((count == 0) || (string == NULL)) 2634 return 1; 2635 2636 if (glslang_initialize(context)) 2637 return 1; 2638 2639 int error = glslang_scan(count, string, length, context); 2640 if (!error) 2641 error = glslang_parse(context); 2642 2643 glslang_finalize(context); 2644 2645 return (error == 0) && (context->numErrors() == 0) ? 0 : 1; 2646 } 2647 2648 2649 2650