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