1 // 2 // Copyright (c) 2002-2014 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 const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, 1022 const TString *name, 1023 const TSymbol *symbol) 1024 { 1025 const TVariable *variable = NULL; 1026 1027 if (!symbol) 1028 { 1029 error(location, "undeclared identifier", name->c_str()); 1030 recover(); 1031 } 1032 else if (!symbol->isVariable()) 1033 { 1034 error(location, "variable expected", name->c_str()); 1035 recover(); 1036 } 1037 else 1038 { 1039 variable = static_cast<const TVariable*>(symbol); 1040 1041 if (symbolTable.findBuiltIn(variable->getName(), shaderVersion) && 1042 !variable->getExtension().empty() && 1043 extensionErrorCheck(location, variable->getExtension())) 1044 { 1045 recover(); 1046 } 1047 } 1048 1049 if (!variable) 1050 { 1051 TType type(EbtFloat, EbpUndefined); 1052 TVariable *fakeVariable = new TVariable(name, type); 1053 symbolTable.declare(fakeVariable); 1054 variable = fakeVariable; 1055 } 1056 1057 return variable; 1058 } 1059 1060 // 1061 // Look up a function name in the symbol table, and make sure it is a function. 1062 // 1063 // Return the function symbol if found, otherwise 0. 1064 // 1065 const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn) 1066 { 1067 // First find by unmangled name to check whether the function name has been 1068 // hidden by a variable name or struct typename. 1069 // If a function is found, check for one with a matching argument list. 1070 const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn); 1071 if (symbol == 0 || symbol->isFunction()) { 1072 symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn); 1073 } 1074 1075 if (symbol == 0) { 1076 error(line, "no matching overloaded function found", call->getName().c_str()); 1077 return 0; 1078 } 1079 1080 if (!symbol->isFunction()) { 1081 error(line, "function name expected", call->getName().c_str()); 1082 return 0; 1083 } 1084 1085 return static_cast<const TFunction*>(symbol); 1086 } 1087 1088 // 1089 // Initializers show up in several places in the grammar. Have one set of 1090 // code to handle them here. 1091 // 1092 // Returns true on error, false if no error 1093 // 1094 bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, 1095 TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) 1096 { 1097 TType type = TType(pType); 1098 1099 if (variable == 0) { 1100 if (reservedErrorCheck(line, identifier)) 1101 return true; 1102 1103 if (voidErrorCheck(line, identifier, pType)) 1104 return true; 1105 1106 // 1107 // add variable to symbol table 1108 // 1109 variable = new TVariable(&identifier, type); 1110 if (! symbolTable.declare(variable)) { 1111 error(line, "redefinition", variable->getName().c_str()); 1112 return true; 1113 // don't delete variable, it's used by error recovery, and the pool 1114 // pop will take care of the memory 1115 } 1116 } 1117 1118 // 1119 // identifier must be of type constant, a global, or a temporary 1120 // 1121 TQualifier qualifier = variable->getType().getQualifier(); 1122 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) { 1123 error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); 1124 return true; 1125 } 1126 // 1127 // test for and propagate constant 1128 // 1129 1130 if (qualifier == EvqConst) { 1131 if (qualifier != initializer->getType().getQualifier()) { 1132 std::stringstream extraInfoStream; 1133 extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; 1134 std::string extraInfo = extraInfoStream.str(); 1135 error(line, " assigning non-constant to", "=", extraInfo.c_str()); 1136 variable->getType().setQualifier(EvqTemporary); 1137 return true; 1138 } 1139 if (type != initializer->getType()) { 1140 error(line, " non-matching types for const initializer ", 1141 variable->getType().getQualifierString()); 1142 variable->getType().setQualifier(EvqTemporary); 1143 return true; 1144 } 1145 if (initializer->getAsConstantUnion()) { 1146 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); 1147 } else if (initializer->getAsSymbolNode()) { 1148 const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0); 1149 const TVariable* tVar = static_cast<const TVariable*>(symbol); 1150 1151 ConstantUnion* constArray = tVar->getConstPointer(); 1152 variable->shareConstPointer(constArray); 1153 } else { 1154 std::stringstream extraInfoStream; 1155 extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; 1156 std::string extraInfo = extraInfoStream.str(); 1157 error(line, " cannot assign to", "=", extraInfo.c_str()); 1158 variable->getType().setQualifier(EvqTemporary); 1159 return true; 1160 } 1161 } 1162 1163 if (qualifier != EvqConst) { 1164 TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); 1165 intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); 1166 if (intermNode == 0) { 1167 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); 1168 return true; 1169 } 1170 } else 1171 intermNode = 0; 1172 1173 return false; 1174 } 1175 1176 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) 1177 { 1178 ASSERT(aggrNode != NULL); 1179 if (!aggrNode->isConstructor()) 1180 return false; 1181 1182 bool allConstant = true; 1183 1184 // check if all the child nodes are constants so that they can be inserted into 1185 // the parent node 1186 TIntermSequence *sequence = aggrNode->getSequence() ; 1187 for (TIntermSequence::iterator p = sequence->begin(); p != sequence->end(); ++p) { 1188 if (!(*p)->getAsTyped()->getAsConstantUnion()) 1189 return false; 1190 } 1191 1192 return allConstant; 1193 } 1194 1195 TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQualifier layoutQualifier, const TPublicType& typeSpecifier) 1196 { 1197 TPublicType returnType = typeSpecifier; 1198 returnType.qualifier = qualifier; 1199 returnType.layoutQualifier = layoutQualifier; 1200 1201 if (typeSpecifier.array) 1202 { 1203 error(typeSpecifier.line, "not supported", "first-class array"); 1204 recover(); 1205 returnType.setArray(false); 1206 } 1207 1208 if (shaderVersion < 300) 1209 { 1210 if (qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) 1211 { 1212 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); 1213 recover(); 1214 } 1215 1216 if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) && 1217 (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) 1218 { 1219 error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); 1220 recover(); 1221 } 1222 } 1223 else 1224 { 1225 switch (qualifier) 1226 { 1227 case EvqSmoothIn: 1228 case EvqSmoothOut: 1229 case EvqVertexOut: 1230 case EvqFragmentIn: 1231 case EvqCentroidOut: 1232 case EvqCentroidIn: 1233 if (typeSpecifier.type == EbtBool) 1234 { 1235 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier)); 1236 recover(); 1237 } 1238 if (typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt) 1239 { 1240 error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier)); 1241 recover(); 1242 } 1243 break; 1244 1245 case EvqVertexIn: 1246 case EvqFragmentOut: 1247 case EvqFlatIn: 1248 case EvqFlatOut: 1249 if (typeSpecifier.type == EbtBool) 1250 { 1251 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier)); 1252 recover(); 1253 } 1254 break; 1255 1256 default: break; 1257 } 1258 } 1259 1260 return returnType; 1261 } 1262 1263 TIntermAggregate* TParseContext::parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier) 1264 { 1265 TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); 1266 TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation); 1267 1268 if (identifier != "") 1269 { 1270 if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) 1271 recover(); 1272 1273 // this error check can mutate the type 1274 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false)) 1275 recover(); 1276 1277 TVariable* variable = 0; 1278 1279 if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable)) 1280 recover(); 1281 1282 if (variable && symbol) 1283 { 1284 symbol->setId(variable->getUniqueId()); 1285 } 1286 } 1287 1288 return aggregate; 1289 } 1290 1291 TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression) 1292 { 1293 if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) 1294 recover(); 1295 1296 // this error check can mutate the type 1297 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true)) 1298 recover(); 1299 1300 if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType)) 1301 { 1302 recover(); 1303 } 1304 1305 TPublicType arrayType = publicType; 1306 1307 int size; 1308 if (arraySizeErrorCheck(identifierLocation, indexExpression, size)) 1309 { 1310 recover(); 1311 } 1312 else 1313 { 1314 arrayType.setArray(true, size); 1315 } 1316 1317 TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(arrayType), identifierLocation); 1318 TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation); 1319 TVariable* variable = 0; 1320 1321 if (arrayErrorCheck(identifierLocation, identifier, arrayType, variable)) 1322 recover(); 1323 1324 if (variable && symbol) 1325 { 1326 symbol->setId(variable->getUniqueId()); 1327 } 1328 1329 return aggregate; 1330 } 1331 1332 TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer) 1333 { 1334 if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) 1335 recover(); 1336 1337 TIntermNode* intermNode; 1338 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode)) 1339 { 1340 // 1341 // Build intermediate representation 1342 // 1343 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : NULL; 1344 } 1345 else 1346 { 1347 recover(); 1348 return NULL; 1349 } 1350 } 1351 1352 TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc, 1353 const TSourceLoc &identifierLoc, 1354 const TString *identifier, 1355 const TSymbol *symbol) 1356 { 1357 // invariant declaration 1358 if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying")) 1359 { 1360 recover(); 1361 } 1362 1363 if (!symbol) 1364 { 1365 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); 1366 recover(); 1367 1368 return NULL; 1369 } 1370 else 1371 { 1372 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); 1373 ASSERT(variable); 1374 const TType &type = variable->getType(); 1375 TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(), 1376 *identifier, type, identifierLoc); 1377 1378 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc); 1379 aggregate->setOp(EOpInvariantDeclaration); 1380 return aggregate; 1381 } 1382 } 1383 1384 TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) 1385 { 1386 TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); 1387 TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); 1388 1389 if (structQualifierErrorCheck(identifierLocation, publicType)) 1390 recover(); 1391 1392 if (locationDeclaratorListCheck(identifierLocation, publicType)) 1393 recover(); 1394 1395 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false)) 1396 recover(); 1397 1398 TVariable* variable = 0; 1399 if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable)) 1400 recover(); 1401 if (symbol && variable) 1402 symbol->setId(variable->getUniqueId()); 1403 1404 return intermAggregate; 1405 } 1406 1407 TIntermAggregate* TParseContext::parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression) 1408 { 1409 if (structQualifierErrorCheck(identifierLocation, publicType)) 1410 recover(); 1411 1412 if (locationDeclaratorListCheck(identifierLocation, publicType)) 1413 recover(); 1414 1415 if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true)) 1416 recover(); 1417 1418 if (arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType)) 1419 { 1420 recover(); 1421 } 1422 else if (indexExpression) 1423 { 1424 int size; 1425 if (arraySizeErrorCheck(arrayLocation, indexExpression, size)) 1426 recover(); 1427 TPublicType arrayType(publicType); 1428 arrayType.setArray(true, size); 1429 TVariable* variable = NULL; 1430 if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable)) 1431 recover(); 1432 TType type = TType(arrayType); 1433 type.setArraySize(size); 1434 1435 return intermediate.growAggregate(declaratorList, intermediate.addSymbol(variable ? variable->getUniqueId() : 0, identifier, type, identifierLocation), identifierLocation); 1436 } 1437 else 1438 { 1439 TPublicType arrayType(publicType); 1440 arrayType.setArray(true); 1441 TVariable* variable = NULL; 1442 if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable)) 1443 recover(); 1444 } 1445 1446 return NULL; 1447 } 1448 1449 TIntermAggregate* TParseContext::parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer) 1450 { 1451 if (structQualifierErrorCheck(identifierLocation, publicType)) 1452 recover(); 1453 1454 if (locationDeclaratorListCheck(identifierLocation, publicType)) 1455 recover(); 1456 1457 TIntermNode* intermNode; 1458 if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode)) 1459 { 1460 // 1461 // build the intermediate representation 1462 // 1463 if (intermNode) 1464 { 1465 return intermediate.growAggregate(declaratorList, intermNode, initLocation); 1466 } 1467 else 1468 { 1469 return declaratorList; 1470 } 1471 } 1472 else 1473 { 1474 recover(); 1475 return NULL; 1476 } 1477 } 1478 1479 void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) 1480 { 1481 if (typeQualifier.qualifier != EvqUniform) 1482 { 1483 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform"); 1484 recover(); 1485 return; 1486 } 1487 1488 const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; 1489 ASSERT(!layoutQualifier.isEmpty()); 1490 1491 if (shaderVersion < 300) 1492 { 1493 error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout"); 1494 recover(); 1495 return; 1496 } 1497 1498 if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier)) 1499 { 1500 recover(); 1501 return; 1502 } 1503 1504 if (layoutQualifier.matrixPacking != EmpUnspecified) 1505 { 1506 defaultMatrixPacking = layoutQualifier.matrixPacking; 1507 } 1508 1509 if (layoutQualifier.blockStorage != EbsUnspecified) 1510 { 1511 defaultBlockStorage = layoutQualifier.blockStorage; 1512 } 1513 } 1514 1515 TFunction *TParseContext::addConstructorFunc(TPublicType publicType) 1516 { 1517 TOperator op = EOpNull; 1518 if (publicType.userDef) 1519 { 1520 op = EOpConstructStruct; 1521 } 1522 else 1523 { 1524 switch (publicType.type) 1525 { 1526 case EbtFloat: 1527 if (publicType.isMatrix()) 1528 { 1529 // TODO: non-square matrices 1530 switch(publicType.getCols()) 1531 { 1532 case 2: op = EOpConstructMat2; break; 1533 case 3: op = EOpConstructMat3; break; 1534 case 4: op = EOpConstructMat4; break; 1535 } 1536 } 1537 else 1538 { 1539 switch(publicType.getNominalSize()) 1540 { 1541 case 1: op = EOpConstructFloat; break; 1542 case 2: op = EOpConstructVec2; break; 1543 case 3: op = EOpConstructVec3; break; 1544 case 4: op = EOpConstructVec4; break; 1545 } 1546 } 1547 break; 1548 1549 case EbtInt: 1550 switch(publicType.getNominalSize()) 1551 { 1552 case 1: op = EOpConstructInt; break; 1553 case 2: op = EOpConstructIVec2; break; 1554 case 3: op = EOpConstructIVec3; break; 1555 case 4: op = EOpConstructIVec4; break; 1556 } 1557 break; 1558 1559 case EbtUInt: 1560 switch(publicType.getNominalSize()) 1561 { 1562 case 1: op = EOpConstructUInt; break; 1563 case 2: op = EOpConstructUVec2; break; 1564 case 3: op = EOpConstructUVec3; break; 1565 case 4: op = EOpConstructUVec4; break; 1566 } 1567 break; 1568 1569 case EbtBool: 1570 switch(publicType.getNominalSize()) 1571 { 1572 case 1: op = EOpConstructBool; break; 1573 case 2: op = EOpConstructBVec2; break; 1574 case 3: op = EOpConstructBVec3; break; 1575 case 4: op = EOpConstructBVec4; break; 1576 } 1577 break; 1578 1579 default: break; 1580 } 1581 1582 if (op == EOpNull) 1583 { 1584 error(publicType.line, "cannot construct this type", getBasicString(publicType.type)); 1585 recover(); 1586 publicType.type = EbtFloat; 1587 op = EOpConstructFloat; 1588 } 1589 } 1590 1591 TString tempString; 1592 TType type(publicType); 1593 return new TFunction(&tempString, type, op); 1594 } 1595 1596 // This function is used to test for the correctness of the parameters passed to various constructor functions 1597 // and also convert them to the right datatype if it is allowed and required. 1598 // 1599 // Returns 0 for an error or the constructed node (aggregate or typed) for no error. 1600 // 1601 TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line) 1602 { 1603 TIntermAggregate *aggregateArguments = arguments->getAsAggregate(); 1604 1605 if (!aggregateArguments) 1606 { 1607 aggregateArguments = new TIntermAggregate; 1608 aggregateArguments->getSequence()->push_back(arguments); 1609 } 1610 1611 if (op == EOpConstructStruct) 1612 { 1613 const TFieldList &fields = type->getStruct()->fields(); 1614 TIntermSequence *args = aggregateArguments->getSequence(); 1615 1616 for (size_t i = 0; i < fields.size(); i++) 1617 { 1618 if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type()) 1619 { 1620 error(line, "Structure constructor arguments do not match structure fields", "Error"); 1621 recover(); 1622 1623 return 0; 1624 } 1625 } 1626 } 1627 1628 // Turn the argument list itself into a constructor 1629 TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); 1630 TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); 1631 if (constConstructor) 1632 { 1633 return constConstructor; 1634 } 1635 1636 return constructor; 1637 } 1638 1639 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) 1640 { 1641 bool canBeFolded = areAllChildConst(aggrNode); 1642 aggrNode->setType(type); 1643 if (canBeFolded) { 1644 bool returnVal = false; 1645 ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; 1646 if (aggrNode->getSequence()->size() == 1) { 1647 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true); 1648 } 1649 else { 1650 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type); 1651 } 1652 if (returnVal) 1653 return 0; 1654 1655 return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); 1656 } 1657 1658 return 0; 1659 } 1660 1661 // 1662 // This function returns the tree representation for the vector field(s) being accessed from contant vector. 1663 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is 1664 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol 1665 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 1666 // a constant matrix. 1667 // 1668 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) 1669 { 1670 TIntermTyped* typedNode; 1671 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1672 1673 ConstantUnion *unionArray; 1674 if (tempConstantNode) { 1675 unionArray = tempConstantNode->getUnionArrayPointer(); 1676 1677 if (!unionArray) { 1678 return node; 1679 } 1680 } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error 1681 error(line, "Cannot offset into the vector", "Error"); 1682 recover(); 1683 1684 return 0; 1685 } 1686 1687 ConstantUnion* constArray = new ConstantUnion[fields.num]; 1688 1689 for (int i = 0; i < fields.num; i++) { 1690 if (fields.offsets[i] >= node->getType().getNominalSize()) { 1691 std::stringstream extraInfoStream; 1692 extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; 1693 std::string extraInfo = extraInfoStream.str(); 1694 error(line, "", "[", extraInfo.c_str()); 1695 recover(); 1696 fields.offsets[i] = 0; 1697 } 1698 1699 constArray[i] = unionArray[fields.offsets[i]]; 1700 1701 } 1702 typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); 1703 return typedNode; 1704 } 1705 1706 // 1707 // This function returns the column being accessed from a constant matrix. The values are retrieved from 1708 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 1709 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 1710 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) 1711 // 1712 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) 1713 { 1714 TIntermTyped* typedNode; 1715 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1716 1717 if (index >= node->getType().getCols()) { 1718 std::stringstream extraInfoStream; 1719 extraInfoStream << "matrix field selection out of range '" << index << "'"; 1720 std::string extraInfo = extraInfoStream.str(); 1721 error(line, "", "[", extraInfo.c_str()); 1722 recover(); 1723 index = 0; 1724 } 1725 1726 if (tempConstantNode) { 1727 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); 1728 int size = tempConstantNode->getType().getCols(); 1729 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); 1730 } else { 1731 error(line, "Cannot offset into the matrix", "Error"); 1732 recover(); 1733 1734 return 0; 1735 } 1736 1737 return typedNode; 1738 } 1739 1740 1741 // 1742 // This function returns an element of an array accessed from a constant array. The values are retrieved from 1743 // the symbol table and parse-tree is built for the type of the element. The input 1744 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a 1745 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) 1746 // 1747 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) 1748 { 1749 TIntermTyped* typedNode; 1750 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); 1751 TType arrayElementType = node->getType(); 1752 arrayElementType.clearArrayness(); 1753 1754 if (index >= node->getType().getArraySize()) { 1755 std::stringstream extraInfoStream; 1756 extraInfoStream << "array field selection out of range '" << index << "'"; 1757 std::string extraInfo = extraInfoStream.str(); 1758 error(line, "", "[", extraInfo.c_str()); 1759 recover(); 1760 index = 0; 1761 } 1762 1763 if (tempConstantNode) { 1764 size_t arrayElementSize = arrayElementType.getObjectSize(); 1765 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); 1766 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); 1767 } else { 1768 error(line, "Cannot offset into the array", "Error"); 1769 recover(); 1770 1771 return 0; 1772 } 1773 1774 return typedNode; 1775 } 1776 1777 1778 // 1779 // This function returns the value of a particular field inside a constant structure from the symbol table. 1780 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr 1781 // function and returns the parse-tree with the values of the embedded/nested struct. 1782 // 1783 TIntermTyped* TParseContext::addConstStruct(const TString &identifier, TIntermTyped *node, const TSourceLoc& line) 1784 { 1785 const TFieldList& fields = node->getType().getStruct()->fields(); 1786 size_t instanceSize = 0; 1787 1788 for (size_t index = 0; index < fields.size(); ++index) { 1789 if (fields[index]->name() == identifier) { 1790 break; 1791 } else { 1792 instanceSize += fields[index]->type()->getObjectSize(); 1793 } 1794 } 1795 1796 TIntermTyped *typedNode; 1797 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); 1798 if (tempConstantNode) { 1799 ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); 1800 1801 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function 1802 } else { 1803 error(line, "Cannot offset into the structure", "Error"); 1804 recover(); 1805 1806 return 0; 1807 } 1808 1809 return typedNode; 1810 } 1811 1812 // 1813 // Interface/uniform blocks 1814 // 1815 TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, 1816 const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine) 1817 { 1818 if (reservedErrorCheck(nameLine, blockName)) 1819 recover(); 1820 1821 if (typeQualifier.qualifier != EvqUniform) 1822 { 1823 error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform"); 1824 recover(); 1825 } 1826 1827 TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; 1828 if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier)) 1829 { 1830 recover(); 1831 } 1832 1833 if (blockLayoutQualifier.matrixPacking == EmpUnspecified) 1834 { 1835 blockLayoutQualifier.matrixPacking = defaultMatrixPacking; 1836 } 1837 1838 if (blockLayoutQualifier.blockStorage == EbsUnspecified) 1839 { 1840 blockLayoutQualifier.blockStorage = defaultBlockStorage; 1841 } 1842 1843 TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName); 1844 if (!symbolTable.declare(blockNameSymbol)) { 1845 error(nameLine, "redefinition", blockName.c_str(), "interface block name"); 1846 recover(); 1847 } 1848 1849 // check for sampler types and apply layout qualifiers 1850 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) { 1851 TField* field = (*fieldList)[memberIndex]; 1852 TType* fieldType = field->type(); 1853 if (IsSampler(fieldType->getBasicType())) { 1854 error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks"); 1855 recover(); 1856 } 1857 1858 const TQualifier qualifier = fieldType->getQualifier(); 1859 switch (qualifier) 1860 { 1861 case EvqGlobal: 1862 case EvqUniform: 1863 break; 1864 default: 1865 error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier)); 1866 recover(); 1867 break; 1868 } 1869 1870 // check layout qualifiers 1871 TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); 1872 if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier)) 1873 { 1874 recover(); 1875 } 1876 1877 if (fieldLayoutQualifier.blockStorage != EbsUnspecified) 1878 { 1879 error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here"); 1880 recover(); 1881 } 1882 1883 if (fieldLayoutQualifier.matrixPacking == EmpUnspecified) 1884 { 1885 fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking; 1886 } 1887 else if (!fieldType->isMatrix()) 1888 { 1889 error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types"); 1890 recover(); 1891 } 1892 1893 fieldType->setLayoutQualifier(fieldLayoutQualifier); 1894 } 1895 1896 // add array index 1897 int arraySize = 0; 1898 if (arrayIndex != NULL) 1899 { 1900 if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize)) 1901 recover(); 1902 } 1903 1904 TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier); 1905 TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize); 1906 1907 TString symbolName = ""; 1908 int symbolId = 0; 1909 1910 if (!instanceName) 1911 { 1912 // define symbols for the members of the interface block 1913 for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) 1914 { 1915 TField* field = (*fieldList)[memberIndex]; 1916 TType* fieldType = field->type(); 1917 1918 // set parent pointer of the field variable 1919 fieldType->setInterfaceBlock(interfaceBlock); 1920 1921 TVariable* fieldVariable = new TVariable(&field->name(), *fieldType); 1922 fieldVariable->setQualifier(typeQualifier.qualifier); 1923 1924 if (!symbolTable.declare(fieldVariable)) { 1925 error(field->line(), "redefinition", field->name().c_str(), "interface block member name"); 1926 recover(); 1927 } 1928 } 1929 } 1930 else 1931 { 1932 // add a symbol for this interface block 1933 TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false); 1934 instanceTypeDef->setQualifier(typeQualifier.qualifier); 1935 1936 if (!symbolTable.declare(instanceTypeDef)) { 1937 error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name"); 1938 recover(); 1939 } 1940 1941 symbolId = instanceTypeDef->getUniqueId(); 1942 symbolName = instanceTypeDef->getName(); 1943 } 1944 1945 TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine); 1946 aggregate->setOp(EOpDeclaration); 1947 1948 exitStructDeclaration(); 1949 return aggregate; 1950 } 1951 1952 bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) 1953 { 1954 ++structNestingLevel; 1955 1956 // Embedded structure definitions are not supported per GLSL ES spec. 1957 // They aren't allowed in GLSL either, but we need to detect this here 1958 // so we don't rely on the GLSL compiler to catch it. 1959 if (structNestingLevel > 1) { 1960 error(line, "", "Embedded struct definitions are not allowed"); 1961 return true; 1962 } 1963 1964 return false; 1965 } 1966 1967 void TParseContext::exitStructDeclaration() 1968 { 1969 --structNestingLevel; 1970 } 1971 1972 namespace { 1973 1974 const int kWebGLMaxStructNesting = 4; 1975 1976 } // namespace 1977 1978 bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) 1979 { 1980 if (!IsWebGLBasedSpec(shaderSpec)) { 1981 return false; 1982 } 1983 1984 if (field.type()->getBasicType() != EbtStruct) { 1985 return false; 1986 } 1987 1988 // We're already inside a structure definition at this point, so add 1989 // one to the field's struct nesting. 1990 if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { 1991 std::stringstream reasonStream; 1992 reasonStream << "Reference of struct type " 1993 << field.type()->getStruct()->name().c_str() 1994 << " exceeds maximum allowed nesting level of " 1995 << kWebGLMaxStructNesting; 1996 std::string reason = reasonStream.str(); 1997 error(line, reason.c_str(), field.name().c_str(), ""); 1998 return true; 1999 } 2000 2001 return false; 2002 } 2003 2004 // 2005 // Parse an array index expression 2006 // 2007 TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) 2008 { 2009 TIntermTyped *indexedExpression = NULL; 2010 2011 if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) 2012 { 2013 if (baseExpression->getAsSymbolNode()) 2014 { 2015 error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); 2016 } 2017 else 2018 { 2019 error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); 2020 } 2021 recover(); 2022 } 2023 2024 if (indexExpression->getQualifier() == EvqConst) 2025 { 2026 int index = indexExpression->getAsConstantUnion()->getIConst(0); 2027 if (index < 0) 2028 { 2029 std::stringstream infoStream; 2030 infoStream << index; 2031 std::string info = infoStream.str(); 2032 error(location, "negative index", info.c_str()); 2033 recover(); 2034 index = 0; 2035 } 2036 if (baseExpression->getType().getQualifier() == EvqConst) 2037 { 2038 if (baseExpression->isArray()) 2039 { 2040 // constant folding for arrays 2041 indexedExpression = addConstArrayNode(index, baseExpression, location); 2042 } 2043 else if (baseExpression->isVector()) 2044 { 2045 // constant folding for vectors 2046 TVectorFields fields; 2047 fields.num = 1; 2048 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array 2049 indexedExpression = addConstVectorNode(fields, baseExpression, location); 2050 } 2051 else if (baseExpression->isMatrix()) 2052 { 2053 // constant folding for matrices 2054 indexedExpression = addConstMatrixNode(index, baseExpression, location); 2055 } 2056 } 2057 else 2058 { 2059 if (baseExpression->isArray()) 2060 { 2061 if (index >= baseExpression->getType().getArraySize()) 2062 { 2063 std::stringstream extraInfoStream; 2064 extraInfoStream << "array index out of range '" << index << "'"; 2065 std::string extraInfo = extraInfoStream.str(); 2066 error(location, "", "[", extraInfo.c_str()); 2067 recover(); 2068 index = baseExpression->getType().getArraySize() - 1; 2069 } 2070 else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) 2071 { 2072 error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); 2073 recover(); 2074 index = 0; 2075 } 2076 } 2077 else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) 2078 { 2079 std::stringstream extraInfoStream; 2080 extraInfoStream << "field selection out of range '" << index << "'"; 2081 std::string extraInfo = extraInfoStream.str(); 2082 error(location, "", "[", extraInfo.c_str()); 2083 recover(); 2084 index = baseExpression->getType().getNominalSize() - 1; 2085 } 2086 2087 indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); 2088 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); 2089 } 2090 } 2091 else 2092 { 2093 if (baseExpression->isInterfaceBlock()) 2094 { 2095 error(location, "", "[", "array indexes for interface blocks arrays must be constant integral expressions"); 2096 recover(); 2097 } 2098 else if (baseExpression->getQualifier() == EvqFragmentOut) 2099 { 2100 error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions"); 2101 recover(); 2102 } 2103 2104 indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); 2105 } 2106 2107 if (indexedExpression == 0) 2108 { 2109 ConstantUnion *unionArray = new ConstantUnion[1]; 2110 unionArray->setFConst(0.0f); 2111 indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); 2112 } 2113 else if (baseExpression->isArray()) 2114 { 2115 const TType &baseType = baseExpression->getType(); 2116 if (baseType.getStruct()) 2117 { 2118 TType copyOfType(baseType.getStruct()); 2119 indexedExpression->setType(copyOfType); 2120 } 2121 else if (baseType.isInterfaceBlock()) 2122 { 2123 TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(), baseType.getLayoutQualifier(), 0); 2124 indexedExpression->setType(copyOfType); 2125 } 2126 else 2127 { 2128 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->getSecondarySize())); 2129 } 2130 2131 if (baseExpression->getType().getQualifier() == EvqConst) 2132 { 2133 indexedExpression->getTypePointer()->setQualifier(EvqConst); 2134 } 2135 } 2136 else if (baseExpression->isMatrix()) 2137 { 2138 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; 2139 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getRows())); 2140 } 2141 else if (baseExpression->isVector()) 2142 { 2143 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; 2144 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); 2145 } 2146 else 2147 { 2148 indexedExpression->setType(baseExpression->getType()); 2149 } 2150 2151 return indexedExpression; 2152 } 2153 2154 TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc& dotLocation, const TString &fieldString, const TSourceLoc& fieldLocation) 2155 { 2156 TIntermTyped *indexedExpression = NULL; 2157 2158 if (baseExpression->isArray()) 2159 { 2160 error(fieldLocation, "cannot apply dot operator to an array", "."); 2161 recover(); 2162 } 2163 2164 if (baseExpression->isVector()) 2165 { 2166 TVectorFields fields; 2167 if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation)) 2168 { 2169 fields.num = 1; 2170 fields.offsets[0] = 0; 2171 recover(); 2172 } 2173 2174 if (baseExpression->getType().getQualifier() == EvqConst) 2175 { 2176 // constant folding for vector fields 2177 indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation); 2178 if (indexedExpression == 0) 2179 { 2180 recover(); 2181 indexedExpression = baseExpression; 2182 } 2183 else 2184 { 2185 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, (int) (fieldString).size())); 2186 } 2187 } 2188 else 2189 { 2190 TString vectorString = fieldString; 2191 TIntermTyped* index = intermediate.addSwizzle(fields, fieldLocation); 2192 indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation); 2193 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, (int) vectorString.size())); 2194 } 2195 } 2196 else if (baseExpression->isMatrix()) 2197 { 2198 TMatrixFields fields; 2199 if (!parseMatrixFields(fieldString, baseExpression->getCols(), baseExpression->getRows(), fields, fieldLocation)) 2200 { 2201 fields.wholeRow = false; 2202 fields.wholeCol = false; 2203 fields.row = 0; 2204 fields.col = 0; 2205 recover(); 2206 } 2207 2208 if (fields.wholeRow || fields.wholeCol) 2209 { 2210 error(dotLocation, " non-scalar fields not implemented yet", "."); 2211 recover(); 2212 ConstantUnion *unionArray = new ConstantUnion[1]; 2213 unionArray->setIConst(0); 2214 TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation); 2215 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation); 2216 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),EvqTemporary, baseExpression->getCols(), baseExpression->getRows())); 2217 } 2218 else 2219 { 2220 ConstantUnion *unionArray = new ConstantUnion[1]; 2221 unionArray->setIConst(fields.col * baseExpression->getRows() + fields.row); 2222 TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation); 2223 indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation); 2224 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision())); 2225 } 2226 } 2227 else if (baseExpression->getBasicType() == EbtStruct) 2228 { 2229 bool fieldFound = false; 2230 const TFieldList& fields = baseExpression->getType().getStruct()->fields(); 2231 if (fields.empty()) 2232 { 2233 error(dotLocation, "structure has no fields", "Internal Error"); 2234 recover(); 2235 indexedExpression = baseExpression; 2236 } 2237 else 2238 { 2239 unsigned int i; 2240 for (i = 0; i < fields.size(); ++i) 2241 { 2242 if (fields[i]->name() == fieldString) 2243 { 2244 fieldFound = true; 2245 break; 2246 } 2247 } 2248 if (fieldFound) 2249 { 2250 if (baseExpression->getType().getQualifier() == EvqConst) 2251 { 2252 indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation); 2253 if (indexedExpression == 0) 2254 { 2255 recover(); 2256 indexedExpression = baseExpression; 2257 } 2258 else 2259 { 2260 indexedExpression->setType(*fields[i]->type()); 2261 // change the qualifier of the return type, not of the structure field 2262 // as the structure definition is shared between various structures. 2263 indexedExpression->getTypePointer()->setQualifier(EvqConst); 2264 } 2265 } 2266 else 2267 { 2268 ConstantUnion *unionArray = new ConstantUnion[1]; 2269 unionArray->setIConst(i); 2270 TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation); 2271 indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation); 2272 indexedExpression->setType(*fields[i]->type()); 2273 } 2274 } 2275 else 2276 { 2277 error(dotLocation, " no such field in structure", fieldString.c_str()); 2278 recover(); 2279 indexedExpression = baseExpression; 2280 } 2281 } 2282 } 2283 else if (baseExpression->isInterfaceBlock()) 2284 { 2285 bool fieldFound = false; 2286 const TFieldList& fields = baseExpression->getType().getInterfaceBlock()->fields(); 2287 if (fields.empty()) 2288 { 2289 error(dotLocation, "interface block has no fields", "Internal Error"); 2290 recover(); 2291 indexedExpression = baseExpression; 2292 } 2293 else 2294 { 2295 unsigned int i; 2296 for (i = 0; i < fields.size(); ++i) 2297 { 2298 if (fields[i]->name() == fieldString) 2299 { 2300 fieldFound = true; 2301 break; 2302 } 2303 } 2304 if (fieldFound) 2305 { 2306 ConstantUnion *unionArray = new ConstantUnion[1]; 2307 unionArray->setIConst(i); 2308 TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation); 2309 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, dotLocation); 2310 indexedExpression->setType(*fields[i]->type()); 2311 } 2312 else 2313 { 2314 error(dotLocation, " no such field in interface block", fieldString.c_str()); 2315 recover(); 2316 indexedExpression = baseExpression; 2317 } 2318 } 2319 } 2320 else 2321 { 2322 if (shaderVersion < 300) 2323 { 2324 error(dotLocation, " field selection requires structure, vector, or matrix on left hand side", fieldString.c_str()); 2325 } 2326 else 2327 { 2328 error(dotLocation, " field selection requires structure, vector, matrix, or interface block on left hand side", fieldString.c_str()); 2329 } 2330 recover(); 2331 indexedExpression = baseExpression; 2332 } 2333 2334 return indexedExpression; 2335 } 2336 2337 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine) 2338 { 2339 TLayoutQualifier qualifier; 2340 2341 qualifier.location = -1; 2342 qualifier.matrixPacking = EmpUnspecified; 2343 qualifier.blockStorage = EbsUnspecified; 2344 2345 if (qualifierType == "shared") 2346 { 2347 qualifier.blockStorage = EbsShared; 2348 } 2349 else if (qualifierType == "packed") 2350 { 2351 qualifier.blockStorage = EbsPacked; 2352 } 2353 else if (qualifierType == "std140") 2354 { 2355 qualifier.blockStorage = EbsStd140; 2356 } 2357 else if (qualifierType == "row_major") 2358 { 2359 qualifier.matrixPacking = EmpRowMajor; 2360 } 2361 else if (qualifierType == "column_major") 2362 { 2363 qualifier.matrixPacking = EmpColumnMajor; 2364 } 2365 else if (qualifierType == "location") 2366 { 2367 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument"); 2368 recover(); 2369 } 2370 else 2371 { 2372 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); 2373 recover(); 2374 } 2375 2376 return qualifier; 2377 } 2378 2379 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine) 2380 { 2381 TLayoutQualifier qualifier; 2382 2383 qualifier.location = -1; 2384 qualifier.matrixPacking = EmpUnspecified; 2385 qualifier.blockStorage = EbsUnspecified; 2386 2387 if (qualifierType != "location") 2388 { 2389 error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments"); 2390 recover(); 2391 } 2392 else 2393 { 2394 // must check that location is non-negative 2395 if (intValue < 0) 2396 { 2397 error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative"); 2398 recover(); 2399 } 2400 else 2401 { 2402 qualifier.location = intValue; 2403 } 2404 } 2405 2406 return qualifier; 2407 } 2408 2409 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier) 2410 { 2411 TLayoutQualifier joinedQualifier = leftQualifier; 2412 2413 if (rightQualifier.location != -1) 2414 { 2415 joinedQualifier.location = rightQualifier.location; 2416 } 2417 if (rightQualifier.matrixPacking != EmpUnspecified) 2418 { 2419 joinedQualifier.matrixPacking = rightQualifier.matrixPacking; 2420 } 2421 if (rightQualifier.blockStorage != EbsUnspecified) 2422 { 2423 joinedQualifier.blockStorage = rightQualifier.blockStorage; 2424 } 2425 2426 return joinedQualifier; 2427 } 2428 2429 TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, 2430 const TSourceLoc &storageLoc, TQualifier storageQualifier) 2431 { 2432 TQualifier mergedQualifier = EvqSmoothIn; 2433 2434 if (storageQualifier == EvqFragmentIn) { 2435 if (interpolationQualifier == EvqSmooth) 2436 mergedQualifier = EvqSmoothIn; 2437 else if (interpolationQualifier == EvqFlat) 2438 mergedQualifier = EvqFlatIn; 2439 else UNREACHABLE(); 2440 } 2441 else if (storageQualifier == EvqCentroidIn) { 2442 if (interpolationQualifier == EvqSmooth) 2443 mergedQualifier = EvqCentroidIn; 2444 else if (interpolationQualifier == EvqFlat) 2445 mergedQualifier = EvqFlatIn; 2446 else UNREACHABLE(); 2447 } 2448 else if (storageQualifier == EvqVertexOut) { 2449 if (interpolationQualifier == EvqSmooth) 2450 mergedQualifier = EvqSmoothOut; 2451 else if (interpolationQualifier == EvqFlat) 2452 mergedQualifier = EvqFlatOut; 2453 else UNREACHABLE(); 2454 } 2455 else if (storageQualifier == EvqCentroidOut) { 2456 if (interpolationQualifier == EvqSmooth) 2457 mergedQualifier = EvqCentroidOut; 2458 else if (interpolationQualifier == EvqFlat) 2459 mergedQualifier = EvqFlatOut; 2460 else UNREACHABLE(); 2461 } 2462 else { 2463 error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString(interpolationQualifier)); 2464 recover(); 2465 2466 mergedQualifier = storageQualifier; 2467 } 2468 2469 TPublicType type; 2470 type.setBasic(EbtVoid, mergedQualifier, storageLoc); 2471 return type; 2472 } 2473 2474 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList) 2475 { 2476 if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier)) { 2477 recover(); 2478 } 2479 2480 for (unsigned int i = 0; i < fieldList->size(); ++i) { 2481 // 2482 // Careful not to replace already known aspects of type, like array-ness 2483 // 2484 TType* type = (*fieldList)[i]->type(); 2485 type->setBasicType(typeSpecifier.type); 2486 type->setPrimarySize(typeSpecifier.primarySize); 2487 type->setSecondarySize(typeSpecifier.secondarySize); 2488 type->setPrecision(typeSpecifier.precision); 2489 type->setQualifier(typeSpecifier.qualifier); 2490 type->setLayoutQualifier(typeSpecifier.layoutQualifier); 2491 2492 // don't allow arrays of arrays 2493 if (type->isArray()) { 2494 if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier)) 2495 recover(); 2496 } 2497 if (typeSpecifier.array) 2498 type->setArraySize(typeSpecifier.arraySize); 2499 if (typeSpecifier.userDef) { 2500 type->setStruct(typeSpecifier.userDef->getStruct()); 2501 } 2502 2503 if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i])) { 2504 recover(); 2505 } 2506 } 2507 2508 return fieldList; 2509 } 2510 2511 TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList) 2512 { 2513 TStructure* structure = new TStructure(structName, fieldList); 2514 TType* structureType = new TType(structure); 2515 2516 structure->setUniqueId(TSymbolTable::nextUniqueId()); 2517 2518 if (!structName->empty()) 2519 { 2520 if (reservedErrorCheck(nameLine, *structName)) 2521 { 2522 recover(); 2523 } 2524 TVariable* userTypeDef = new TVariable(structName, *structureType, true); 2525 if (!symbolTable.declare(userTypeDef)) { 2526 error(nameLine, "redefinition", structName->c_str(), "struct"); 2527 recover(); 2528 } 2529 } 2530 2531 // ensure we do not specify any storage qualifiers on the struct members 2532 for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++) 2533 { 2534 const TField &field = *(*fieldList)[typeListIndex]; 2535 const TQualifier qualifier = field.type()->getQualifier(); 2536 switch (qualifier) 2537 { 2538 case EvqGlobal: 2539 case EvqTemporary: 2540 break; 2541 default: 2542 error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier)); 2543 recover(); 2544 break; 2545 } 2546 } 2547 2548 TPublicType publicType; 2549 publicType.setBasic(EbtStruct, EvqTemporary, structLine); 2550 publicType.userDef = structureType; 2551 exitStructDeclaration(); 2552 2553 return publicType; 2554 } 2555 2556 // 2557 // Parse an array of strings using yyparse. 2558 // 2559 // Returns 0 for success. 2560 // 2561 int PaParseStrings(size_t count, const char* const string[], const int length[], 2562 TParseContext* context) { 2563 if ((count == 0) || (string == NULL)) 2564 return 1; 2565 2566 if (glslang_initialize(context)) 2567 return 1; 2568 2569 int error = glslang_scan(count, string, length, context); 2570 if (!error) 2571 error = glslang_parse(context); 2572 2573 glslang_finalize(context); 2574 2575 return (error == 0) && (context->numErrors() == 0) ? 0 : 1; 2576 } 2577 2578 2579 2580