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 // 8 // Build the intermediate representation. 9 // 10 11 #include <float.h> 12 #include <limits.h> 13 #include <algorithm> 14 15 #include "compiler/translator/HashNames.h" 16 #include "compiler/translator/localintermediate.h" 17 #include "compiler/translator/QualifierAlive.h" 18 #include "compiler/translator/RemoveTree.h" 19 #include "compiler/translator/SymbolTable.h" 20 21 bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); 22 23 static TPrecision GetHigherPrecision(TPrecision left, TPrecision right) 24 { 25 return left > right ? left : right; 26 } 27 28 const char* getOperatorString(TOperator op) 29 { 30 switch (op) { 31 case EOpInitialize: return "="; 32 case EOpAssign: return "="; 33 case EOpAddAssign: return "+="; 34 case EOpSubAssign: return "-="; 35 case EOpDivAssign: return "/="; 36 37 // Fall-through. 38 case EOpMulAssign: 39 case EOpVectorTimesMatrixAssign: 40 case EOpVectorTimesScalarAssign: 41 case EOpMatrixTimesScalarAssign: 42 case EOpMatrixTimesMatrixAssign: return "*="; 43 44 // Fall-through. 45 case EOpIndexDirect: 46 case EOpIndexIndirect: return "[]"; 47 48 case EOpIndexDirectStruct: 49 case EOpIndexDirectInterfaceBlock: return "."; 50 case EOpVectorSwizzle: return "."; 51 case EOpAdd: return "+"; 52 case EOpSub: return "-"; 53 case EOpMul: return "*"; 54 case EOpDiv: return "/"; 55 case EOpMod: UNIMPLEMENTED(); break; 56 case EOpEqual: return "=="; 57 case EOpNotEqual: return "!="; 58 case EOpLessThan: return "<"; 59 case EOpGreaterThan: return ">"; 60 case EOpLessThanEqual: return "<="; 61 case EOpGreaterThanEqual: return ">="; 62 63 // Fall-through. 64 case EOpVectorTimesScalar: 65 case EOpVectorTimesMatrix: 66 case EOpMatrixTimesVector: 67 case EOpMatrixTimesScalar: 68 case EOpMatrixTimesMatrix: return "*"; 69 70 case EOpLogicalOr: return "||"; 71 case EOpLogicalXor: return "^^"; 72 case EOpLogicalAnd: return "&&"; 73 case EOpNegative: return "-"; 74 case EOpVectorLogicalNot: return "not"; 75 case EOpLogicalNot: return "!"; 76 case EOpPostIncrement: return "++"; 77 case EOpPostDecrement: return "--"; 78 case EOpPreIncrement: return "++"; 79 case EOpPreDecrement: return "--"; 80 81 // Fall-through. 82 case EOpConvIntToBool: 83 case EOpConvUIntToBool: 84 case EOpConvFloatToBool: return "bool"; 85 86 // Fall-through. 87 case EOpConvBoolToFloat: 88 case EOpConvUIntToFloat: 89 case EOpConvIntToFloat: return "float"; 90 91 // Fall-through. 92 case EOpConvFloatToInt: 93 case EOpConvUIntToInt: 94 case EOpConvBoolToInt: return "int"; 95 96 // Fall-through. 97 case EOpConvIntToUInt: 98 case EOpConvFloatToUInt: 99 case EOpConvBoolToUInt: return "uint"; 100 101 case EOpRadians: return "radians"; 102 case EOpDegrees: return "degrees"; 103 case EOpSin: return "sin"; 104 case EOpCos: return "cos"; 105 case EOpTan: return "tan"; 106 case EOpAsin: return "asin"; 107 case EOpAcos: return "acos"; 108 case EOpAtan: return "atan"; 109 case EOpExp: return "exp"; 110 case EOpLog: return "log"; 111 case EOpExp2: return "exp2"; 112 case EOpLog2: return "log2"; 113 case EOpSqrt: return "sqrt"; 114 case EOpInverseSqrt: return "inversesqrt"; 115 case EOpAbs: return "abs"; 116 case EOpSign: return "sign"; 117 case EOpFloor: return "floor"; 118 case EOpCeil: return "ceil"; 119 case EOpFract: return "fract"; 120 case EOpLength: return "length"; 121 case EOpNormalize: return "normalize"; 122 case EOpDFdx: return "dFdx"; 123 case EOpDFdy: return "dFdy"; 124 case EOpFwidth: return "fwidth"; 125 case EOpAny: return "any"; 126 case EOpAll: return "all"; 127 128 default: break; 129 } 130 return ""; 131 } 132 133 //////////////////////////////////////////////////////////////////////////// 134 // 135 // First set of functions are to help build the intermediate representation. 136 // These functions are not member functions of the nodes. 137 // They are called from parser productions. 138 // 139 ///////////////////////////////////////////////////////////////////////////// 140 141 // 142 // Add a terminal node for an identifier in an expression. 143 // 144 // Returns the added node. 145 // 146 TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) 147 { 148 TIntermSymbol* node = new TIntermSymbol(id, name, type); 149 node->setLine(line); 150 151 return node; 152 } 153 154 // 155 // Connect two nodes with a new parent that does a binary operation on the nodes. 156 // 157 // Returns the added node. 158 // 159 TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) 160 { 161 switch (op) { 162 case EOpEqual: 163 case EOpNotEqual: 164 if (left->isArray()) 165 return 0; 166 break; 167 case EOpLessThan: 168 case EOpGreaterThan: 169 case EOpLessThanEqual: 170 case EOpGreaterThanEqual: 171 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { 172 return 0; 173 } 174 break; 175 case EOpLogicalOr: 176 case EOpLogicalXor: 177 case EOpLogicalAnd: 178 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { 179 return 0; 180 } 181 break; 182 case EOpAdd: 183 case EOpSub: 184 case EOpDiv: 185 case EOpMul: 186 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) 187 return 0; 188 default: break; 189 } 190 191 // 192 // First try converting the children to compatible types. 193 // 194 if (left->getType().getStruct() && right->getType().getStruct()) { 195 if (left->getType() != right->getType()) 196 return 0; 197 } else { 198 TIntermTyped* child = addConversion(op, left->getType(), right); 199 if (child) 200 right = child; 201 else { 202 child = addConversion(op, right->getType(), left); 203 if (child) 204 left = child; 205 else 206 return 0; 207 } 208 } 209 210 // 211 // Need a new node holding things together then. Make 212 // one and promote it to the right type. 213 // 214 TIntermBinary* node = new TIntermBinary(op); 215 node->setLine(line); 216 217 node->setLeft(left); 218 node->setRight(right); 219 if (!node->promote(infoSink)) 220 return 0; 221 222 // 223 // See if we can fold constants. 224 // 225 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); 226 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); 227 if (leftTempConstant && rightTempConstant) { 228 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); 229 230 if (typedReturnNode) 231 return typedReturnNode; 232 } 233 234 return node; 235 } 236 237 // 238 // Connect two nodes through an assignment. 239 // 240 // Returns the added node. 241 // 242 TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) 243 { 244 // 245 // Like adding binary math, except the conversion can only go 246 // from right to left. 247 // 248 TIntermBinary* node = new TIntermBinary(op); 249 node->setLine(line); 250 251 TIntermTyped* child = addConversion(op, left->getType(), right); 252 if (child == 0) 253 return 0; 254 255 node->setLeft(left); 256 node->setRight(child); 257 if (! node->promote(infoSink)) 258 return 0; 259 260 return node; 261 } 262 263 // 264 // Connect two nodes through an index operator, where the left node is the base 265 // of an array or struct, and the right node is a direct or indirect offset. 266 // 267 // Returns the added node. 268 // The caller should set the type of the returned node. 269 // 270 TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) 271 { 272 TIntermBinary* node = new TIntermBinary(op); 273 node->setLine(line); 274 node->setLeft(base); 275 node->setRight(index); 276 277 // caller should set the type 278 279 return node; 280 } 281 282 // 283 // Add one node as the parent of another that it operates on. 284 // 285 // Returns the added node. 286 // 287 TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line) 288 { 289 TIntermUnary* node; 290 TIntermTyped* child = childNode->getAsTyped(); 291 292 if (child == 0) { 293 infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); 294 return 0; 295 } 296 297 switch (op) { 298 case EOpLogicalNot: 299 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { 300 return 0; 301 } 302 break; 303 304 case EOpPostIncrement: 305 case EOpPreIncrement: 306 case EOpPostDecrement: 307 case EOpPreDecrement: 308 case EOpNegative: 309 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) 310 return 0; 311 default: break; 312 } 313 314 // 315 // Do we need to promote the operand? 316 // 317 // Note: Implicit promotions were removed from the language. 318 // 319 TBasicType newType = EbtVoid; 320 switch (op) { 321 case EOpConstructInt: newType = EbtInt; break; 322 case EOpConstructUInt: newType = EbtUInt; break; 323 case EOpConstructBool: newType = EbtBool; break; 324 case EOpConstructFloat: newType = EbtFloat; break; 325 default: break; 326 } 327 328 if (newType != EbtVoid) { 329 child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, 330 child->getNominalSize(), 331 child->getSecondarySize(), 332 child->isArray()), 333 child); 334 if (child == 0) 335 return 0; 336 } 337 338 // 339 // For constructors, we are now done, it's all in the conversion. 340 // 341 switch (op) { 342 case EOpConstructInt: 343 case EOpConstructUInt: 344 case EOpConstructBool: 345 case EOpConstructFloat: 346 return child; 347 default: break; 348 } 349 350 TIntermConstantUnion *childTempConstant = 0; 351 if (child->getAsConstantUnion()) 352 childTempConstant = child->getAsConstantUnion(); 353 354 // 355 // Make a new node for the operator. 356 // 357 node = new TIntermUnary(op); 358 node->setLine(line); 359 node->setOperand(child); 360 361 if (! node->promote(infoSink)) 362 return 0; 363 364 if (childTempConstant) { 365 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); 366 367 if (newChild) 368 return newChild; 369 } 370 371 return node; 372 } 373 374 // 375 // This is the safe way to change the operator on an aggregate, as it 376 // does lots of error checking and fixing. Especially for establishing 377 // a function call's operation on it's set of parameters. Sequences 378 // of instructions are also aggregates, but they just direnctly set 379 // their operator to EOpSequence. 380 // 381 // Returns an aggregate node, which could be the one passed in if 382 // it was already an aggregate but no operator was set. 383 // 384 TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line) 385 { 386 TIntermAggregate* aggNode; 387 388 // 389 // Make sure we have an aggregate. If not turn it into one. 390 // 391 if (node) { 392 aggNode = node->getAsAggregate(); 393 if (aggNode == 0 || aggNode->getOp() != EOpNull) { 394 // 395 // Make an aggregate containing this node. 396 // 397 aggNode = new TIntermAggregate(); 398 aggNode->getSequence().push_back(node); 399 } 400 } else 401 aggNode = new TIntermAggregate(); 402 403 // 404 // Set the operator. 405 // 406 aggNode->setOp(op); 407 aggNode->setLine(line); 408 409 return aggNode; 410 } 411 412 // 413 // Convert one type to another. 414 // 415 // Returns the node representing the conversion, which could be the same 416 // node passed in if no conversion was needed. 417 // 418 // Return 0 if a conversion can't be done. 419 // 420 TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) 421 { 422 // 423 // Does the base type allow operation? 424 // 425 if (node->getBasicType() == EbtVoid || 426 IsSampler(node->getBasicType())) 427 { 428 return 0; 429 } 430 431 // 432 // Otherwise, if types are identical, no problem 433 // 434 if (type == node->getType()) 435 return node; 436 437 // 438 // If one's a structure, then no conversions. 439 // 440 if (type.getStruct() || node->getType().getStruct()) 441 return 0; 442 443 // 444 // If one's an array, then no conversions. 445 // 446 if (type.isArray() || node->getType().isArray()) 447 return 0; 448 449 TBasicType promoteTo; 450 451 switch (op) { 452 // 453 // Explicit conversions 454 // 455 case EOpConstructBool: 456 promoteTo = EbtBool; 457 break; 458 case EOpConstructFloat: 459 promoteTo = EbtFloat; 460 break; 461 case EOpConstructInt: 462 promoteTo = EbtInt; 463 break; 464 case EOpConstructUInt: 465 promoteTo = EbtUInt; 466 break; 467 default: 468 // 469 // implicit conversions were removed from the language. 470 // 471 if (type.getBasicType() != node->getType().getBasicType()) 472 return 0; 473 // 474 // Size and structure could still differ, but that's 475 // handled by operator promotion. 476 // 477 return node; 478 } 479 480 if (node->getAsConstantUnion()) { 481 482 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion())); 483 } else { 484 485 // 486 // Add a new newNode for the conversion. 487 // 488 TIntermUnary* newNode = 0; 489 490 TOperator newOp = EOpNull; 491 switch (promoteTo) { 492 case EbtFloat: 493 switch (node->getBasicType()) { 494 case EbtInt: newOp = EOpConvIntToFloat; break; 495 case EbtUInt: newOp = EOpConvFloatToUInt; break; 496 case EbtBool: newOp = EOpConvBoolToFloat; break; 497 default: 498 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); 499 return 0; 500 } 501 break; 502 case EbtBool: 503 switch (node->getBasicType()) { 504 case EbtInt: newOp = EOpConvIntToBool; break; 505 case EbtUInt: newOp = EOpConvBoolToUInt; break; 506 case EbtFloat: newOp = EOpConvFloatToBool; break; 507 default: 508 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); 509 return 0; 510 } 511 break; 512 case EbtInt: 513 switch (node->getBasicType()) { 514 case EbtUInt: newOp = EOpConvUIntToInt; break; 515 case EbtBool: newOp = EOpConvBoolToInt; break; 516 case EbtFloat: newOp = EOpConvFloatToInt; break; 517 default: 518 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); 519 return 0; 520 } 521 break; 522 case EbtUInt: 523 switch (node->getBasicType()) { 524 case EbtInt: newOp = EOpConvIntToUInt; break; 525 case EbtBool: newOp = EOpConvBoolToUInt; break; 526 case EbtFloat: newOp = EOpConvFloatToUInt; break; 527 default: 528 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); 529 return 0; 530 } 531 break; 532 default: 533 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); 534 return 0; 535 } 536 537 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->getSecondarySize(), node->isArray()); 538 newNode = new TIntermUnary(newOp, type); 539 newNode->setLine(node->getLine()); 540 newNode->setOperand(node); 541 542 return newNode; 543 } 544 } 545 546 // 547 // Safe way to combine two nodes into an aggregate. Works with null pointers, 548 // a node that's not a aggregate yet, etc. 549 // 550 // Returns the resulting aggregate, unless 0 was passed in for 551 // both existing nodes. 552 // 553 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line) 554 { 555 if (left == 0 && right == 0) 556 return 0; 557 558 TIntermAggregate* aggNode = 0; 559 if (left) 560 aggNode = left->getAsAggregate(); 561 if (!aggNode || aggNode->getOp() != EOpNull) { 562 aggNode = new TIntermAggregate; 563 if (left) 564 aggNode->getSequence().push_back(left); 565 } 566 567 if (right) 568 aggNode->getSequence().push_back(right); 569 570 aggNode->setLine(line); 571 572 return aggNode; 573 } 574 575 // 576 // Turn an existing node into an aggregate. 577 // 578 // Returns an aggregate, unless 0 was passed in for the existing node. 579 // 580 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) 581 { 582 if (node == 0) 583 return 0; 584 585 TIntermAggregate* aggNode = new TIntermAggregate; 586 aggNode->getSequence().push_back(node); 587 588 aggNode->setLine(line); 589 590 return aggNode; 591 } 592 593 // 594 // For "if" test nodes. There are three children; a condition, 595 // a true path, and a false path. The two paths are in the 596 // nodePair. 597 // 598 // Returns the selection node created. 599 // 600 TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) 601 { 602 // 603 // For compile time constant selections, prune the code and 604 // test now. 605 // 606 607 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { 608 if (cond->getAsConstantUnion()->getBConst(0) == true) 609 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; 610 else 611 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; 612 } 613 614 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); 615 node->setLine(line); 616 617 return node; 618 } 619 620 621 TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) 622 { 623 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { 624 return right; 625 } else { 626 TIntermTyped *commaAggregate = growAggregate(left, right, line); 627 commaAggregate->getAsAggregate()->setOp(EOpComma); 628 commaAggregate->setType(right->getType()); 629 commaAggregate->getTypePointer()->setQualifier(EvqTemporary); 630 return commaAggregate; 631 } 632 } 633 634 // 635 // For "?:" test nodes. There are three children; a condition, 636 // a true path, and a false path. The two paths are specified 637 // as separate parameters. 638 // 639 // Returns the selection node created, or 0 if one could not be. 640 // 641 TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) 642 { 643 // 644 // Get compatible types. 645 // 646 TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock); 647 if (child) 648 falseBlock = child; 649 else { 650 child = addConversion(EOpSequence, falseBlock->getType(), trueBlock); 651 if (child) 652 trueBlock = child; 653 else 654 return 0; 655 } 656 657 // 658 // See if all the operands are constant, then fold it otherwise not. 659 // 660 661 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { 662 if (cond->getAsConstantUnion()->getBConst(0)) 663 return trueBlock; 664 else 665 return falseBlock; 666 } 667 668 // 669 // Make a selection node. 670 // 671 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); 672 node->getTypePointer()->setQualifier(EvqTemporary); 673 node->setLine(line); 674 675 return node; 676 } 677 678 // 679 // Constant terminal nodes. Has a union that contains bool, float or int constants 680 // 681 // Returns the constant union node created. 682 // 683 684 TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) 685 { 686 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); 687 node->setLine(line); 688 689 return node; 690 } 691 692 TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) 693 { 694 695 TIntermAggregate* node = new TIntermAggregate(EOpSequence); 696 697 node->setLine(line); 698 TIntermConstantUnion* constIntNode; 699 TIntermSequence &sequenceVector = node->getSequence(); 700 ConstantUnion* unionArray; 701 702 for (int i = 0; i < fields.num; i++) { 703 unionArray = new ConstantUnion[1]; 704 unionArray->setIConst(fields.offsets[i]); 705 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); 706 sequenceVector.push_back(constIntNode); 707 } 708 709 return node; 710 } 711 712 // 713 // Create loop nodes. 714 // 715 TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line) 716 { 717 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); 718 node->setLine(line); 719 720 return node; 721 } 722 723 // 724 // Add branches. 725 // 726 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) 727 { 728 return addBranch(branchOp, 0, line); 729 } 730 731 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) 732 { 733 TIntermBranch* node = new TIntermBranch(branchOp, expression); 734 node->setLine(line); 735 736 return node; 737 } 738 739 // 740 // This is to be executed once the final root is put on top by the parsing 741 // process. 742 // 743 bool TIntermediate::postProcess(TIntermNode* root) 744 { 745 if (root == 0) 746 return true; 747 748 // 749 // First, finish off the top level sequence, if any 750 // 751 TIntermAggregate* aggRoot = root->getAsAggregate(); 752 if (aggRoot && aggRoot->getOp() == EOpNull) 753 aggRoot->setOp(EOpSequence); 754 755 return true; 756 } 757 758 // 759 // This deletes the tree. 760 // 761 void TIntermediate::remove(TIntermNode* root) 762 { 763 if (root) 764 RemoveAllTreeNodes(root); 765 } 766 767 //////////////////////////////////////////////////////////////// 768 // 769 // Member functions of the nodes used for building the tree. 770 // 771 //////////////////////////////////////////////////////////////// 772 773 #define REPLACE_IF_IS(node, type, original, replacement) \ 774 if (node == original) { \ 775 node = static_cast<type *>(replacement); \ 776 return true; \ 777 } 778 779 bool TIntermLoop::replaceChildNode( 780 TIntermNode *original, TIntermNode *replacement) 781 { 782 REPLACE_IF_IS(init, TIntermNode, original, replacement); 783 REPLACE_IF_IS(cond, TIntermTyped, original, replacement); 784 REPLACE_IF_IS(expr, TIntermTyped, original, replacement); 785 REPLACE_IF_IS(body, TIntermNode, original, replacement); 786 return false; 787 } 788 789 void TIntermLoop::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const 790 { 791 if (init) 792 { 793 nodeQueue->push(init); 794 } 795 if (cond) 796 { 797 nodeQueue->push(cond); 798 } 799 if (expr) 800 { 801 nodeQueue->push(expr); 802 } 803 if (body) 804 { 805 nodeQueue->push(body); 806 } 807 } 808 809 bool TIntermBranch::replaceChildNode( 810 TIntermNode *original, TIntermNode *replacement) 811 { 812 REPLACE_IF_IS(expression, TIntermTyped, original, replacement); 813 return false; 814 } 815 816 void TIntermBranch::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const 817 { 818 if (expression) 819 { 820 nodeQueue->push(expression); 821 } 822 } 823 824 bool TIntermBinary::replaceChildNode( 825 TIntermNode *original, TIntermNode *replacement) 826 { 827 REPLACE_IF_IS(left, TIntermTyped, original, replacement); 828 REPLACE_IF_IS(right, TIntermTyped, original, replacement); 829 return false; 830 } 831 832 void TIntermBinary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const 833 { 834 if (left) 835 { 836 nodeQueue->push(left); 837 } 838 if (right) 839 { 840 nodeQueue->push(right); 841 } 842 } 843 844 bool TIntermUnary::replaceChildNode( 845 TIntermNode *original, TIntermNode *replacement) 846 { 847 REPLACE_IF_IS(operand, TIntermTyped, original, replacement); 848 return false; 849 } 850 851 void TIntermUnary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const 852 { 853 if (operand) 854 { 855 nodeQueue->push(operand); 856 } 857 } 858 859 bool TIntermAggregate::replaceChildNode( 860 TIntermNode *original, TIntermNode *replacement) 861 { 862 for (size_t ii = 0; ii < sequence.size(); ++ii) 863 { 864 REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement); 865 } 866 return false; 867 } 868 869 void TIntermAggregate::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const 870 { 871 for (size_t childIndex = 0; childIndex < sequence.size(); childIndex++) 872 { 873 nodeQueue->push(sequence[childIndex]); 874 } 875 } 876 877 bool TIntermSelection::replaceChildNode( 878 TIntermNode *original, TIntermNode *replacement) 879 { 880 REPLACE_IF_IS(condition, TIntermTyped, original, replacement); 881 REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement); 882 REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement); 883 return false; 884 } 885 886 void TIntermSelection::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const 887 { 888 if (condition) 889 { 890 nodeQueue->push(condition); 891 } 892 if (trueBlock) 893 { 894 nodeQueue->push(trueBlock); 895 } 896 if (falseBlock) 897 { 898 nodeQueue->push(falseBlock); 899 } 900 } 901 902 // 903 // Say whether or not an operation node changes the value of a variable. 904 // 905 bool TIntermOperator::isAssignment() const 906 { 907 switch (op) { 908 case EOpPostIncrement: 909 case EOpPostDecrement: 910 case EOpPreIncrement: 911 case EOpPreDecrement: 912 case EOpAssign: 913 case EOpAddAssign: 914 case EOpSubAssign: 915 case EOpMulAssign: 916 case EOpVectorTimesMatrixAssign: 917 case EOpVectorTimesScalarAssign: 918 case EOpMatrixTimesScalarAssign: 919 case EOpMatrixTimesMatrixAssign: 920 case EOpDivAssign: 921 return true; 922 default: 923 return false; 924 } 925 } 926 927 // 928 // returns true if the operator is for one of the constructors 929 // 930 bool TIntermOperator::isConstructor() const 931 { 932 switch (op) { 933 case EOpConstructVec2: 934 case EOpConstructVec3: 935 case EOpConstructVec4: 936 case EOpConstructMat2: 937 case EOpConstructMat3: 938 case EOpConstructMat4: 939 case EOpConstructFloat: 940 case EOpConstructIVec2: 941 case EOpConstructIVec3: 942 case EOpConstructIVec4: 943 case EOpConstructInt: 944 case EOpConstructUVec2: 945 case EOpConstructUVec3: 946 case EOpConstructUVec4: 947 case EOpConstructUInt: 948 case EOpConstructBVec2: 949 case EOpConstructBVec3: 950 case EOpConstructBVec4: 951 case EOpConstructBool: 952 case EOpConstructStruct: 953 return true; 954 default: 955 return false; 956 } 957 } 958 959 // 960 // Make sure the type of a unary operator is appropriate for its 961 // combination of operation and operand type. 962 // 963 // Returns false in nothing makes sense. 964 // 965 bool TIntermUnary::promote(TInfoSink&) 966 { 967 switch (op) { 968 case EOpLogicalNot: 969 if (operand->getBasicType() != EbtBool) 970 return false; 971 break; 972 case EOpNegative: 973 case EOpPostIncrement: 974 case EOpPostDecrement: 975 case EOpPreIncrement: 976 case EOpPreDecrement: 977 if (operand->getBasicType() == EbtBool) 978 return false; 979 break; 980 981 // operators for built-ins are already type checked against their prototype 982 case EOpAny: 983 case EOpAll: 984 case EOpVectorLogicalNot: 985 return true; 986 987 default: 988 if (operand->getBasicType() != EbtFloat) 989 return false; 990 } 991 992 setType(operand->getType()); 993 type.setQualifier(EvqTemporary); 994 995 return true; 996 } 997 998 bool validateMultiplication(TOperator op, const TType &left, const TType &right) 999 { 1000 switch (op) 1001 { 1002 case EOpMul: 1003 case EOpMulAssign: 1004 return left.getNominalSize() == right.getNominalSize() && left.getSecondarySize() == right.getSecondarySize(); 1005 case EOpVectorTimesScalar: 1006 case EOpVectorTimesScalarAssign: 1007 return true; 1008 case EOpVectorTimesMatrix: 1009 return left.getNominalSize() == right.getRows(); 1010 case EOpVectorTimesMatrixAssign: 1011 return left.getNominalSize() == right.getRows() && left.getNominalSize() == right.getCols(); 1012 case EOpMatrixTimesVector: 1013 return left.getCols() == right.getNominalSize(); 1014 case EOpMatrixTimesScalar: 1015 case EOpMatrixTimesScalarAssign: 1016 return true; 1017 case EOpMatrixTimesMatrix: 1018 return left.getCols() == right.getRows(); 1019 case EOpMatrixTimesMatrixAssign: 1020 return left.getCols() == right.getCols() && left.getRows() == right.getRows(); 1021 1022 default: 1023 UNREACHABLE(); 1024 return false; 1025 } 1026 } 1027 1028 // 1029 // Establishes the type of the resultant operation, as well as 1030 // makes the operator the correct one for the operands. 1031 // 1032 // Returns false if operator can't work on operands. 1033 // 1034 bool TIntermBinary::promote(TInfoSink& infoSink) 1035 { 1036 // This function only handles scalars, vectors, and matrices. 1037 if (left->isArray() || right->isArray()) 1038 { 1039 infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); 1040 return false; 1041 } 1042 1043 // GLSL ES 2.0 does not support implicit type casting. 1044 // So the basic type should always match. 1045 if (left->getBasicType() != right->getBasicType()) 1046 return false; 1047 1048 // 1049 // Base assumption: just make the type the same as the left 1050 // operand. Then only deviations from this need be coded. 1051 // 1052 setType(left->getType()); 1053 1054 // The result gets promoted to the highest precision. 1055 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); 1056 getTypePointer()->setPrecision(higherPrecision); 1057 1058 // Binary operations results in temporary variables unless both 1059 // operands are const. 1060 if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) 1061 { 1062 getTypePointer()->setQualifier(EvqTemporary); 1063 } 1064 1065 const int nominalSize = std::max(left->getNominalSize(), right->getNominalSize()); 1066 1067 // 1068 // All scalars or structs. Code after this test assumes this case is removed! 1069 // 1070 if (nominalSize == 1) 1071 { 1072 switch (op) 1073 { 1074 // 1075 // Promote to conditional 1076 // 1077 case EOpEqual: 1078 case EOpNotEqual: 1079 case EOpLessThan: 1080 case EOpGreaterThan: 1081 case EOpLessThanEqual: 1082 case EOpGreaterThanEqual: 1083 setType(TType(EbtBool, EbpUndefined)); 1084 break; 1085 1086 // 1087 // And and Or operate on conditionals 1088 // 1089 case EOpLogicalAnd: 1090 case EOpLogicalOr: 1091 // Both operands must be of type bool. 1092 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) 1093 { 1094 return false; 1095 } 1096 setType(TType(EbtBool, EbpUndefined)); 1097 break; 1098 1099 default: 1100 break; 1101 } 1102 return true; 1103 } 1104 1105 // If we reach here, at least one of the operands is vector or matrix. 1106 // The other operand could be a scalar, vector, or matrix. 1107 // Can these two operands be combined? 1108 // 1109 TBasicType basicType = left->getBasicType(); 1110 switch (op) 1111 { 1112 case EOpMul: 1113 if (!left->isMatrix() && right->isMatrix()) 1114 { 1115 if (left->isVector()) 1116 { 1117 op = EOpVectorTimesMatrix; 1118 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), 1)); 1119 } 1120 else 1121 { 1122 op = EOpMatrixTimesScalar; 1123 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), right->getRows())); 1124 } 1125 } 1126 else if (left->isMatrix() && !right->isMatrix()) 1127 { 1128 if (right->isVector()) 1129 { 1130 op = EOpMatrixTimesVector; 1131 setType(TType(basicType, higherPrecision, EvqTemporary, left->getRows(), 1)); 1132 } 1133 else 1134 { 1135 op = EOpMatrixTimesScalar; 1136 } 1137 } 1138 else if (left->isMatrix() && right->isMatrix()) 1139 { 1140 op = EOpMatrixTimesMatrix; 1141 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows())); 1142 } 1143 else if (!left->isMatrix() && !right->isMatrix()) 1144 { 1145 if (left->isVector() && right->isVector()) 1146 { 1147 // leave as component product 1148 } 1149 else if (left->isVector() || right->isVector()) 1150 { 1151 op = EOpVectorTimesScalar; 1152 setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, 1)); 1153 } 1154 } 1155 else 1156 { 1157 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); 1158 return false; 1159 } 1160 1161 if (!validateMultiplication(op, left->getType(), right->getType())) 1162 { 1163 return false; 1164 } 1165 break; 1166 1167 case EOpMulAssign: 1168 if (!left->isMatrix() && right->isMatrix()) 1169 { 1170 if (left->isVector()) 1171 { 1172 op = EOpVectorTimesMatrixAssign; 1173 } 1174 else 1175 { 1176 return false; 1177 } 1178 } 1179 else if (left->isMatrix() && !right->isMatrix()) 1180 { 1181 if (right->isVector()) 1182 { 1183 return false; 1184 } 1185 else 1186 { 1187 op = EOpMatrixTimesScalarAssign; 1188 } 1189 } 1190 else if (left->isMatrix() && right->isMatrix()) 1191 { 1192 op = EOpMatrixTimesMatrixAssign; 1193 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows())); 1194 } 1195 else if (!left->isMatrix() && !right->isMatrix()) 1196 { 1197 if (left->isVector() && right->isVector()) 1198 { 1199 // leave as component product 1200 } 1201 else if (left->isVector() || right->isVector()) 1202 { 1203 if (! left->isVector()) 1204 return false; 1205 op = EOpVectorTimesScalarAssign; 1206 setType(TType(basicType, higherPrecision, EvqTemporary, left->getNominalSize(), 1)); 1207 } 1208 } 1209 else 1210 { 1211 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); 1212 return false; 1213 } 1214 1215 if (!validateMultiplication(op, left->getType(), right->getType())) 1216 { 1217 return false; 1218 } 1219 break; 1220 1221 case EOpAssign: 1222 case EOpInitialize: 1223 case EOpAdd: 1224 case EOpSub: 1225 case EOpDiv: 1226 case EOpAddAssign: 1227 case EOpSubAssign: 1228 case EOpDivAssign: 1229 { 1230 if ((left->isMatrix() && right->isVector()) || 1231 (left->isVector() && right->isMatrix())) 1232 return false; 1233 1234 // Are the sizes compatible? 1235 if (left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize()) 1236 { 1237 // If the nominal size of operands do not match: 1238 // One of them must be scalar. 1239 if (!left->isScalar() && !right->isScalar()) 1240 return false; 1241 1242 // Operator cannot be of type pure assignment. 1243 if (op == EOpAssign || op == EOpInitialize) 1244 return false; 1245 } 1246 1247 const int secondarySize = std::max(left->getSecondarySize(), right->getSecondarySize()); 1248 1249 setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize)); 1250 } 1251 break; 1252 1253 case EOpEqual: 1254 case EOpNotEqual: 1255 case EOpLessThan: 1256 case EOpGreaterThan: 1257 case EOpLessThanEqual: 1258 case EOpGreaterThanEqual: 1259 if ((left->getNominalSize() != right->getNominalSize()) || 1260 (left->getSecondarySize() != right->getSecondarySize())) 1261 return false; 1262 setType(TType(EbtBool, EbpUndefined)); 1263 break; 1264 1265 default: 1266 return false; 1267 } 1268 1269 return true; 1270 } 1271 1272 bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) 1273 { 1274 const TFieldList& fields = leftNodeType.getStruct()->fields(); 1275 1276 size_t structSize = fields.size(); 1277 size_t index = 0; 1278 1279 for (size_t j = 0; j < structSize; j++) { 1280 size_t size = fields[j]->type()->getObjectSize(); 1281 for (size_t i = 0; i < size; i++) { 1282 if (fields[j]->type()->getBasicType() == EbtStruct) { 1283 if (!CompareStructure(*fields[j]->type(), &rightUnionArray[index], &leftUnionArray[index])) 1284 return false; 1285 } else { 1286 if (leftUnionArray[index] != rightUnionArray[index]) 1287 return false; 1288 index++; 1289 } 1290 1291 } 1292 } 1293 return true; 1294 } 1295 1296 bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) 1297 { 1298 if (leftNodeType.isArray()) { 1299 TType typeWithoutArrayness = leftNodeType; 1300 typeWithoutArrayness.clearArrayness(); 1301 1302 size_t arraySize = leftNodeType.getArraySize(); 1303 1304 for (size_t i = 0; i < arraySize; ++i) { 1305 size_t offset = typeWithoutArrayness.getObjectSize() * i; 1306 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) 1307 return false; 1308 } 1309 } else 1310 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); 1311 1312 return true; 1313 } 1314 1315 // 1316 // The fold functions see if an operation on a constant can be done in place, 1317 // without generating run-time code. 1318 // 1319 // Returns the node to keep using, which may or may not be the node passed in. 1320 // 1321 1322 TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) 1323 { 1324 ConstantUnion *unionArray = getUnionArrayPointer(); 1325 1326 if (!unionArray) 1327 return 0; 1328 1329 size_t objectSize = getType().getObjectSize(); 1330 1331 if (constantNode) 1332 { 1333 // binary operations 1334 TIntermConstantUnion *node = constantNode->getAsConstantUnion(); 1335 ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); 1336 TType returnType = getType(); 1337 1338 if (!rightUnionArray) 1339 return 0; 1340 1341 // for a case like float f = 1.2 + vec4(2,3,4,5); 1342 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) 1343 { 1344 rightUnionArray = new ConstantUnion[objectSize]; 1345 for (size_t i = 0; i < objectSize; ++i) 1346 { 1347 rightUnionArray[i] = *node->getUnionArrayPointer(); 1348 } 1349 returnType = getType(); 1350 } 1351 else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) 1352 { 1353 // for a case like float f = vec4(2,3,4,5) + 1.2; 1354 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; 1355 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) 1356 { 1357 unionArray[i] = *getUnionArrayPointer(); 1358 } 1359 returnType = node->getType(); 1360 objectSize = constantNode->getType().getObjectSize(); 1361 } 1362 1363 ConstantUnion* tempConstArray = 0; 1364 TIntermConstantUnion *tempNode; 1365 1366 bool boolNodeFlag = false; 1367 switch(op) { 1368 case EOpAdd: 1369 tempConstArray = new ConstantUnion[objectSize]; 1370 { 1371 for (size_t i = 0; i < objectSize; i++) 1372 tempConstArray[i] = unionArray[i] + rightUnionArray[i]; 1373 } 1374 break; 1375 case EOpSub: 1376 tempConstArray = new ConstantUnion[objectSize]; 1377 { 1378 for (size_t i = 0; i < objectSize; i++) 1379 tempConstArray[i] = unionArray[i] - rightUnionArray[i]; 1380 } 1381 break; 1382 1383 case EOpMul: 1384 case EOpVectorTimesScalar: 1385 case EOpMatrixTimesScalar: 1386 tempConstArray = new ConstantUnion[objectSize]; 1387 { 1388 for (size_t i = 0; i < objectSize; i++) 1389 tempConstArray[i] = unionArray[i] * rightUnionArray[i]; 1390 } 1391 break; 1392 1393 case EOpMatrixTimesMatrix: 1394 { 1395 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) 1396 { 1397 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply"); 1398 return 0; 1399 } 1400 1401 const int leftCols = getCols(); 1402 const int leftRows = getRows(); 1403 const int rightCols = constantNode->getType().getCols(); 1404 const int rightRows = constantNode->getType().getRows(); 1405 const int resultCols = rightCols; 1406 const int resultRows = leftRows; 1407 1408 tempConstArray = new ConstantUnion[resultCols*resultRows]; 1409 for (int row = 0; row < resultRows; row++) 1410 { 1411 for (int column = 0; column < resultCols; column++) 1412 { 1413 tempConstArray[resultRows * column + row].setFConst(0.0f); 1414 for (int i = 0; i < leftCols; i++) 1415 { 1416 tempConstArray[resultRows * column + row].setFConst(tempConstArray[resultRows * column + row].getFConst() + unionArray[i * leftRows + row].getFConst() * (rightUnionArray[column * rightRows + i].getFConst())); 1417 } 1418 } 1419 } 1420 1421 // update return type for matrix product 1422 returnType.setPrimarySize(resultCols); 1423 returnType.setSecondarySize(resultRows); 1424 } 1425 break; 1426 1427 case EOpDiv: 1428 { 1429 tempConstArray = new ConstantUnion[objectSize]; 1430 for (size_t i = 0; i < objectSize; i++) 1431 { 1432 switch (getType().getBasicType()) 1433 { 1434 case EbtFloat: 1435 if (rightUnionArray[i] == 0.0f) 1436 { 1437 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); 1438 tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); 1439 } 1440 else 1441 { 1442 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); 1443 } 1444 break; 1445 1446 case EbtInt: 1447 if (rightUnionArray[i] == 0) 1448 { 1449 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); 1450 tempConstArray[i].setIConst(INT_MAX); 1451 } 1452 else 1453 { 1454 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); 1455 } 1456 break; 1457 1458 case EbtUInt: 1459 if (rightUnionArray[i] == 0) 1460 { 1461 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); 1462 tempConstArray[i].setUConst(UINT_MAX); 1463 } 1464 else 1465 { 1466 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst()); 1467 } 1468 break; 1469 1470 default: 1471 infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); 1472 return 0; 1473 } 1474 } 1475 } 1476 break; 1477 1478 case EOpMatrixTimesVector: 1479 { 1480 if (node->getBasicType() != EbtFloat) 1481 { 1482 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); 1483 return 0; 1484 } 1485 1486 const int matrixCols = getCols(); 1487 const int matrixRows = getRows(); 1488 1489 tempConstArray = new ConstantUnion[matrixRows]; 1490 1491 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) 1492 { 1493 tempConstArray[matrixRow].setFConst(0.0f); 1494 for (int col = 0; col < matrixCols; col++) 1495 { 1496 tempConstArray[matrixRow].setFConst(tempConstArray[matrixRow].getFConst() + ((unionArray[col * matrixRows + matrixRow].getFConst()) * rightUnionArray[col].getFConst())); 1497 } 1498 } 1499 1500 returnType = node->getType(); 1501 returnType.setPrimarySize(matrixRows); 1502 1503 tempNode = new TIntermConstantUnion(tempConstArray, returnType); 1504 tempNode->setLine(getLine()); 1505 1506 return tempNode; 1507 } 1508 1509 case EOpVectorTimesMatrix: 1510 { 1511 if (getType().getBasicType() != EbtFloat) 1512 { 1513 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix"); 1514 return 0; 1515 } 1516 1517 const int matrixCols = constantNode->getType().getCols(); 1518 const int matrixRows = constantNode->getType().getRows(); 1519 1520 tempConstArray = new ConstantUnion[matrixCols]; 1521 1522 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) 1523 { 1524 tempConstArray[matrixCol].setFConst(0.0f); 1525 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) 1526 { 1527 tempConstArray[matrixCol].setFConst(tempConstArray[matrixCol].getFConst() + ((unionArray[matrixRow].getFConst()) * rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst())); 1528 } 1529 } 1530 1531 returnType.setPrimarySize(matrixCols); 1532 } 1533 break; 1534 1535 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently 1536 { 1537 tempConstArray = new ConstantUnion[objectSize]; 1538 for (size_t i = 0; i < objectSize; i++) 1539 { 1540 tempConstArray[i] = unionArray[i] && rightUnionArray[i]; 1541 } 1542 } 1543 break; 1544 1545 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently 1546 { 1547 tempConstArray = new ConstantUnion[objectSize]; 1548 for (size_t i = 0; i < objectSize; i++) 1549 { 1550 tempConstArray[i] = unionArray[i] || rightUnionArray[i]; 1551 } 1552 } 1553 break; 1554 1555 case EOpLogicalXor: 1556 { 1557 tempConstArray = new ConstantUnion[objectSize]; 1558 for (size_t i = 0; i < objectSize; i++) 1559 { 1560 switch (getType().getBasicType()) 1561 { 1562 case EbtBool: 1563 tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); 1564 break; 1565 default: 1566 UNREACHABLE(); 1567 break; 1568 } 1569 } 1570 } 1571 break; 1572 1573 case EOpLessThan: 1574 assert(objectSize == 1); 1575 tempConstArray = new ConstantUnion[1]; 1576 tempConstArray->setBConst(*unionArray < *rightUnionArray); 1577 returnType = TType(EbtBool, EbpUndefined, EvqConst); 1578 break; 1579 1580 case EOpGreaterThan: 1581 assert(objectSize == 1); 1582 tempConstArray = new ConstantUnion[1]; 1583 tempConstArray->setBConst(*unionArray > *rightUnionArray); 1584 returnType = TType(EbtBool, EbpUndefined, EvqConst); 1585 break; 1586 1587 case EOpLessThanEqual: 1588 { 1589 assert(objectSize == 1); 1590 ConstantUnion constant; 1591 constant.setBConst(*unionArray > *rightUnionArray); 1592 tempConstArray = new ConstantUnion[1]; 1593 tempConstArray->setBConst(!constant.getBConst()); 1594 returnType = TType(EbtBool, EbpUndefined, EvqConst); 1595 break; 1596 } 1597 1598 case EOpGreaterThanEqual: 1599 { 1600 assert(objectSize == 1); 1601 ConstantUnion constant; 1602 constant.setBConst(*unionArray < *rightUnionArray); 1603 tempConstArray = new ConstantUnion[1]; 1604 tempConstArray->setBConst(!constant.getBConst()); 1605 returnType = TType(EbtBool, EbpUndefined, EvqConst); 1606 break; 1607 } 1608 1609 case EOpEqual: 1610 if (getType().getBasicType() == EbtStruct) 1611 { 1612 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) 1613 boolNodeFlag = true; 1614 } 1615 else 1616 { 1617 for (size_t i = 0; i < objectSize; i++) 1618 { 1619 if (unionArray[i] != rightUnionArray[i]) 1620 { 1621 boolNodeFlag = true; 1622 break; // break out of for loop 1623 } 1624 } 1625 } 1626 1627 tempConstArray = new ConstantUnion[1]; 1628 if (!boolNodeFlag) 1629 { 1630 tempConstArray->setBConst(true); 1631 } 1632 else 1633 { 1634 tempConstArray->setBConst(false); 1635 } 1636 1637 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); 1638 tempNode->setLine(getLine()); 1639 1640 return tempNode; 1641 1642 case EOpNotEqual: 1643 if (getType().getBasicType() == EbtStruct) 1644 { 1645 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) 1646 boolNodeFlag = true; 1647 } 1648 else 1649 { 1650 for (size_t i = 0; i < objectSize; i++) 1651 { 1652 if (unionArray[i] == rightUnionArray[i]) 1653 { 1654 boolNodeFlag = true; 1655 break; // break out of for loop 1656 } 1657 } 1658 } 1659 1660 tempConstArray = new ConstantUnion[1]; 1661 if (!boolNodeFlag) 1662 { 1663 tempConstArray->setBConst(true); 1664 } 1665 else 1666 { 1667 tempConstArray->setBConst(false); 1668 } 1669 1670 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); 1671 tempNode->setLine(getLine()); 1672 1673 return tempNode; 1674 1675 default: 1676 infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); 1677 return 0; 1678 } 1679 tempNode = new TIntermConstantUnion(tempConstArray, returnType); 1680 tempNode->setLine(getLine()); 1681 1682 return tempNode; 1683 } 1684 else 1685 { 1686 // 1687 // Do unary operations 1688 // 1689 TIntermConstantUnion *newNode = 0; 1690 ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; 1691 for (size_t i = 0; i < objectSize; i++) 1692 { 1693 switch(op) 1694 { 1695 case EOpNegative: 1696 switch (getType().getBasicType()) 1697 { 1698 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; 1699 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; 1700 case EbtUInt: tempConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break; 1701 default: 1702 infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); 1703 return 0; 1704 } 1705 break; 1706 1707 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently 1708 switch (getType().getBasicType()) 1709 { 1710 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; 1711 default: 1712 infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); 1713 return 0; 1714 } 1715 break; 1716 1717 default: 1718 return 0; 1719 } 1720 } 1721 newNode = new TIntermConstantUnion(tempConstArray, getType()); 1722 newNode->setLine(getLine()); 1723 return newNode; 1724 } 1725 } 1726 1727 TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) 1728 { 1729 size_t size = node->getType().getObjectSize(); 1730 1731 ConstantUnion *leftUnionArray = new ConstantUnion[size]; 1732 1733 for (size_t i=0; i < size; i++) { 1734 1735 switch (promoteTo) { 1736 case EbtFloat: 1737 switch (node->getType().getBasicType()) { 1738 case EbtInt: 1739 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i))); 1740 break; 1741 case EbtUInt: 1742 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i))); 1743 break; 1744 case EbtBool: 1745 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i))); 1746 break; 1747 case EbtFloat: 1748 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i))); 1749 break; 1750 default: 1751 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); 1752 return 0; 1753 } 1754 break; 1755 case EbtInt: 1756 switch (node->getType().getBasicType()) { 1757 case EbtInt: 1758 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i))); 1759 break; 1760 case EbtUInt: 1761 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i))); 1762 break; 1763 case EbtBool: 1764 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i))); 1765 break; 1766 case EbtFloat: 1767 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i))); 1768 break; 1769 default: 1770 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); 1771 return 0; 1772 } 1773 break; 1774 case EbtUInt: 1775 switch (node->getType().getBasicType()) { 1776 case EbtInt: 1777 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i))); 1778 break; 1779 case EbtUInt: 1780 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i))); 1781 break; 1782 case EbtBool: 1783 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i))); 1784 break; 1785 case EbtFloat: 1786 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i))); 1787 break; 1788 default: 1789 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); 1790 return 0; 1791 } 1792 break; 1793 case EbtBool: 1794 switch (node->getType().getBasicType()) { 1795 case EbtInt: 1796 leftUnionArray[i].setBConst(node->getIConst(i) != 0); 1797 break; 1798 case EbtUInt: 1799 leftUnionArray[i].setBConst(node->getUConst(i) != 0); 1800 break; 1801 case EbtBool: 1802 leftUnionArray[i].setBConst(node->getBConst(i)); 1803 break; 1804 case EbtFloat: 1805 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); 1806 break; 1807 default: 1808 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); 1809 return 0; 1810 } 1811 1812 break; 1813 default: 1814 infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); 1815 return 0; 1816 } 1817 1818 } 1819 1820 const TType& t = node->getType(); 1821 1822 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine()); 1823 } 1824 1825 // static 1826 TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction) 1827 { 1828 if (hashFunction == NULL || name.empty()) 1829 return name; 1830 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); 1831 TStringStream stream; 1832 stream << HASHED_NAME_PREFIX << std::hex << number; 1833 TString hashedName = stream.str(); 1834 return hashedName; 1835 } 1836