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