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/ParseContext.h" 8 9 #include <stdarg.h> 10 #include <stdio.h> 11 12 #include "compiler/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 matSize, 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 >= matSize || fields.col >= matSize) { 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 return lValueErrorCheck(line, op, binaryNode->getLeft()); 281 case EOpVectorSwizzle: 282 errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); 283 if (!errorReturn) { 284 int offset[4] = {0,0,0,0}; 285 286 TIntermTyped* rightNode = binaryNode->getRight(); 287 TIntermAggregate *aggrNode = rightNode->getAsAggregate(); 288 289 for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 290 p != aggrNode->getSequence().end(); p++) { 291 int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); 292 offset[value]++; 293 if (offset[value] > 1) { 294 error(line, " l-value of swizzle cannot have duplicate components", op); 295 296 return true; 297 } 298 } 299 } 300 301 return errorReturn; 302 default: 303 break; 304 } 305 error(line, " l-value required", op); 306 307 return true; 308 } 309 310 311 const char* symbol = 0; 312 if (symNode != 0) 313 symbol = symNode->getSymbol().c_str(); 314 315 const char* message = 0; 316 switch (node->getQualifier()) { 317 case EvqConst: message = "can't modify a const"; break; 318 case EvqConstReadOnly: message = "can't modify a const"; break; 319 case EvqAttribute: message = "can't modify an attribute"; break; 320 case EvqUniform: message = "can't modify a uniform"; break; 321 case EvqVaryingIn: message = "can't modify a varying"; break; 322 case EvqFragCoord: message = "can't modify gl_FragCoord"; break; 323 case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; 324 case EvqPointCoord: message = "can't modify gl_PointCoord"; break; 325 default: 326 327 // 328 // Type that can't be written to? 329 // 330 switch (node->getBasicType()) { 331 case EbtSampler2D: 332 case EbtSamplerCube: 333 message = "can't modify a sampler"; 334 break; 335 case EbtVoid: 336 message = "can't modify void"; 337 break; 338 default: 339 break; 340 } 341 } 342 343 if (message == 0 && binaryNode == 0 && symNode == 0) { 344 error(line, " l-value required", op); 345 346 return true; 347 } 348 349 350 // 351 // Everything else is okay, no error. 352 // 353 if (message == 0) 354 return false; 355 356 // 357 // If we get here, we have an error and a message. 358 // 359 if (symNode) { 360 std::stringstream extraInfoStream; 361 extraInfoStream << "\"" << symbol << "\" (" << message << ")"; 362 std::string extraInfo = extraInfoStream.str(); 363 error(line, " l-value required", op, extraInfo.c_str()); 364 } 365 else { 366 std::stringstream extraInfoStream; 367 extraInfoStream << "(" << message << ")"; 368 std::string extraInfo = extraInfoStream.str(); 369 error(line, " l-value required", op, extraInfo.c_str()); 370 } 371 372 return true; 373 } 374 375 // 376 // Both test, and if necessary spit out an error, to see if the node is really 377 // a constant. 378 // 379 // Returns true if the was an error. 380 // 381 bool TParseContext::constErrorCheck(TIntermTyped* node) 382 { 383 if (node->getQualifier() == EvqConst) 384 return false; 385 386 error(node->getLine(), "constant expression required", ""); 387 388 return true; 389 } 390 391 // 392 // Both test, and if necessary spit out an error, to see if the node is really 393 // an integer. 394 // 395 // Returns true if the was an error. 396 // 397 bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) 398 { 399 if (node->getBasicType() == EbtInt && node->getNominalSize() == 1) 400 return false; 401 402 error(node->getLine(), "integer expression required", token); 403 404 return true; 405 } 406 407 // 408 // Both test, and if necessary spit out an error, to see if we are currently 409 // globally scoped. 410 // 411 // Returns true if the was an error. 412 // 413 bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token) 414 { 415 if (global) 416 return false; 417 418 error(line, "only allowed at global scope", token); 419 420 return true; 421 } 422 423 // 424 // For now, keep it simple: if it starts "gl_", it's reserved, independent 425 // of scope. Except, if the symbol table is at the built-in push-level, 426 // which is when we are parsing built-ins. 427 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a 428 // webgl shader. 429 // 430 // Returns true if there was an error. 431 // 432 bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier) 433 { 434 static const char* reservedErrMsg = "reserved built-in name"; 435 if (!symbolTable.atBuiltInLevel()) { 436 if (identifier.compare(0, 3, "gl_") == 0) { 437 error(line, reservedErrMsg, "gl_"); 438 return true; 439 } 440 if (isWebGLBasedSpec(shaderSpec)) { 441 if (identifier.compare(0, 6, "webgl_") == 0) { 442 error(line, reservedErrMsg, "webgl_"); 443 return true; 444 } 445 if (identifier.compare(0, 7, "_webgl_") == 0) { 446 error(line, reservedErrMsg, "_webgl_"); 447 return true; 448 } 449 if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) { 450 error(line, reservedErrMsg, "css_"); 451 return true; 452 } 453 } 454 if (identifier.find("__") != TString::npos) { 455 error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str()); 456 return true; 457 } 458 } 459 460 return false; 461 } 462 463 // 464 // Make sure there is enough data provided to the constructor to build 465 // something of the type of the constructor. Also returns the type of 466 // the constructor. 467 // 468 // Returns true if there was an error in construction. 469 // 470 bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type) 471 { 472 *type = function.getReturnType(); 473 474 bool constructingMatrix = false; 475 switch(op) { 476 case EOpConstructMat2: 477 case EOpConstructMat3: 478 case EOpConstructMat4: 479 constructingMatrix = true; 480 break; 481 default: 482 break; 483 } 484 485 // 486 // Note: It's okay to have too many components available, but not okay to have unused 487 // arguments. 'full' will go to true when enough args have been seen. If we loop 488 // again, there is an extra argument, so 'overfull' will become true. 489 // 490 491 size_t size = 0; 492 bool constType = true; 493 bool full = false; 494 bool overFull = false; 495 bool matrixInMatrix = false; 496 bool arrayArg = false; 497 for (size_t i = 0; i < function.getParamCount(); ++i) { 498 const TParameter& param = function.getParam(i); 499 size += param.type->getObjectSize(); 500 501 if (constructingMatrix && param.type->isMatrix()) 502 matrixInMatrix = true; 503 if (full) 504 overFull = true; 505 if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) 506 full = true; 507 if (param.type->getQualifier() != EvqConst) 508 constType = false; 509 if (param.type->isArray()) 510 arrayArg = true; 511 } 512 513 if (constType) 514 type->setQualifier(EvqConst); 515 516 if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) { 517 error(line, "array constructor needs one argument per array element", "constructor"); 518 return true; 519 } 520 521 if (arrayArg && op != EOpConstructStruct) { 522 error(line, "constructing from a non-dereferenced array", "constructor"); 523 return true; 524 } 525 526 if (matrixInMatrix && !type->isArray()) { 527 if (function.getParamCount() != 1) { 528 error(line, "constructing matrix from matrix can only take one argument", "constructor"); 529 return true; 530 } 531 } 532 533 if (overFull) { 534 error(line, "too many arguments", "constructor"); 535 return true; 536 } 537 538 if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) { 539 error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); 540 return true; 541 } 542 543 if (!type->isMatrix() || !matrixInMatrix) { 544 if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || 545 (op == EOpConstructStruct && size < type->getObjectSize())) { 546 error(line, "not enough data provided for construction", "constructor"); 547 return true; 548 } 549 } 550 551 TIntermTyped *typed = node ? node->getAsTyped() : 0; 552 if (typed == 0) { 553 error(line, "constructor argument does not have a type", "constructor"); 554 return true; 555 } 556 if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { 557 error(line, "cannot convert a sampler", "constructor"); 558 return true; 559 } 560 if (typed->getBasicType() == EbtVoid) { 561 error(line, "cannot convert a void", "constructor"); 562 return true; 563 } 564 565 return false; 566 } 567 568 // This function checks to see if a void variable has been declared and raise an error message for such a case 569 // 570 // returns true in case of an error 571 // 572 bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType) 573 { 574 if (pubType.type == EbtVoid) { 575 error(line, "illegal use of type 'void'", identifier.c_str()); 576 return true; 577 } 578 579 return false; 580 } 581 582 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not 583 // 584 // returns true in case of an error 585 // 586 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type) 587 { 588 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { 589 error(line, "boolean expression expected", ""); 590 return true; 591 } 592 593 return false; 594 } 595 596 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not 597 // 598 // returns true in case of an error 599 // 600 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) 601 { 602 if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { 603 error(line, "boolean expression expected", ""); 604 return true; 605 } 606 607 return false; 608 } 609 610 bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason) 611 { 612 if (pType.type == EbtStruct) { 613 if (containsSampler(*pType.userDef)) { 614 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); 615 616 return true; 617 } 618 619 return false; 620 } else if (IsSampler(pType.type)) { 621 error(line, reason, getBasicString(pType.type)); 622 623 return true; 624 } 625 626 return false; 627 } 628 629 bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) 630 { 631 if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && 632 pType.type == EbtStruct) { 633 error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); 634 635 return true; 636 } 637 638 if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) 639 return true; 640 641 return false; 642 } 643 644 bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) 645 { 646 if ((qualifier == EvqOut || qualifier == EvqInOut) && 647 type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { 648 error(line, "samplers cannot be output parameters", type.getBasicString()); 649 return true; 650 } 651 652 return false; 653 } 654 655 bool TParseContext::containsSampler(TType& type) 656 { 657 if (IsSampler(type.getBasicType())) 658 return true; 659 660 if (type.getBasicType() == EbtStruct) { 661 const TFieldList& fields = type.getStruct()->fields(); 662 for (unsigned int i = 0; i < fields.size(); ++i) { 663 if (containsSampler(*fields[i]->type())) 664 return true; 665 } 666 } 667 668 return false; 669 } 670 671 // 672 // Do size checking for an array type's size. 673 // 674 // Returns true if there was an error. 675 // 676 bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) 677 { 678 TIntermConstantUnion* constant = expr->getAsConstantUnion(); 679 if (constant == 0 || constant->getBasicType() != EbtInt) { 680 error(line, "array size must be a constant integer expression", ""); 681 return true; 682 } 683 684 size = constant->getIConst(0); 685 686 if (size <= 0) { 687 error(line, "array size must be a positive integer", ""); 688 size = 1; 689 return true; 690 } 691 692 return false; 693 } 694 695 // 696 // See if this qualifier can be an array. 697 // 698 // Returns true if there is an error. 699 // 700 bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) 701 { 702 if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { 703 error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); 704 return true; 705 } 706 707 return false; 708 } 709 710 // 711 // See if this type can be an array. 712 // 713 // Returns true if there is an error. 714 // 715 bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type) 716 { 717 // 718 // Can the type be an array? 719 // 720 if (type.array) { 721 error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str()); 722 return true; 723 } 724 725 return false; 726 } 727 728 // 729 // Do all the semantic checking for declaring an array, with and 730 // without a size, and make the right changes to the symbol table. 731 // 732 // size == 0 means no specified size. 733 // 734 // Returns true if there was an error. 735 // 736 bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable) 737 { 738 // 739 // Don't check for reserved word use until after we know it's not in the symbol table, 740 // because reserved arrays can be redeclared. 741 // 742 743 bool builtIn = false; 744 bool sameScope = false; 745 TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope); 746 if (symbol == 0 || !sameScope) { 747 if (reservedErrorCheck(line, identifier)) 748 return true; 749 750 variable = new TVariable(&identifier, TType(type)); 751 752 if (type.arraySize) 753 variable->getType().setArraySize(type.arraySize); 754 755 if (! symbolTable.insert(*variable)) { 756 delete variable; 757 error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str()); 758 return true; 759 } 760 } else { 761 if (! symbol->isVariable()) { 762 error(line, "variable expected", identifier.c_str()); 763 return true; 764 } 765 766 variable = static_cast<TVariable*>(symbol); 767 if (! variable->getType().isArray()) { 768 error(line, "redeclaring non-array as array", identifier.c_str()); 769 return true; 770 } 771 if (variable->getType().getArraySize() > 0) { 772 error(line, "redeclaration of array with size", identifier.c_str()); 773 return true; 774 } 775 776 if (! variable->getType().sameElementType(TType(type))) { 777 error(line, "redeclaration of array with a different type", identifier.c_str()); 778 return true; 779 } 780 781 if (type.arraySize) 782 variable->getType().setArraySize(type.arraySize); 783 } 784 785 if (voidErrorCheck(line, identifier, type)) 786 return true; 787 788 return false; 789 } 790 791 // 792 // Enforce non-initializer type/qualifier rules. 793 // 794 // Returns true if there was an error. 795 // 796 bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) 797 { 798 if (type.qualifier == EvqConst) 799 { 800 // Make the qualifier make sense. 801 type.qualifier = EvqTemporary; 802 803 if (array) 804 { 805 error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str()); 806 } 807 else if (type.isStructureContainingArrays()) 808 { 809 error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str()); 810 } 811 else 812 { 813 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); 814 } 815 816 return true; 817 } 818 819 return false; 820 } 821 822 // 823 // Do semantic checking for a variable declaration that has no initializer, 824 // and update the symbol table. 825 // 826 // Returns true if there was an error. 827 // 828 bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) 829 { 830 if (reservedErrorCheck(line, identifier)) 831 recover(); 832 833 variable = new TVariable(&identifier, TType(type)); 834 835 if (! symbolTable.insert(*variable)) { 836 error(line, "redefinition", variable->getName().c_str()); 837 delete variable; 838 variable = 0; 839 return true; 840 } 841 842 if (voidErrorCheck(line, identifier, type)) 843 return true; 844 845 return false; 846 } 847 848 bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) 849 { 850 if (qualifier != EvqConst && qualifier != EvqTemporary) { 851 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); 852 return true; 853 } 854 if (qualifier == EvqConst && paramQualifier != EvqIn) { 855 error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); 856 return true; 857 } 858 859 if (qualifier == EvqConst) 860 type->setQualifier(EvqConstReadOnly); 861 else 862 type->setQualifier(paramQualifier); 863 864 return false; 865 } 866 867 bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) 868 { 869 const TExtensionBehavior& extBehavior = extensionBehavior(); 870 TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); 871 if (iter == extBehavior.end()) { 872 error(line, "extension", extension.c_str(), "is not supported"); 873 return true; 874 } 875 // In GLSL ES, an extension's default behavior is "disable". 876 if (iter->second == EBhDisable || iter->second == EBhUndefined) { 877 error(line, "extension", extension.c_str(), "is disabled"); 878 return true; 879 } 880 if (iter->second == EBhWarn) { 881 warning(line, "extension", extension.c_str(), "is being used"); 882 return false; 883 } 884 885 return false; 886 } 887 888 bool TParseContext::supportsExtension(const char* extension) 889 { 890 const TExtensionBehavior& extbehavior = extensionBehavior(); 891 TExtensionBehavior::const_iterator iter = extbehavior.find(extension); 892 return (iter != extbehavior.end()); 893 } 894 895 bool TParseContext::isExtensionEnabled(const char* extension) const 896 { 897 const TExtensionBehavior& extbehavior = extensionBehavior(); 898 TExtensionBehavior::const_iterator iter = extbehavior.find(extension); 899 900 if (iter == extbehavior.end()) 901 { 902 return false; 903 } 904 905 return (iter->second == EBhEnable || iter->second == EBhRequire); 906 } 907 908 ///////////////////////////////////////////////////////////////////////////////// 909 // 910 // Non-Errors. 911 // 912 ///////////////////////////////////////////////////////////////////////////////// 913 914 // 915 // Look up a function name in the symbol table, and make sure it is a function. 916 // 917 // Return the function symbol if found, otherwise 0. 918 // 919 const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) 920 { 921 // First find by unmangled name to check whether the function name has been 922 // hidden by a variable name or struct typename. 923 // If a function is found, check for one with a matching argument list. 924 const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); 925 if (symbol == 0 || symbol->isFunction()) { 926 symbol = symbolTable.find(call->getMangledName(), builtIn); 927 } 928 929 if (symbol == 0) { 930 error(line, "no matching overloaded function found", call->getName().c_str()); 931 return 0; 932 } 933 934 if (!symbol->isFunction()) { 935 error(line, "function name expected", call->getName().c_str()); 936 return 0; 937 } 938 939 return static_cast<const TFunction*>(symbol); 940 } 941 942 // 943 // Initializers show up in several places in the grammar. Have one set of 944 // code to handle them here. 945 // 946 bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, 947 TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) 948 { 949 TType type = TType(pType); 950 951 if (variable == 0) { 952 if (reservedErrorCheck(line, identifier)) 953 return true; 954 955 if (voidErrorCheck(line, identifier, pType)) 956 return true; 957 958 // 959 // add variable to symbol table 960 // 961 variable = new TVariable(&identifier, type); 962 if (! symbolTable.insert(*variable)) { 963 error(line, "redefinition", variable->getName().c_str()); 964 return true; 965 // don't delete variable, it's used by error recovery, and the pool 966 // pop will take care of the memory 967 } 968 } 969 970 // 971 // identifier must be of type constant, a global, or a temporary 972 // 973 TQualifier qualifier = variable->getType().getQualifier(); 974 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) { 975 error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); 976 return true; 977 } 978 // 979 // test for and propagate constant 980 // 981 982 if (qualifier == EvqConst) { 983 if (qualifier != initializer->getType().getQualifier()) { 984 std::stringstream extraInfoStream; 985 extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; 986 std::string extraInfo = extraInfoStream.str(); 987 error(line, " assigning non-constant to", "=", extraInfo.c_str()); 988 variable->getType().setQualifier(EvqTemporary); 989 return true; 990 } 991 if (type != initializer->getType()) { 992 error(line, " non-matching types for const initializer ", 993 variable->getType().getQualifierString()); 994 variable->getType().setQualifier(EvqTemporary); 995 return true; 996 } 997 if (initializer->getAsConstantUnion()) { 998 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); 999 } else if (initializer->getAsSymbolNode()) { 1000 const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); 1001 const TVariable* tVar = static_cast<const TVariable*>(symbol); 1002 1003 ConstantUnion* constArray = tVar->getConstPointer(); 1004 variable->shareConstPointer(constArray); 1005 } else { 1006 std::stringstream extraInfoStream; 1007 extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; 1008 std::string extraInfo = extraInfoStream.str(); 1009 error(line, " cannot assign to", "=", extraInfo.c_str()); 1010 variable->getType().setQualifier(EvqTemporary); 1011 return true; 1012 } 1013 } 1014 1015 if (qualifier != EvqConst) { 1016 TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); 1017 intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); 1018 if (intermNode == 0) { 1019 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); 1020 return true; 1021 } 1022 } else 1023 intermNode = 0; 1024 1025 return false; 1026 } 1027 1028 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) 1029 { 1030 ASSERT(aggrNode != NULL); 1031 if (!aggrNode->isConstructor()) 1032 return false; 1033 1034 bool allConstant = true; 1035 1036 // check if all the child nodes are constants so that they can be inserted into 1037 // the parent node 1038 TIntermSequence &sequence = aggrNode->getSequence() ; 1039 for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { 1040 if (!(*p)->getAsTyped()->getAsConstantUnion()) 1041 return false; 1042 } 1043 1044 return allConstant; 1045 } 1046 1047 // This function is used to test for the correctness of the parameters passed to various constructor functions 1048 // and also convert them to the right datatype if it is allowed and required. 1049 // 1050 // Returns 0 for an error or the constructed node (aggregate or typed) for no error. 1051 // 1052 TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) 1053 { 1054 if (node == 0) 1055 return 0; 1056 1057 TIntermAggregate* aggrNode = node->getAsAggregate(); 1058 1059 TFieldList::const_iterator memberFields; 1060 if (op == EOpConstructStruct) 1061 memberFields = type->getStruct()->fields().begin(); 1062 1063 TType elementType = *type; 1064 if (type->isArray()) 1065 elementType.clearArrayness(); 1066 1067 bool singleArg; 1068 if (aggrNode) { 1069 if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) 1070 singleArg = true; 1071 else 1072 singleArg = false; 1073 } else 1074 singleArg = true; 1075 1076 TIntermTyped *newNode; 1077 if (singleArg) { 1078 // If structure constructor or array constructor is being called 1079 // for only one parameter inside the structure, we need to call constructStruct function once. 1080 if (type->isArray()) 1081 newNode = constructStruct(node, &elementType, 1, node->getLine(), false); 1082 else if (op == EOpConstructStruct) 1083 newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); 1084 else 1085 newNode = constructBuiltIn(type, op, node, node->getLine(), false); 1086 1087 if (newNode && newNode->getAsAggregate()) { 1088 TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); 1089 if (constConstructor) 1090 return constConstructor; 1091 } 1092 1093 return newNode; 1094 } 1095 1096 // 1097 // Handle list of arguments. 1098 // 1099 TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor 1100 // if the structure constructor contains more than one parameter, then construct 1101 // each parameter 1102 1103 int paramCount = 0; // keeps a track of the constructor parameter number being checked 1104 1105 // for each parameter to the constructor call, check to see if the right type is passed or convert them 1106 // to the right type if possible (and allowed). 1107 // for structure constructors, just check if the right type is passed, no conversion is allowed. 1108 1109 for (TIntermSequence::iterator p = sequenceVector.begin(); 1110 p != sequenceVector.end(); p++, paramCount++) { 1111 if (type->isArray()) 1112 newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); 1113 else if (op == EOpConstructStruct) 1114 newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); 1115 else 1116 newNode = constructBuiltIn(type, op, *p, node->getLine(), true); 1117 1118 if (newNode) { 1119 *p = newNode; 1120 } 1121 } 1122 1123 TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); 1124 TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); 1125 if (constConstructor) 1126 return constConstructor; 1127 1128 return constructor; 1129 } 1130 1131 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) 1132 { 1133 bool canBeFolded = areAllChildConst(aggrNode); 1134 aggrNode->setType(type); 1135 if (canBeFolded) { 1136 bool returnVal = false; 1137 ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; 1138 if (aggrNode->getSequence().size() == 1) { 1139 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true); 1140 } 1141 else { 1142 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type); 1143 } 1144 if (returnVal) 1145 return 0; 1146 1147 return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); 1148 } 1149 1150 return 0; 1151 } 1152 1153 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value 1154 // for the parameter to the constructor (passed to this function). Essentially, it converts 1155 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 1156 // float, then float is converted to int. 1157 // 1158 // Returns 0 for an error or the constructed node. 1159 // 1160 TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) 1161 { 1162 TIntermTyped* newNode; 1163 TOperator basicOp; 1164 1165 // 1166 // First, convert types as needed. 1167 // 1168 switch (op) { 1169 case EOpConstructVec2: 1170 case EOpConstructVec3: 1171 case EOpConstructVec4: 1172 case EOpConstructMat2: 1173 case EOpConstructMat3: 1174 case EOpConstructMat4: 1175 case EOpConstructFloat: 1176 basicOp = EOpConstructFloat; 1177 break; 1178 1179 case EOpConstructIVec2: 1180 case EOpConstructIVec3: 1181 case EOpConstructIVec4: 1182 case EOpConstructInt: 1183 basicOp = EOpConstructInt; 1184 break; 1185 1186 case EOpConstructBVec2: 1187 case EOpConstructBVec3: 1188 case EOpConstructBVec4: 1189 case EOpConstructBool: 1190 basicOp = EOpConstructBool; 1191 break; 1192 1193 default: 1194 error(line, "unsupported construction", ""); 1195 recover(); 1196 1197 return 0; 1198 } 1199 newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); 1200 if (newNode == 0) { 1201 error(line, "can't convert", "constructor"); 1202 return 0; 1203 } 1204 1205 // 1206 // Now, if there still isn't an operation to do the construction, and we need one, add one. 1207 // 1208 1209 // Otherwise, skip out early. 1210 if (subset || (newNode != node && newNode->getType() == *type)) 1211 return newNode; 1212 1213 // setAggregateOperator will insert a new node for the constructor, as needed. 1214 return intermediate.setAggregateOperator(newNode, op, line); 1215 } 1216 1217 // This function tests for the type of the parameters to the structures constructors. Raises 1218 // an error message if the expected type does not match the parameter passed to the constructor. 1219 // 1220 // Returns 0 for an error or the input node itself if the expected and the given parameter types match. 1221 // 1222 TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) 1223 { 1224 if (*type == node->getAsTyped()->getType()) { 1225 if (subset) 1226 return node->getAsTyped(); 1227 else 1228 return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); 1229 } else { 1230 std::stringstream extraInfoStream; 1231 extraInfoStream << "cannot convert parameter " << paramCount 1232 << " from '" << node->getAsTyped()->getType().getBasicString() 1233 << "' to '" << type->getBasicString() << "'"; 1234 std::string extraInfo = extraInfoStream.str(); 1235 error(line, "", "constructor", extraInfo.c_str()); 1236 recover(); 1237 } 1238 1239 return 0; 1240 } 1241 1242 // 1243 // This function returns the tree representation for the vector field(s) being accessed from contant vector. 1244 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is 1245 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol 1246 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 1247 // a constant matrix. 1248 // 1249 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) 1250 { 1251 TIntermTyped* typedNode; 1252 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1253 1254 ConstantUnion *unionArray; 1255 if (tempConstantNode) { 1256 unionArray = tempConstantNode->getUnionArrayPointer(); 1257 1258 if (!unionArray) { 1259 return node; 1260 } 1261 } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error 1262 error(line, "Cannot offset into the vector", "Error"); 1263 recover(); 1264 1265 return 0; 1266 } 1267 1268 ConstantUnion* constArray = new ConstantUnion[fields.num]; 1269 1270 for (int i = 0; i < fields.num; i++) { 1271 if (fields.offsets[i] >= node->getType().getNominalSize()) { 1272 std::stringstream extraInfoStream; 1273 extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; 1274 std::string extraInfo = extraInfoStream.str(); 1275 error(line, "", "[", extraInfo.c_str()); 1276 recover(); 1277 fields.offsets[i] = 0; 1278 } 1279 1280 constArray[i] = unionArray[fields.offsets[i]]; 1281 1282 } 1283 typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); 1284 return typedNode; 1285 } 1286 1287 // 1288 // This function returns the column being accessed from a constant matrix. The values are retrieved from 1289 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 1290 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 1291 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) 1292 // 1293 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) 1294 { 1295 TIntermTyped* typedNode; 1296 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1297 1298 if (index >= node->getType().getNominalSize()) { 1299 std::stringstream extraInfoStream; 1300 extraInfoStream << "matrix field selection out of range '" << index << "'"; 1301 std::string extraInfo = extraInfoStream.str(); 1302 error(line, "", "[", extraInfo.c_str()); 1303 recover(); 1304 index = 0; 1305 } 1306 1307 if (tempConstantNode) { 1308 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); 1309 int size = tempConstantNode->getType().getNominalSize(); 1310 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); 1311 } else { 1312 error(line, "Cannot offset into the matrix", "Error"); 1313 recover(); 1314 1315 return 0; 1316 } 1317 1318 return typedNode; 1319 } 1320 1321 1322 // 1323 // This function returns an element of an array accessed from a constant array. The values are retrieved from 1324 // the symbol table and parse-tree is built for the type of the element. The input 1325 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a 1326 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) 1327 // 1328 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) 1329 { 1330 TIntermTyped* typedNode; 1331 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1332 TType arrayElementType = node->getType(); 1333 arrayElementType.clearArrayness(); 1334 1335 if (index >= node->getType().getArraySize()) { 1336 std::stringstream extraInfoStream; 1337 extraInfoStream << "array field selection out of range '" << index << "'"; 1338 std::string extraInfo = extraInfoStream.str(); 1339 error(line, "", "[", extraInfo.c_str()); 1340 recover(); 1341 index = 0; 1342 } 1343 1344 if (tempConstantNode) { 1345 size_t arrayElementSize = arrayElementType.getObjectSize(); 1346 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); 1347 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); 1348 } else { 1349 error(line, "Cannot offset into the array", "Error"); 1350 recover(); 1351 1352 return 0; 1353 } 1354 1355 return typedNode; 1356 } 1357 1358 1359 // 1360 // This function returns the value of a particular field inside a constant structure from the symbol table. 1361 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr 1362 // function and returns the parse-tree with the values of the embedded/nested struct. 1363 // 1364 TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) 1365 { 1366 const TFieldList& fields = node->getType().getStruct()->fields(); 1367 1368 size_t instanceSize = 0; 1369 for (size_t index = 0; index < fields.size(); ++index) { 1370 if (fields[index]->name() == identifier) { 1371 break; 1372 } else { 1373 instanceSize += fields[index]->type()->getObjectSize(); 1374 } 1375 } 1376 1377 TIntermTyped* typedNode = 0; 1378 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1379 if (tempConstantNode) { 1380 ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); 1381 1382 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function 1383 } else { 1384 error(line, "Cannot offset into the structure", "Error"); 1385 recover(); 1386 1387 return 0; 1388 } 1389 1390 return typedNode; 1391 } 1392 1393 bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) 1394 { 1395 ++structNestingLevel; 1396 1397 // Embedded structure definitions are not supported per GLSL ES spec. 1398 // They aren't allowed in GLSL either, but we need to detect this here 1399 // so we don't rely on the GLSL compiler to catch it. 1400 if (structNestingLevel > 1) { 1401 error(line, "", "Embedded struct definitions are not allowed"); 1402 return true; 1403 } 1404 1405 return false; 1406 } 1407 1408 void TParseContext::exitStructDeclaration() 1409 { 1410 --structNestingLevel; 1411 } 1412 1413 namespace { 1414 1415 const int kWebGLMaxStructNesting = 4; 1416 1417 } // namespace 1418 1419 bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) 1420 { 1421 if (!isWebGLBasedSpec(shaderSpec)) { 1422 return false; 1423 } 1424 1425 if (field.type()->getBasicType() != EbtStruct) { 1426 return false; 1427 } 1428 1429 // We're already inside a structure definition at this point, so add 1430 // one to the field's struct nesting. 1431 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { 1432 std::stringstream reasonStream; 1433 reasonStream << "Reference of struct type " 1434 << field.type()->getStruct()->name().c_str() 1435 << " exceeds maximum allowed nesting level of " 1436 << kWebGLMaxStructNesting; 1437 std::string reason = reasonStream.str(); 1438 error(line, reason.c_str(), field.name().c_str(), ""); 1439 return true; 1440 } 1441 1442 return false; 1443 } 1444 1445 // 1446 // Parse an array index expression 1447 // 1448 TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) 1449 { 1450 TIntermTyped *indexedExpression = NULL; 1451 1452 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) 1453 { 1454 if (baseExpression->getAsSymbolNode()) 1455 { 1456 error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); 1457 } 1458 else 1459 { 1460 error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); 1461 } 1462 recover(); 1463 } 1464 1465 if (indexExpression->getQualifier() == EvqConst) 1466 { 1467 int index = indexExpression->getAsConstantUnion()->getIConst(0); 1468 if (index < 0) 1469 { 1470 std::stringstream infoStream; 1471 infoStream << index; 1472 std::string info = infoStream.str(); 1473 error(location, "negative index", info.c_str()); 1474 recover(); 1475 index = 0; 1476 } 1477 if (baseExpression->getType().getQualifier() == EvqConst) 1478 { 1479 if (baseExpression->isArray()) 1480 { 1481 // constant folding for arrays 1482 indexedExpression = addConstArrayNode(index, baseExpression, location); 1483 } 1484 else if (baseExpression->isVector()) 1485 { 1486 // constant folding for vectors 1487 TVectorFields fields; 1488 fields.num = 1; 1489 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array 1490 indexedExpression = addConstVectorNode(fields, baseExpression, location); 1491 } 1492 else if (baseExpression->isMatrix()) 1493 { 1494 // constant folding for matrices 1495 indexedExpression = addConstMatrixNode(index, baseExpression, location); 1496 } 1497 } 1498 else 1499 { 1500 if (baseExpression->isArray()) 1501 { 1502 if (index >= baseExpression->getType().getArraySize()) 1503 { 1504 std::stringstream extraInfoStream; 1505 extraInfoStream << "array index out of range '" << index << "'"; 1506 std::string extraInfo = extraInfoStream.str(); 1507 error(location, "", "[", extraInfo.c_str()); 1508 recover(); 1509 index = baseExpression->getType().getArraySize() - 1; 1510 } 1511 else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) 1512 { 1513 error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); 1514 recover(); 1515 index = 0; 1516 } 1517 } 1518 else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) 1519 { 1520 std::stringstream extraInfoStream; 1521 extraInfoStream << "field selection out of range '" << index << "'"; 1522 std::string extraInfo = extraInfoStream.str(); 1523 error(location, "", "[", extraInfo.c_str()); 1524 recover(); 1525 index = baseExpression->getType().getNominalSize() - 1; 1526 } 1527 1528 indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); 1529 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); 1530 } 1531 } 1532 else 1533 { 1534 indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); 1535 } 1536 1537 if (indexedExpression == 0) 1538 { 1539 ConstantUnion *unionArray = new ConstantUnion[1]; 1540 unionArray->setFConst(0.0f); 1541 indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); 1542 } 1543 else if (baseExpression->isArray()) 1544 { 1545 const TType &baseType = baseExpression->getType(); 1546 if (baseType.getStruct()) 1547 { 1548 TType copyOfType(baseType.getStruct()); 1549 indexedExpression->setType(copyOfType); 1550 } 1551 else 1552 { 1553 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix())); 1554 } 1555 1556 if (baseExpression->getType().getQualifier() == EvqConst) 1557 { 1558 indexedExpression->getTypePointer()->setQualifier(EvqConst); 1559 } 1560 } 1561 else if (baseExpression->isMatrix()) 1562 { 1563 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; 1564 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize())); 1565 } 1566 else if (baseExpression->isVector()) 1567 { 1568 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; 1569 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); 1570 } 1571 else 1572 { 1573 indexedExpression->setType(baseExpression->getType()); 1574 } 1575 1576 return indexedExpression; 1577 } 1578 1579 // 1580 // Parse an array of strings using yyparse. 1581 // 1582 // Returns 0 for success. 1583 // 1584 int PaParseStrings(size_t count, const char* const string[], const int length[], 1585 TParseContext* context) { 1586 if ((count == 0) || (string == NULL)) 1587 return 1; 1588 1589 if (glslang_initialize(context)) 1590 return 1; 1591 1592 int error = glslang_scan(count, string, length, context); 1593 if (!error) 1594 error = glslang_parse(context); 1595 1596 glslang_finalize(context); 1597 1598 return (error == 0) && (context->numErrors() == 0) ? 0 : 1; 1599 } 1600 1601 1602 1603