IntermNode.cpp (146403B)
1 // 2 // Copyright 2002 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 <math.h> 14 #include <stdlib.h> 15 #include <algorithm> 16 #include <vector> 17 18 #include "common/mathutil.h" 19 #include "common/matrix_utils.h" 20 #include "common/utilities.h" 21 #include "compiler/translator/Diagnostics.h" 22 #include "compiler/translator/ImmutableString.h" 23 #include "compiler/translator/IntermNode.h" 24 #include "compiler/translator/SymbolTable.h" 25 #include "compiler/translator/util.h" 26 27 namespace sh 28 { 29 30 namespace 31 { 32 33 const float kPi = 3.14159265358979323846f; 34 const float kDegreesToRadiansMultiplier = kPi / 180.0f; 35 const float kRadiansToDegreesMultiplier = 180.0f / kPi; 36 37 TPrecision GetHigherPrecision(TPrecision left, TPrecision right) 38 { 39 return left > right ? left : right; 40 } 41 42 TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size) 43 { 44 TConstantUnion *constUnion = new TConstantUnion[size]; 45 for (size_t i = 0; i < size; ++i) 46 constUnion[i] = constant; 47 48 return constUnion; 49 } 50 51 void UndefinedConstantFoldingError(const TSourceLoc &loc, 52 const TFunction *function, 53 TBasicType basicType, 54 TDiagnostics *diagnostics, 55 TConstantUnion *result) 56 { 57 diagnostics->warning(loc, "operation result is undefined for the values passed in", 58 function->name().data()); 59 60 switch (basicType) 61 { 62 case EbtFloat: 63 result->setFConst(0.0f); 64 break; 65 case EbtInt: 66 result->setIConst(0); 67 break; 68 case EbtUInt: 69 result->setUConst(0u); 70 break; 71 case EbtBool: 72 result->setBConst(false); 73 break; 74 default: 75 break; 76 } 77 } 78 79 float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize) 80 { 81 float result = 0.0f; 82 for (size_t i = 0; i < paramArraySize; i++) 83 { 84 float f = paramArray[i].getFConst(); 85 result += f * f; 86 } 87 return sqrtf(result); 88 } 89 90 float VectorDotProduct(const TConstantUnion *paramArray1, 91 const TConstantUnion *paramArray2, 92 size_t paramArraySize) 93 { 94 float result = 0.0f; 95 for (size_t i = 0; i < paramArraySize; i++) 96 result += paramArray1[i].getFConst() * paramArray2[i].getFConst(); 97 return result; 98 } 99 100 TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray, const TIntermTyped *originalNode) 101 { 102 ASSERT(constArray != nullptr); 103 // Note that we inherit whatever qualifier the folded node had. Nodes may be constant folded 104 // without being qualified as constant. 105 TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType()); 106 folded->setLine(originalNode->getLine()); 107 return folded; 108 } 109 110 angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, 111 const unsigned int rows, 112 const unsigned int cols) 113 { 114 std::vector<float> elements; 115 for (size_t i = 0; i < rows * cols; i++) 116 elements.push_back(paramArray[i].getFConst()); 117 // Transpose is used since the Matrix constructor expects arguments in row-major order, 118 // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below 119 // so that the created matrix will have the expected dimensions after the transpose. 120 return angle::Matrix<float>(elements, cols, rows).transpose(); 121 } 122 123 angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int size) 124 { 125 std::vector<float> elements; 126 for (size_t i = 0; i < size * size; i++) 127 elements.push_back(paramArray[i].getFConst()); 128 // Transpose is used since the Matrix constructor expects arguments in row-major order, 129 // whereas the paramArray is in column-major order. 130 return angle::Matrix<float>(elements, size).transpose(); 131 } 132 133 void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray) 134 { 135 // Transpose is used since the input Matrix is in row-major order, 136 // whereas the actual result should be in column-major order. 137 angle::Matrix<float> result = m.transpose(); 138 std::vector<float> resultElements = result.elements(); 139 for (size_t i = 0; i < resultElements.size(); i++) 140 resultArray[i].setFConst(resultElements[i]); 141 } 142 143 bool CanFoldAggregateBuiltInOp(TOperator op) 144 { 145 switch (op) 146 { 147 case EOpAtan: 148 case EOpPow: 149 case EOpMod: 150 case EOpMin: 151 case EOpMax: 152 case EOpClamp: 153 case EOpMix: 154 case EOpStep: 155 case EOpSmoothstep: 156 case EOpFma: 157 case EOpLdexp: 158 case EOpMatrixCompMult: 159 case EOpOuterProduct: 160 case EOpEqualComponentWise: 161 case EOpNotEqualComponentWise: 162 case EOpLessThanComponentWise: 163 case EOpLessThanEqualComponentWise: 164 case EOpGreaterThanComponentWise: 165 case EOpGreaterThanEqualComponentWise: 166 case EOpDistance: 167 case EOpDot: 168 case EOpCross: 169 case EOpFaceforward: 170 case EOpReflect: 171 case EOpRefract: 172 case EOpBitfieldExtract: 173 case EOpBitfieldInsert: 174 case EOpDFdx: 175 case EOpDFdy: 176 case EOpFwidth: 177 return true; 178 default: 179 return false; 180 } 181 } 182 183 void PropagatePrecisionIfApplicable(TIntermTyped *node, TPrecision precision) 184 { 185 if (precision == EbpUndefined || node->getPrecision() != EbpUndefined) 186 { 187 return; 188 } 189 190 if (IsPrecisionApplicableToType(node->getBasicType())) 191 { 192 node->propagatePrecision(precision); 193 } 194 } 195 196 } // namespace 197 198 //////////////////////////////////////////////////////////////// 199 // 200 // Member functions of the nodes used for building the tree. 201 // 202 //////////////////////////////////////////////////////////////// 203 204 TIntermExpression::TIntermExpression(const TType &t) : TIntermTyped(), mType(t) {} 205 206 #define REPLACE_IF_IS(node, type, original, replacement) \ 207 do \ 208 { \ 209 if (node == original) \ 210 { \ 211 node = static_cast<type *>(replacement); \ 212 return true; \ 213 } \ 214 } while (0) 215 216 size_t TIntermSymbol::getChildCount() const 217 { 218 return 0; 219 } 220 221 TIntermNode *TIntermSymbol::getChildNode(size_t index) const 222 { 223 UNREACHABLE(); 224 return nullptr; 225 } 226 227 size_t TIntermConstantUnion::getChildCount() const 228 { 229 return 0; 230 } 231 232 TIntermNode *TIntermConstantUnion::getChildNode(size_t index) const 233 { 234 UNREACHABLE(); 235 return nullptr; 236 } 237 238 size_t TIntermLoop::getChildCount() const 239 { 240 return (mInit ? 1 : 0) + (mCond ? 1 : 0) + (mExpr ? 1 : 0) + (mBody ? 1 : 0); 241 } 242 243 TIntermNode *TIntermLoop::getChildNode(size_t index) const 244 { 245 TIntermNode *children[4]; 246 unsigned int childIndex = 0; 247 if (mInit) 248 { 249 children[childIndex] = mInit; 250 ++childIndex; 251 } 252 if (mCond) 253 { 254 children[childIndex] = mCond; 255 ++childIndex; 256 } 257 if (mExpr) 258 { 259 children[childIndex] = mExpr; 260 ++childIndex; 261 } 262 if (mBody) 263 { 264 children[childIndex] = mBody; 265 ++childIndex; 266 } 267 ASSERT(index < childIndex); 268 return children[index]; 269 } 270 271 bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 272 { 273 ASSERT(original != nullptr); // This risks replacing multiple children. 274 REPLACE_IF_IS(mInit, TIntermNode, original, replacement); 275 REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); 276 REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); 277 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); 278 return false; 279 } 280 281 TIntermBranch::TIntermBranch(const TIntermBranch &node) 282 : TIntermBranch(node.mFlowOp, node.mExpression ? node.mExpression->deepCopy() : nullptr) 283 {} 284 285 size_t TIntermBranch::getChildCount() const 286 { 287 return (mExpression ? 1 : 0); 288 } 289 290 TIntermNode *TIntermBranch::getChildNode(size_t index) const 291 { 292 ASSERT(mExpression); 293 ASSERT(index == 0); 294 return mExpression; 295 } 296 297 bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 298 { 299 REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); 300 return false; 301 } 302 303 size_t TIntermSwizzle::getChildCount() const 304 { 305 return 1; 306 } 307 308 TIntermNode *TIntermSwizzle::getChildNode(size_t index) const 309 { 310 ASSERT(mOperand); 311 ASSERT(index == 0); 312 return mOperand; 313 } 314 315 bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 316 { 317 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); 318 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); 319 return false; 320 } 321 322 size_t TIntermBinary::getChildCount() const 323 { 324 return 2; 325 } 326 327 TIntermNode *TIntermBinary::getChildNode(size_t index) const 328 { 329 ASSERT(index < 2); 330 if (index == 0) 331 { 332 return mLeft; 333 } 334 return mRight; 335 } 336 337 bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 338 { 339 REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); 340 REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); 341 return false; 342 } 343 344 size_t TIntermUnary::getChildCount() const 345 { 346 return 1; 347 } 348 349 TIntermNode *TIntermUnary::getChildNode(size_t index) const 350 { 351 ASSERT(mOperand); 352 ASSERT(index == 0); 353 return mOperand; 354 } 355 356 bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 357 { 358 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); 359 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); 360 return false; 361 } 362 363 size_t TIntermGlobalQualifierDeclaration::getChildCount() const 364 { 365 return 1; 366 } 367 368 TIntermNode *TIntermGlobalQualifierDeclaration::getChildNode(size_t index) const 369 { 370 ASSERT(mSymbol); 371 ASSERT(index == 0); 372 return mSymbol; 373 } 374 375 bool TIntermGlobalQualifierDeclaration::replaceChildNode(TIntermNode *original, 376 TIntermNode *replacement) 377 { 378 REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement); 379 return false; 380 } 381 382 size_t TIntermFunctionDefinition::getChildCount() const 383 { 384 return 2; 385 } 386 387 TIntermNode *TIntermFunctionDefinition::getChildNode(size_t index) const 388 { 389 ASSERT(index < 2); 390 if (index == 0) 391 { 392 return mPrototype; 393 } 394 return mBody; 395 } 396 397 bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 398 { 399 REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement); 400 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); 401 return false; 402 } 403 404 size_t TIntermAggregate::getChildCount() const 405 { 406 return mArguments.size(); 407 } 408 409 TIntermNode *TIntermAggregate::getChildNode(size_t index) const 410 { 411 return mArguments[index]; 412 } 413 414 bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 415 { 416 return replaceChildNodeInternal(original, replacement); 417 } 418 419 TIntermBlock::TIntermBlock(const TIntermBlock &node) 420 { 421 for (TIntermNode *intermNode : node.mStatements) 422 { 423 mStatements.push_back(intermNode->deepCopy()); 424 } 425 426 ASSERT(!node.mIsTreeRoot); 427 mIsTreeRoot = false; 428 } 429 430 TIntermBlock::TIntermBlock(std::initializer_list<TIntermNode *> stmts) 431 { 432 for (TIntermNode *stmt : stmts) 433 { 434 appendStatement(stmt); 435 } 436 } 437 438 size_t TIntermBlock::getChildCount() const 439 { 440 return mStatements.size(); 441 } 442 443 TIntermNode *TIntermBlock::getChildNode(size_t index) const 444 { 445 return mStatements[index]; 446 } 447 448 bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 449 { 450 return replaceChildNodeInternal(original, replacement); 451 } 452 453 void TIntermBlock::replaceAllChildren(const TIntermSequence &newStatements) 454 { 455 mStatements.clear(); 456 mStatements.insert(mStatements.begin(), newStatements.begin(), newStatements.end()); 457 } 458 459 size_t TIntermFunctionPrototype::getChildCount() const 460 { 461 return 0; 462 } 463 464 TIntermNode *TIntermFunctionPrototype::getChildNode(size_t index) const 465 { 466 UNREACHABLE(); 467 return nullptr; 468 } 469 470 bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 471 { 472 return false; 473 } 474 475 TIntermDeclaration::TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr) 476 { 477 if (initExpr) 478 { 479 appendDeclarator( 480 new TIntermBinary(TOperator::EOpInitialize, new TIntermSymbol(var), initExpr)); 481 } 482 else 483 { 484 appendDeclarator(new TIntermSymbol(var)); 485 } 486 } 487 488 TIntermDeclaration::TIntermDeclaration(std::initializer_list<const TVariable *> declarators) 489 : TIntermDeclaration() 490 { 491 for (const TVariable *d : declarators) 492 { 493 appendDeclarator(new TIntermSymbol(d)); 494 } 495 } 496 497 TIntermDeclaration::TIntermDeclaration(std::initializer_list<TIntermTyped *> declarators) 498 : TIntermDeclaration() 499 { 500 for (TIntermTyped *d : declarators) 501 { 502 appendDeclarator(d); 503 } 504 } 505 506 size_t TIntermDeclaration::getChildCount() const 507 { 508 return mDeclarators.size(); 509 } 510 511 TIntermNode *TIntermDeclaration::getChildNode(size_t index) const 512 { 513 return mDeclarators[index]; 514 } 515 516 bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 517 { 518 return replaceChildNodeInternal(original, replacement); 519 } 520 521 TIntermDeclaration::TIntermDeclaration(const TIntermDeclaration &node) 522 { 523 for (TIntermNode *intermNode : node.mDeclarators) 524 { 525 mDeclarators.push_back(intermNode->deepCopy()); 526 } 527 } 528 529 bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement) 530 { 531 for (size_t ii = 0; ii < getSequence()->size(); ++ii) 532 { 533 REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement); 534 } 535 return false; 536 } 537 538 bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original, 539 const TIntermSequence &replacements) 540 { 541 for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it) 542 { 543 if (*it == original) 544 { 545 it = getSequence()->erase(it); 546 getSequence()->insert(it, replacements.begin(), replacements.end()); 547 return true; 548 } 549 } 550 return false; 551 } 552 553 bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position, 554 const TIntermSequence &insertions) 555 { 556 if (position > getSequence()->size()) 557 { 558 return false; 559 } 560 auto it = getSequence()->begin() + position; 561 getSequence()->insert(it, insertions.begin(), insertions.end()); 562 return true; 563 } 564 565 TIntermSymbol::TIntermSymbol(const TVariable *variable) : TIntermTyped(), mVariable(variable) {} 566 567 bool TIntermSymbol::hasConstantValue() const 568 { 569 return variable().getConstPointer() != nullptr; 570 } 571 572 const TConstantUnion *TIntermSymbol::getConstantValue() const 573 { 574 return variable().getConstPointer(); 575 } 576 577 const TSymbolUniqueId &TIntermSymbol::uniqueId() const 578 { 579 return mVariable->uniqueId(); 580 } 581 582 ImmutableString TIntermSymbol::getName() const 583 { 584 return mVariable->name(); 585 } 586 587 const TType &TIntermSymbol::getType() const 588 { 589 return mVariable->getType(); 590 } 591 592 void TIntermSymbol::propagatePrecision(TPrecision precision) 593 { 594 // Every declared variable should already have a precision. Some built-ins don't have a defined 595 // precision. This is not asserted however: 596 // 597 // - A shader with no precision specified either globally or on a variable will fail with a 598 // compilation error later on. 599 // - Transformations declaring variables without precision will be caught by AST validation. 600 } 601 602 TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func, 603 TIntermSequence *arguments) 604 { 605 return new TIntermAggregate(&func, func.getReturnType(), EOpCallFunctionInAST, arguments); 606 } 607 608 TIntermAggregate *TIntermAggregate::CreateRawFunctionCall(const TFunction &func, 609 TIntermSequence *arguments) 610 { 611 return new TIntermAggregate(&func, func.getReturnType(), EOpCallInternalRawFunction, arguments); 612 } 613 614 TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func, 615 TIntermSequence *arguments) 616 { 617 // Every built-in function should have an op. 618 ASSERT(func.getBuiltInOp() != EOpNull); 619 return new TIntermAggregate(&func, func.getReturnType(), func.getBuiltInOp(), arguments); 620 } 621 622 TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type, TIntermSequence *arguments) 623 { 624 return new TIntermAggregate(nullptr, type, EOpConstruct, arguments); 625 } 626 627 TIntermAggregate *TIntermAggregate::CreateConstructor( 628 const TType &type, 629 const std::initializer_list<TIntermNode *> &arguments) 630 { 631 TIntermSequence argSequence(arguments); 632 return CreateConstructor(type, &argSequence); 633 } 634 635 TIntermAggregate::TIntermAggregate(const TFunction *func, 636 const TType &type, 637 TOperator op, 638 TIntermSequence *arguments) 639 : TIntermOperator(op, type), mUseEmulatedFunction(false), mFunction(func) 640 { 641 if (arguments != nullptr) 642 { 643 mArguments.swap(*arguments); 644 } 645 ASSERT(mFunction == nullptr || mFunction->symbolType() != SymbolType::Empty); 646 setPrecisionAndQualifier(); 647 } 648 649 void TIntermAggregate::setPrecisionAndQualifier() 650 { 651 mType.setQualifier(EvqTemporary); 652 if ((!BuiltInGroup::IsBuiltIn(mOp) && !isFunctionCall()) || BuiltInGroup::IsMath(mOp)) 653 { 654 if (areChildrenConstQualified()) 655 { 656 mType.setQualifier(EvqConst); 657 } 658 } 659 660 propagatePrecision(derivePrecision()); 661 } 662 663 bool TIntermAggregate::areChildrenConstQualified() 664 { 665 for (TIntermNode *arg : mArguments) 666 { 667 TIntermTyped *typedArg = arg->getAsTyped(); 668 if (typedArg && typedArg->getQualifier() != EvqConst) 669 { 670 return false; 671 } 672 } 673 return true; 674 } 675 676 // Derive precision from children nodes 677 TPrecision TIntermAggregate::derivePrecision() const 678 { 679 if (getBasicType() == EbtBool || getBasicType() == EbtVoid || getBasicType() == EbtStruct) 680 { 681 return EbpUndefined; 682 } 683 684 // For AST function calls, take the qualifier from the declared one. 685 if (isFunctionCall()) 686 { 687 return mType.getPrecision(); 688 } 689 690 // Some built-ins explicitly specify their precision. 691 switch (mOp) 692 { 693 case EOpBitfieldExtract: 694 return mArguments[0]->getAsTyped()->getPrecision(); 695 case EOpBitfieldInsert: 696 return GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(), 697 mArguments[1]->getAsTyped()->getPrecision()); 698 case EOpTextureSize: 699 case EOpImageSize: 700 case EOpUaddCarry: 701 case EOpUsubBorrow: 702 case EOpUmulExtended: 703 case EOpImulExtended: 704 case EOpFrexp: 705 case EOpLdexp: 706 return EbpHigh; 707 default: 708 break; 709 } 710 711 // The rest of the math operations and constructors get their precision from their arguments. 712 if (BuiltInGroup::IsMath(mOp) || mOp == EOpConstruct) 713 { 714 TPrecision precision = EbpUndefined; 715 for (TIntermNode *argument : mArguments) 716 { 717 precision = GetHigherPrecision(argument->getAsTyped()->getPrecision(), precision); 718 } 719 return precision; 720 } 721 722 // Atomic operations return highp. 723 if (BuiltInGroup::IsImageAtomic(mOp) || BuiltInGroup::IsAtomicCounter(mOp) || 724 BuiltInGroup::IsAtomicMemory(mOp)) 725 { 726 return EbpHigh; 727 } 728 729 // Texture functions return the same precision as that of the sampler (textureSize returns 730 // highp, but that's handled above). imageLoad similar takes the precision of the image. The 731 // same is true for dFd*, interpolateAt* and subpassLoad operations. 732 if (BuiltInGroup::IsTexture(mOp) || BuiltInGroup::IsImageLoad(mOp) || 733 BuiltInGroup::IsDerivativesFS(mOp) || BuiltInGroup::IsInterpolationFS(mOp) || 734 mOp == EOpSubpassLoad) 735 { 736 return mArguments[0]->getAsTyped()->getPrecision(); 737 } 738 739 // Every possibility must be explicitly handled, except for desktop-GLSL-specific built-ins 740 // for which precision does't matter. 741 return EbpUndefined; 742 } 743 744 // Propagate precision to children nodes that don't already have it defined. 745 void TIntermAggregate::propagatePrecision(TPrecision precision) 746 { 747 mType.setPrecision(precision); 748 749 // For constructors, propagate precision to arguments. 750 if (isConstructor()) 751 { 752 for (TIntermNode *arg : mArguments) 753 { 754 PropagatePrecisionIfApplicable(arg->getAsTyped(), precision); 755 } 756 return; 757 } 758 759 // For function calls, propagate precision of each parameter to its corresponding argument. 760 if (isFunctionCall()) 761 { 762 for (size_t paramIndex = 0; paramIndex < mFunction->getParamCount(); ++paramIndex) 763 { 764 const TVariable *paramVariable = mFunction->getParam(paramIndex); 765 PropagatePrecisionIfApplicable(mArguments[paramIndex]->getAsTyped(), 766 paramVariable->getType().getPrecision()); 767 } 768 return; 769 } 770 771 // Some built-ins explicitly specify the precision of their parameters. 772 switch (mOp) 773 { 774 case EOpUaddCarry: 775 case EOpUsubBorrow: 776 case EOpUmulExtended: 777 case EOpImulExtended: 778 PropagatePrecisionIfApplicable(mArguments[0]->getAsTyped(), EbpHigh); 779 PropagatePrecisionIfApplicable(mArguments[1]->getAsTyped(), EbpHigh); 780 break; 781 case EOpFindMSB: 782 case EOpFrexp: 783 case EOpLdexp: 784 PropagatePrecisionIfApplicable(mArguments[0]->getAsTyped(), EbpHigh); 785 break; 786 default: 787 break; 788 } 789 } 790 791 const char *TIntermAggregate::functionName() const 792 { 793 ASSERT(!isConstructor()); 794 switch (mOp) 795 { 796 case EOpCallInternalRawFunction: 797 case EOpCallFunctionInAST: 798 return mFunction->name().data(); 799 default: 800 if (BuiltInGroup::IsBuiltIn(mOp)) 801 { 802 return mFunction->name().data(); 803 } 804 return GetOperatorString(mOp); 805 } 806 } 807 808 bool TIntermAggregate::hasConstantValue() const 809 { 810 if (!isConstructor()) 811 { 812 return false; 813 } 814 for (TIntermNode *constructorArg : mArguments) 815 { 816 if (!constructorArg->getAsTyped()->hasConstantValue()) 817 { 818 return false; 819 } 820 } 821 return true; 822 } 823 824 bool TIntermAggregate::isConstantNullValue() const 825 { 826 if (!isConstructor()) 827 { 828 return false; 829 } 830 for (TIntermNode *constructorArg : mArguments) 831 { 832 if (!constructorArg->getAsTyped()->isConstantNullValue()) 833 { 834 return false; 835 } 836 } 837 return true; 838 } 839 840 const TConstantUnion *TIntermAggregate::getConstantValue() const 841 { 842 if (!hasConstantValue()) 843 { 844 return nullptr; 845 } 846 ASSERT(isConstructor()); 847 ASSERT(mArguments.size() > 0u); 848 849 TConstantUnion *constArray = nullptr; 850 if (isArray()) 851 { 852 size_t elementSize = mArguments.front()->getAsTyped()->getType().getObjectSize(); 853 constArray = new TConstantUnion[elementSize * getOutermostArraySize()]; 854 855 size_t elementOffset = 0u; 856 for (TIntermNode *constructorArg : mArguments) 857 { 858 const TConstantUnion *elementConstArray = 859 constructorArg->getAsTyped()->getConstantValue(); 860 ASSERT(elementConstArray); 861 size_t elementSizeBytes = sizeof(TConstantUnion) * elementSize; 862 memcpy(static_cast<void *>(&constArray[elementOffset]), 863 static_cast<const void *>(elementConstArray), elementSizeBytes); 864 elementOffset += elementSize; 865 } 866 return constArray; 867 } 868 869 size_t resultSize = getType().getObjectSize(); 870 constArray = new TConstantUnion[resultSize]; 871 TBasicType basicType = getBasicType(); 872 873 size_t resultIndex = 0u; 874 875 if (mArguments.size() == 1u) 876 { 877 TIntermNode *argument = mArguments.front(); 878 TIntermTyped *argumentTyped = argument->getAsTyped(); 879 const TConstantUnion *argumentConstantValue = argumentTyped->getConstantValue(); 880 // Check the special case of constructing a matrix diagonal from a single scalar, 881 // or a vector from a single scalar. 882 if (argumentTyped->getType().getObjectSize() == 1u) 883 { 884 if (isMatrix()) 885 { 886 const uint8_t resultCols = getType().getCols(); 887 const uint8_t resultRows = getType().getRows(); 888 for (uint8_t col = 0; col < resultCols; ++col) 889 { 890 for (uint8_t row = 0; row < resultRows; ++row) 891 { 892 if (col == row) 893 { 894 constArray[resultIndex].cast(basicType, argumentConstantValue[0]); 895 } 896 else 897 { 898 constArray[resultIndex].setFConst(0.0f); 899 } 900 ++resultIndex; 901 } 902 } 903 } 904 else 905 { 906 while (resultIndex < resultSize) 907 { 908 constArray[resultIndex].cast(basicType, argumentConstantValue[0]); 909 ++resultIndex; 910 } 911 } 912 ASSERT(resultIndex == resultSize); 913 return constArray; 914 } 915 else if (isMatrix() && argumentTyped->isMatrix()) 916 { 917 // The special case of constructing a matrix from a matrix. 918 const uint8_t argumentCols = argumentTyped->getType().getCols(); 919 const uint8_t argumentRows = argumentTyped->getType().getRows(); 920 const uint8_t resultCols = getType().getCols(); 921 const uint8_t resultRows = getType().getRows(); 922 for (uint8_t col = 0; col < resultCols; ++col) 923 { 924 for (uint8_t row = 0; row < resultRows; ++row) 925 { 926 if (col < argumentCols && row < argumentRows) 927 { 928 constArray[resultIndex].cast( 929 basicType, argumentConstantValue[col * argumentRows + row]); 930 } 931 else if (col == row) 932 { 933 constArray[resultIndex].setFConst(1.0f); 934 } 935 else 936 { 937 constArray[resultIndex].setFConst(0.0f); 938 } 939 ++resultIndex; 940 } 941 } 942 ASSERT(resultIndex == resultSize); 943 return constArray; 944 } 945 } 946 947 for (TIntermNode *argument : mArguments) 948 { 949 TIntermTyped *argumentTyped = argument->getAsTyped(); 950 size_t argumentSize = argumentTyped->getType().getObjectSize(); 951 const TConstantUnion *argumentConstantValue = argumentTyped->getConstantValue(); 952 for (size_t i = 0u; i < argumentSize; ++i) 953 { 954 if (resultIndex >= resultSize) 955 break; 956 constArray[resultIndex].cast(basicType, argumentConstantValue[i]); 957 ++resultIndex; 958 } 959 } 960 ASSERT(resultIndex == resultSize); 961 return constArray; 962 } 963 964 bool TIntermAggregate::hasSideEffects() const 965 { 966 if (getQualifier() == EvqConst) 967 { 968 return false; 969 } 970 971 // If the function itself is known to have a side effect, the expression has a side effect. 972 const bool calledFunctionHasSideEffects = 973 mFunction != nullptr && !mFunction->isKnownToNotHaveSideEffects(); 974 975 if (calledFunctionHasSideEffects) 976 { 977 return true; 978 } 979 980 // Otherwise it only has a side effect if one of the arguments does. 981 for (TIntermNode *arg : mArguments) 982 { 983 if (arg->getAsTyped()->hasSideEffects()) 984 { 985 return true; 986 } 987 } 988 return false; 989 } 990 991 void TIntermBlock::appendStatement(TIntermNode *statement) 992 { 993 // Declaration nodes with no children can appear if it was an empty declaration or if all the 994 // declarators just added constants to the symbol table instead of generating code. We still 995 // need to add the declaration to the AST in that case because it might be relevant to the 996 // validity of switch/case. 997 if (statement != nullptr) 998 { 999 mStatements.push_back(statement); 1000 } 1001 } 1002 1003 void TIntermBlock::insertStatement(size_t insertPosition, TIntermNode *statement) 1004 { 1005 ASSERT(statement != nullptr); 1006 mStatements.insert(mStatements.begin() + insertPosition, statement); 1007 } 1008 1009 void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator) 1010 { 1011 ASSERT(declarator != nullptr); 1012 ASSERT(declarator->getAsSymbolNode() != nullptr || 1013 (declarator->getAsBinaryNode() != nullptr && 1014 declarator->getAsBinaryNode()->getOp() == EOpInitialize)); 1015 ASSERT(mDeclarators.empty() || 1016 declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType())); 1017 mDeclarators.push_back(declarator); 1018 } 1019 1020 size_t TIntermTernary::getChildCount() const 1021 { 1022 return 3; 1023 } 1024 1025 TIntermNode *TIntermTernary::getChildNode(size_t index) const 1026 { 1027 ASSERT(index < 3); 1028 if (index == 0) 1029 { 1030 return mCondition; 1031 } 1032 if (index == 1) 1033 { 1034 return mTrueExpression; 1035 } 1036 return mFalseExpression; 1037 } 1038 1039 bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 1040 { 1041 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); 1042 REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement); 1043 REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement); 1044 return false; 1045 } 1046 1047 size_t TIntermIfElse::getChildCount() const 1048 { 1049 return 1 + (mTrueBlock ? 1 : 0) + (mFalseBlock ? 1 : 0); 1050 } 1051 1052 TIntermNode *TIntermIfElse::getChildNode(size_t index) const 1053 { 1054 if (index == 0) 1055 { 1056 return mCondition; 1057 } 1058 if (mTrueBlock && index == 1) 1059 { 1060 return mTrueBlock; 1061 } 1062 return mFalseBlock; 1063 } 1064 1065 bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 1066 { 1067 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); 1068 REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement); 1069 REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement); 1070 return false; 1071 } 1072 1073 size_t TIntermSwitch::getChildCount() const 1074 { 1075 return 2; 1076 } 1077 1078 TIntermNode *TIntermSwitch::getChildNode(size_t index) const 1079 { 1080 ASSERT(index < 2); 1081 if (index == 0) 1082 { 1083 return mInit; 1084 } 1085 return mStatementList; 1086 } 1087 1088 bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 1089 { 1090 REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); 1091 REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement); 1092 ASSERT(mStatementList); 1093 return false; 1094 } 1095 1096 TIntermCase::TIntermCase(const TIntermCase &node) : TIntermCase(node.mCondition->deepCopy()) {} 1097 1098 size_t TIntermCase::getChildCount() const 1099 { 1100 return (mCondition ? 1 : 0); 1101 } 1102 1103 TIntermNode *TIntermCase::getChildNode(size_t index) const 1104 { 1105 ASSERT(index == 0); 1106 ASSERT(mCondition); 1107 return mCondition; 1108 } 1109 1110 bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement) 1111 { 1112 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); 1113 return false; 1114 } 1115 1116 TIntermTyped::TIntermTyped() : mIsPrecise(false) {} 1117 TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermTyped() 1118 { 1119 // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that 1120 // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy. 1121 // We need to manually copy any fields of TIntermNode. 1122 mLine = node.mLine; 1123 1124 // Once deteremined, the tree is not expected to transform. 1125 ASSERT(!mIsPrecise); 1126 } 1127 1128 bool TIntermTyped::hasConstantValue() const 1129 { 1130 return false; 1131 } 1132 1133 bool TIntermTyped::isConstantNullValue() const 1134 { 1135 return false; 1136 } 1137 1138 const TConstantUnion *TIntermTyped::getConstantValue() const 1139 { 1140 return nullptr; 1141 } 1142 1143 TPrecision TIntermTyped::derivePrecision() const 1144 { 1145 UNREACHABLE(); 1146 return EbpUndefined; 1147 } 1148 1149 void TIntermTyped::propagatePrecision(TPrecision precision) 1150 { 1151 UNREACHABLE(); 1152 } 1153 1154 TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) 1155 : TIntermExpression(node) 1156 { 1157 mUnionArrayPointer = node.mUnionArrayPointer; 1158 } 1159 1160 TIntermFunctionPrototype::TIntermFunctionPrototype(const TFunction *function) 1161 : TIntermTyped(), mFunction(function) 1162 { 1163 ASSERT(mFunction->symbolType() != SymbolType::Empty); 1164 } 1165 1166 const TType &TIntermFunctionPrototype::getType() const 1167 { 1168 return mFunction->getReturnType(); 1169 } 1170 1171 TIntermAggregate::TIntermAggregate(const TIntermAggregate &node) 1172 : TIntermOperator(node), 1173 mUseEmulatedFunction(node.mUseEmulatedFunction), 1174 mFunction(node.mFunction) 1175 { 1176 for (TIntermNode *arg : node.mArguments) 1177 { 1178 TIntermTyped *typedArg = arg->getAsTyped(); 1179 ASSERT(typedArg != nullptr); 1180 TIntermTyped *argCopy = typedArg->deepCopy(); 1181 mArguments.push_back(argCopy); 1182 } 1183 } 1184 1185 TIntermAggregate *TIntermAggregate::shallowCopy() const 1186 { 1187 TIntermSequence copySeq; 1188 copySeq.insert(copySeq.begin(), getSequence()->begin(), getSequence()->end()); 1189 TIntermAggregate *copyNode = new TIntermAggregate(mFunction, mType, mOp, ©Seq); 1190 copyNode->setLine(mLine); 1191 return copyNode; 1192 } 1193 1194 TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermExpression(node) 1195 { 1196 TIntermTyped *operandCopy = node.mOperand->deepCopy(); 1197 ASSERT(operandCopy != nullptr); 1198 mOperand = operandCopy; 1199 mSwizzleOffsets = node.mSwizzleOffsets; 1200 mHasFoldedDuplicateOffsets = node.mHasFoldedDuplicateOffsets; 1201 } 1202 1203 TIntermBinary::TIntermBinary(const TIntermBinary &node) : TIntermOperator(node) 1204 { 1205 TIntermTyped *leftCopy = node.mLeft->deepCopy(); 1206 TIntermTyped *rightCopy = node.mRight->deepCopy(); 1207 ASSERT(leftCopy != nullptr && rightCopy != nullptr); 1208 mLeft = leftCopy; 1209 mRight = rightCopy; 1210 } 1211 1212 TIntermUnary::TIntermUnary(const TIntermUnary &node) 1213 : TIntermOperator(node), 1214 mUseEmulatedFunction(node.mUseEmulatedFunction), 1215 mFunction(node.mFunction) 1216 { 1217 TIntermTyped *operandCopy = node.mOperand->deepCopy(); 1218 ASSERT(operandCopy != nullptr); 1219 mOperand = operandCopy; 1220 } 1221 1222 TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermExpression(node) 1223 { 1224 TIntermTyped *conditionCopy = node.mCondition->deepCopy(); 1225 TIntermTyped *trueCopy = node.mTrueExpression->deepCopy(); 1226 TIntermTyped *falseCopy = node.mFalseExpression->deepCopy(); 1227 ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr); 1228 mCondition = conditionCopy; 1229 mTrueExpression = trueCopy; 1230 mFalseExpression = falseCopy; 1231 } 1232 1233 bool TIntermOperator::isAssignment() const 1234 { 1235 return IsAssignment(mOp); 1236 } 1237 1238 bool TIntermOperator::isMultiplication() const 1239 { 1240 switch (mOp) 1241 { 1242 case EOpMul: 1243 case EOpMatrixTimesMatrix: 1244 case EOpMatrixTimesVector: 1245 case EOpMatrixTimesScalar: 1246 case EOpVectorTimesMatrix: 1247 case EOpVectorTimesScalar: 1248 return true; 1249 default: 1250 return false; 1251 } 1252 } 1253 1254 bool TIntermOperator::isConstructor() const 1255 { 1256 return (mOp == EOpConstruct); 1257 } 1258 1259 bool TIntermOperator::isFunctionCall() const 1260 { 1261 switch (mOp) 1262 { 1263 case EOpCallFunctionInAST: 1264 case EOpCallInternalRawFunction: 1265 return true; 1266 default: 1267 return false; 1268 } 1269 } 1270 1271 TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right) 1272 { 1273 if (left.isMatrix()) 1274 { 1275 if (right.isMatrix()) 1276 { 1277 return EOpMatrixTimesMatrix; 1278 } 1279 else 1280 { 1281 if (right.isVector()) 1282 { 1283 return EOpMatrixTimesVector; 1284 } 1285 else 1286 { 1287 return EOpMatrixTimesScalar; 1288 } 1289 } 1290 } 1291 else 1292 { 1293 if (right.isMatrix()) 1294 { 1295 if (left.isVector()) 1296 { 1297 return EOpVectorTimesMatrix; 1298 } 1299 else 1300 { 1301 return EOpMatrixTimesScalar; 1302 } 1303 } 1304 else 1305 { 1306 // Neither operand is a matrix. 1307 if (left.isVector() == right.isVector()) 1308 { 1309 // Leave as component product. 1310 return EOpMul; 1311 } 1312 else 1313 { 1314 return EOpVectorTimesScalar; 1315 } 1316 } 1317 } 1318 } 1319 1320 TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right) 1321 { 1322 if (left.isMatrix()) 1323 { 1324 if (right.isMatrix()) 1325 { 1326 return EOpMatrixTimesMatrixAssign; 1327 } 1328 else 1329 { 1330 // right should be scalar, but this may not be validated yet. 1331 return EOpMatrixTimesScalarAssign; 1332 } 1333 } 1334 else 1335 { 1336 if (right.isMatrix()) 1337 { 1338 // Left should be a vector, but this may not be validated yet. 1339 return EOpVectorTimesMatrixAssign; 1340 } 1341 else 1342 { 1343 // Neither operand is a matrix. 1344 if (left.isVector() == right.isVector()) 1345 { 1346 // Leave as component product. 1347 return EOpMulAssign; 1348 } 1349 else 1350 { 1351 // left should be vector and right should be scalar, but this may not be validated 1352 // yet. 1353 return EOpVectorTimesScalarAssign; 1354 } 1355 } 1356 } 1357 } 1358 1359 // 1360 // Make sure the type of a unary operator is appropriate for its 1361 // combination of operation and operand type. 1362 // 1363 void TIntermUnary::promote() 1364 { 1365 if (mOp == EOpArrayLength) 1366 { 1367 // Special case: the qualifier of .length() doesn't depend on the operand qualifier. 1368 setType(TType(EbtInt, EbpHigh, EvqConst)); 1369 return; 1370 } 1371 1372 TQualifier resultQualifier = EvqTemporary; 1373 if (mOperand->getQualifier() == EvqConst) 1374 resultQualifier = EvqConst; 1375 1376 TType resultType = mOperand->getType(); 1377 resultType.setQualifier(resultQualifier); 1378 1379 // Result is an intermediate value, so make sure it's identified as such. 1380 resultType.setInterfaceBlock(nullptr); 1381 1382 // Override type properties for special built-ins. Precision is determined later by 1383 // |derivePrecision|. 1384 switch (mOp) 1385 { 1386 case EOpFloatBitsToInt: 1387 resultType.setBasicType(EbtInt); 1388 break; 1389 case EOpFloatBitsToUint: 1390 resultType.setBasicType(EbtUInt); 1391 break; 1392 case EOpIntBitsToFloat: 1393 case EOpUintBitsToFloat: 1394 resultType.setBasicType(EbtFloat); 1395 break; 1396 case EOpPackSnorm2x16: 1397 case EOpPackUnorm2x16: 1398 case EOpPackHalf2x16: 1399 case EOpPackUnorm4x8: 1400 case EOpPackSnorm4x8: 1401 resultType.setBasicType(EbtUInt); 1402 resultType.setPrimarySize(1); 1403 break; 1404 case EOpUnpackSnorm2x16: 1405 case EOpUnpackUnorm2x16: 1406 case EOpUnpackHalf2x16: 1407 resultType.setBasicType(EbtFloat); 1408 resultType.setPrimarySize(2); 1409 break; 1410 case EOpUnpackUnorm4x8: 1411 case EOpUnpackSnorm4x8: 1412 resultType.setBasicType(EbtFloat); 1413 resultType.setPrimarySize(4); 1414 break; 1415 case EOpAny: 1416 case EOpAll: 1417 resultType.setBasicType(EbtBool); 1418 resultType.setPrimarySize(1); 1419 break; 1420 case EOpLength: 1421 case EOpDeterminant: 1422 resultType.setBasicType(EbtFloat); 1423 resultType.setPrimarySize(1); 1424 resultType.setSecondarySize(1); 1425 break; 1426 case EOpTranspose: 1427 ASSERT(resultType.getBasicType() == EbtFloat); 1428 resultType.setPrimarySize(mOperand->getType().getRows()); 1429 resultType.setSecondarySize(mOperand->getType().getCols()); 1430 break; 1431 case EOpIsinf: 1432 case EOpIsnan: 1433 resultType.setBasicType(EbtBool); 1434 break; 1435 case EOpBitCount: 1436 case EOpFindLSB: 1437 case EOpFindMSB: 1438 resultType.setBasicType(EbtInt); 1439 break; 1440 default: 1441 break; 1442 } 1443 1444 setType(resultType); 1445 propagatePrecision(derivePrecision()); 1446 } 1447 1448 // Derive precision from children nodes 1449 TPrecision TIntermUnary::derivePrecision() const 1450 { 1451 // Unary operators generally derive their precision from their operand, except for a few 1452 // built-ins where this is overriden. 1453 switch (mOp) 1454 { 1455 case EOpArrayLength: 1456 case EOpFloatBitsToInt: 1457 case EOpFloatBitsToUint: 1458 case EOpIntBitsToFloat: 1459 case EOpUintBitsToFloat: 1460 case EOpPackSnorm2x16: 1461 case EOpPackUnorm2x16: 1462 case EOpPackHalf2x16: 1463 case EOpPackUnorm4x8: 1464 case EOpPackSnorm4x8: 1465 case EOpUnpackSnorm2x16: 1466 case EOpUnpackUnorm2x16: 1467 case EOpBitfieldReverse: 1468 return EbpHigh; 1469 case EOpUnpackHalf2x16: 1470 case EOpUnpackUnorm4x8: 1471 case EOpUnpackSnorm4x8: 1472 return EbpMedium; 1473 case EOpBitCount: 1474 case EOpFindLSB: 1475 case EOpFindMSB: 1476 return EbpLow; 1477 case EOpAny: 1478 case EOpAll: 1479 case EOpIsinf: 1480 case EOpIsnan: 1481 return EbpUndefined; 1482 default: 1483 return mOperand->getPrecision(); 1484 } 1485 } 1486 1487 void TIntermUnary::propagatePrecision(TPrecision precision) 1488 { 1489 mType.setPrecision(precision); 1490 1491 // Generally precision of the operand and the precision of the result match. A few built-ins 1492 // are exceptional. 1493 switch (mOp) 1494 { 1495 case EOpArrayLength: 1496 case EOpPackSnorm2x16: 1497 case EOpPackUnorm2x16: 1498 case EOpPackUnorm4x8: 1499 case EOpPackSnorm4x8: 1500 case EOpPackHalf2x16: 1501 case EOpBitCount: 1502 case EOpFindLSB: 1503 case EOpFindMSB: 1504 case EOpIsinf: 1505 case EOpIsnan: 1506 // Precision of result does not affect the operand in any way. 1507 break; 1508 case EOpFloatBitsToInt: 1509 case EOpFloatBitsToUint: 1510 case EOpIntBitsToFloat: 1511 case EOpUintBitsToFloat: 1512 case EOpUnpackSnorm2x16: 1513 case EOpUnpackUnorm2x16: 1514 case EOpUnpackUnorm4x8: 1515 case EOpUnpackSnorm4x8: 1516 case EOpUnpackHalf2x16: 1517 case EOpBitfieldReverse: 1518 PropagatePrecisionIfApplicable(mOperand, EbpHigh); 1519 break; 1520 default: 1521 PropagatePrecisionIfApplicable(mOperand, precision); 1522 } 1523 } 1524 1525 TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets) 1526 : TIntermExpression(TType(EbtFloat, EbpUndefined)), 1527 mOperand(operand), 1528 mSwizzleOffsets(swizzleOffsets), 1529 mHasFoldedDuplicateOffsets(false) 1530 { 1531 ASSERT(mOperand); 1532 ASSERT(mOperand->getType().isVector()); 1533 ASSERT(mSwizzleOffsets.size() <= 4); 1534 promote(); 1535 } 1536 1537 TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function) 1538 : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function) 1539 { 1540 ASSERT(mOperand); 1541 ASSERT(!BuiltInGroup::IsBuiltIn(op) || (function != nullptr && function->getBuiltInOp() == op)); 1542 promote(); 1543 } 1544 1545 TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right) 1546 : TIntermOperator(op), mLeft(left), mRight(right) 1547 { 1548 ASSERT(mLeft); 1549 ASSERT(mRight); 1550 promote(); 1551 } 1552 1553 TIntermBinary *TIntermBinary::CreateComma(TIntermTyped *left, 1554 TIntermTyped *right, 1555 int shaderVersion) 1556 { 1557 TIntermBinary *node = new TIntermBinary(EOpComma, left, right); 1558 node->getTypePointer()->setQualifier(GetCommaQualifier(shaderVersion, left, right)); 1559 return node; 1560 } 1561 1562 TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol, 1563 bool isPrecise, 1564 const TSourceLoc &line) 1565 : TIntermNode(), mSymbol(symbol), mIsPrecise(isPrecise) 1566 { 1567 ASSERT(symbol); 1568 setLine(line); 1569 } 1570 1571 TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration( 1572 const TIntermGlobalQualifierDeclaration &node) 1573 : TIntermGlobalQualifierDeclaration(static_cast<TIntermSymbol *>(node.mSymbol->deepCopy()), 1574 node.mIsPrecise, 1575 node.mLine) 1576 {} 1577 1578 TIntermTernary::TIntermTernary(TIntermTyped *cond, 1579 TIntermTyped *trueExpression, 1580 TIntermTyped *falseExpression) 1581 : TIntermExpression(trueExpression->getType()), 1582 mCondition(cond), 1583 mTrueExpression(trueExpression), 1584 mFalseExpression(falseExpression) 1585 { 1586 ASSERT(mCondition); 1587 ASSERT(mTrueExpression); 1588 ASSERT(mFalseExpression); 1589 getTypePointer()->setQualifier( 1590 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression)); 1591 1592 propagatePrecision(derivePrecision()); 1593 } 1594 1595 TIntermLoop::TIntermLoop(TLoopType type, 1596 TIntermNode *init, 1597 TIntermTyped *cond, 1598 TIntermTyped *expr, 1599 TIntermBlock *body) 1600 : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body) 1601 { 1602 // Declaration nodes with no children can appear if all the declarators just added constants to 1603 // the symbol table instead of generating code. They're no-ops so don't add them to the tree. 1604 if (mInit && mInit->getAsDeclarationNode() && 1605 mInit->getAsDeclarationNode()->getSequence()->empty()) 1606 { 1607 mInit = nullptr; 1608 } 1609 } 1610 1611 TIntermLoop::TIntermLoop(const TIntermLoop &node) 1612 : TIntermLoop(node.mType, 1613 node.mInit ? node.mInit->deepCopy() : nullptr, 1614 node.mCond ? node.mCond->deepCopy() : nullptr, 1615 node.mExpr ? node.mExpr->deepCopy() : nullptr, 1616 node.mBody ? node.mBody->deepCopy() : nullptr) 1617 {} 1618 1619 TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB) 1620 : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB) 1621 { 1622 ASSERT(mCondition); 1623 // Prune empty false blocks so that there won't be unnecessary operations done on it. 1624 if (mFalseBlock && mFalseBlock->getSequence()->empty()) 1625 { 1626 mFalseBlock = nullptr; 1627 } 1628 } 1629 1630 TIntermIfElse::TIntermIfElse(const TIntermIfElse &node) 1631 : TIntermIfElse(node.mCondition->deepCopy(), 1632 node.mTrueBlock->deepCopy(), 1633 node.mFalseBlock ? node.mFalseBlock->deepCopy() : nullptr) 1634 {} 1635 1636 TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList) 1637 : TIntermNode(), mInit(init), mStatementList(statementList) 1638 { 1639 ASSERT(mInit); 1640 ASSERT(mStatementList); 1641 } 1642 1643 TIntermSwitch::TIntermSwitch(const TIntermSwitch &node) 1644 : TIntermSwitch(node.mInit->deepCopy(), node.mStatementList->deepCopy()) 1645 {} 1646 1647 void TIntermSwitch::setStatementList(TIntermBlock *statementList) 1648 { 1649 ASSERT(statementList); 1650 mStatementList = statementList; 1651 } 1652 1653 // static 1654 TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond, 1655 TIntermTyped *trueExpression, 1656 TIntermTyped *falseExpression) 1657 { 1658 if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst && 1659 falseExpression->getQualifier() == EvqConst) 1660 { 1661 return EvqConst; 1662 } 1663 return EvqTemporary; 1664 } 1665 1666 // Derive precision from children nodes 1667 TPrecision TIntermTernary::derivePrecision() const 1668 { 1669 return GetHigherPrecision(mTrueExpression->getPrecision(), mFalseExpression->getPrecision()); 1670 } 1671 1672 void TIntermTernary::propagatePrecision(TPrecision precision) 1673 { 1674 mType.setPrecision(precision); 1675 1676 PropagatePrecisionIfApplicable(mTrueExpression, precision); 1677 PropagatePrecisionIfApplicable(mFalseExpression, precision); 1678 } 1679 1680 TIntermTyped *TIntermTernary::fold(TDiagnostics * /* diagnostics */) 1681 { 1682 if (mCondition->getAsConstantUnion()) 1683 { 1684 if (mCondition->getAsConstantUnion()->getBConst(0)) 1685 { 1686 return mTrueExpression; 1687 } 1688 else 1689 { 1690 return mFalseExpression; 1691 } 1692 } 1693 return this; 1694 } 1695 1696 void TIntermSwizzle::promote() 1697 { 1698 TQualifier resultQualifier = EvqTemporary; 1699 if (mOperand->getQualifier() == EvqConst) 1700 resultQualifier = EvqConst; 1701 1702 size_t numFields = mSwizzleOffsets.size(); 1703 setType(TType(mOperand->getBasicType(), EbpUndefined, resultQualifier, 1704 static_cast<uint8_t>(numFields))); 1705 propagatePrecision(derivePrecision()); 1706 } 1707 1708 // Derive precision from children nodes 1709 TPrecision TIntermSwizzle::derivePrecision() const 1710 { 1711 return mOperand->getPrecision(); 1712 } 1713 1714 void TIntermSwizzle::propagatePrecision(TPrecision precision) 1715 { 1716 mType.setPrecision(precision); 1717 1718 PropagatePrecisionIfApplicable(mOperand, precision); 1719 } 1720 1721 bool TIntermSwizzle::hasDuplicateOffsets() const 1722 { 1723 if (mHasFoldedDuplicateOffsets) 1724 { 1725 return true; 1726 } 1727 int offsetCount[4] = {0u, 0u, 0u, 0u}; 1728 for (const auto offset : mSwizzleOffsets) 1729 { 1730 offsetCount[offset]++; 1731 if (offsetCount[offset] > 1) 1732 { 1733 return true; 1734 } 1735 } 1736 return false; 1737 } 1738 1739 void TIntermSwizzle::setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets) 1740 { 1741 mHasFoldedDuplicateOffsets = hasFoldedDuplicateOffsets; 1742 } 1743 1744 bool TIntermSwizzle::offsetsMatch(int offset) const 1745 { 1746 return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset; 1747 } 1748 1749 void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const 1750 { 1751 for (const int offset : mSwizzleOffsets) 1752 { 1753 switch (offset) 1754 { 1755 case 0: 1756 *out << "x"; 1757 break; 1758 case 1: 1759 *out << "y"; 1760 break; 1761 case 2: 1762 *out << "z"; 1763 break; 1764 case 3: 1765 *out << "w"; 1766 break; 1767 default: 1768 UNREACHABLE(); 1769 } 1770 } 1771 } 1772 1773 TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion, 1774 const TIntermTyped *left, 1775 const TIntermTyped *right) 1776 { 1777 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression. 1778 if (shaderVersion >= 300 || left->getQualifier() != EvqConst || 1779 right->getQualifier() != EvqConst) 1780 { 1781 return EvqTemporary; 1782 } 1783 return EvqConst; 1784 } 1785 1786 // Establishes the type of the result of the binary operation. 1787 void TIntermBinary::promote() 1788 { 1789 ASSERT(!isMultiplication() || 1790 mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType())); 1791 1792 // Comma is handled as a special case. Note that the comma node qualifier depends on the shader 1793 // version and so is not being set here. 1794 if (mOp == EOpComma) 1795 { 1796 setType(mRight->getType()); 1797 return; 1798 } 1799 1800 // Base assumption: just make the type the same as the left 1801 // operand. Then only deviations from this need be coded. 1802 setType(mLeft->getType()); 1803 1804 TQualifier resultQualifier = EvqConst; 1805 // Binary operations results in temporary variables unless both 1806 // operands are const. If initializing a specialization constant, make the declarator also 1807 // EvqSpecConst. 1808 const bool isSpecConstInit = mOp == EOpInitialize && mLeft->getQualifier() == EvqSpecConst; 1809 const bool isEitherNonConst = 1810 mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst; 1811 if (!isSpecConstInit && isEitherNonConst) 1812 { 1813 resultQualifier = EvqTemporary; 1814 getTypePointer()->setQualifier(EvqTemporary); 1815 } 1816 1817 // Result is an intermediate value, so make sure it's identified as such. That's not true for 1818 // interface block arrays being indexed. 1819 if (mOp != EOpIndexDirect && mOp != EOpIndexIndirect) 1820 { 1821 getTypePointer()->setInterfaceBlock(nullptr); 1822 } 1823 1824 // Handle indexing ops. 1825 switch (mOp) 1826 { 1827 case EOpIndexDirect: 1828 case EOpIndexIndirect: 1829 if (mLeft->isArray()) 1830 { 1831 mType.toArrayElementType(); 1832 } 1833 else if (mLeft->isMatrix()) 1834 { 1835 mType.toMatrixColumnType(); 1836 } 1837 else if (mLeft->isVector()) 1838 { 1839 mType.toComponentType(); 1840 } 1841 else 1842 { 1843 UNREACHABLE(); 1844 } 1845 return; 1846 case EOpIndexDirectStruct: 1847 { 1848 const TFieldList &fields = mLeft->getType().getStruct()->fields(); 1849 const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0); 1850 setType(*fields[fieldIndex]->type()); 1851 getTypePointer()->setQualifier(resultQualifier); 1852 return; 1853 } 1854 case EOpIndexDirectInterfaceBlock: 1855 { 1856 const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields(); 1857 const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0); 1858 setType(*fields[fieldIndex]->type()); 1859 getTypePointer()->setQualifier(resultQualifier); 1860 return; 1861 } 1862 default: 1863 break; 1864 } 1865 1866 ASSERT(mLeft->isArray() == mRight->isArray()); 1867 1868 const uint8_t nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize()); 1869 1870 switch (mOp) 1871 { 1872 case EOpMul: 1873 break; 1874 case EOpMatrixTimesScalar: 1875 if (mRight->isMatrix()) 1876 { 1877 getTypePointer()->setPrimarySize(mRight->getCols()); 1878 getTypePointer()->setSecondarySize(mRight->getRows()); 1879 } 1880 break; 1881 case EOpMatrixTimesVector: 1882 getTypePointer()->setPrimarySize(mLeft->getRows()); 1883 getTypePointer()->setSecondarySize(1); 1884 break; 1885 case EOpMatrixTimesMatrix: 1886 getTypePointer()->setPrimarySize(mRight->getCols()); 1887 getTypePointer()->setSecondarySize(mLeft->getRows()); 1888 break; 1889 case EOpVectorTimesScalar: 1890 getTypePointer()->setPrimarySize(nominalSize); 1891 break; 1892 case EOpVectorTimesMatrix: 1893 getTypePointer()->setPrimarySize(mRight->getCols()); 1894 ASSERT(getType().getSecondarySize() == 1); 1895 break; 1896 case EOpMulAssign: 1897 case EOpVectorTimesScalarAssign: 1898 case EOpVectorTimesMatrixAssign: 1899 case EOpMatrixTimesScalarAssign: 1900 case EOpMatrixTimesMatrixAssign: 1901 ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType())); 1902 break; 1903 case EOpAssign: 1904 case EOpInitialize: 1905 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && 1906 (mLeft->getSecondarySize() == mRight->getSecondarySize())); 1907 break; 1908 case EOpAdd: 1909 case EOpSub: 1910 case EOpDiv: 1911 case EOpIMod: 1912 case EOpBitShiftLeft: 1913 case EOpBitShiftRight: 1914 case EOpBitwiseAnd: 1915 case EOpBitwiseXor: 1916 case EOpBitwiseOr: 1917 case EOpAddAssign: 1918 case EOpSubAssign: 1919 case EOpDivAssign: 1920 case EOpIModAssign: 1921 case EOpBitShiftLeftAssign: 1922 case EOpBitShiftRightAssign: 1923 case EOpBitwiseAndAssign: 1924 case EOpBitwiseXorAssign: 1925 case EOpBitwiseOrAssign: 1926 { 1927 ASSERT(!mLeft->isArray() && !mRight->isArray()); 1928 const uint8_t secondarySize = 1929 std::max(mLeft->getSecondarySize(), mRight->getSecondarySize()); 1930 getTypePointer()->setPrimarySize(nominalSize); 1931 getTypePointer()->setSecondarySize(secondarySize); 1932 break; 1933 } 1934 case EOpEqual: 1935 case EOpNotEqual: 1936 case EOpLessThan: 1937 case EOpGreaterThan: 1938 case EOpLessThanEqual: 1939 case EOpGreaterThanEqual: 1940 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && 1941 (mLeft->getSecondarySize() == mRight->getSecondarySize())); 1942 setType(TType(EbtBool, EbpUndefined, resultQualifier)); 1943 break; 1944 1945 // 1946 // And and Or operate on conditionals 1947 // 1948 case EOpLogicalAnd: 1949 case EOpLogicalXor: 1950 case EOpLogicalOr: 1951 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); 1952 break; 1953 1954 case EOpIndexDirect: 1955 case EOpIndexIndirect: 1956 case EOpIndexDirectInterfaceBlock: 1957 case EOpIndexDirectStruct: 1958 // These ops should be already fully handled. 1959 UNREACHABLE(); 1960 break; 1961 default: 1962 UNREACHABLE(); 1963 break; 1964 } 1965 1966 propagatePrecision(derivePrecision()); 1967 } 1968 1969 // Derive precision from children nodes 1970 TPrecision TIntermBinary::derivePrecision() const 1971 { 1972 // Assignments use the type and precision of the lvalue-expression 1973 // GLSL ES spec section 5.8: Assignments 1974 // "The assignment operator stores the value of rvalue-expression into the l-value and returns 1975 // an r-value with the type and precision of lvalue-expression." 1976 if (IsAssignment(mOp)) 1977 { 1978 return mLeft->getPrecision(); 1979 } 1980 1981 const TPrecision higherPrecision = 1982 GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision()); 1983 1984 switch (mOp) 1985 { 1986 case EOpComma: 1987 // Comma takes the right node's value. 1988 return mRight->getPrecision(); 1989 1990 case EOpIndexDirect: 1991 case EOpIndexIndirect: 1992 case EOpBitShiftLeft: 1993 case EOpBitShiftRight: 1994 // When indexing an array, the precision of the array is preserved (which is the left 1995 // node). 1996 // For shift operations, the precision is derived from the expression being shifted 1997 // (which is also the left node). 1998 return mLeft->getPrecision(); 1999 2000 case EOpIndexDirectStruct: 2001 case EOpIndexDirectInterfaceBlock: 2002 { 2003 // When selecting the field of a block, the precision is taken from the field's 2004 // declaration. 2005 const TFieldList &fields = mOp == EOpIndexDirectStruct 2006 ? mLeft->getType().getStruct()->fields() 2007 : mLeft->getType().getInterfaceBlock()->fields(); 2008 const int fieldIndex = mRight->getAsConstantUnion()->getIConst(0); 2009 return fields[fieldIndex]->type()->getPrecision(); 2010 } 2011 2012 case EOpEqual: 2013 case EOpNotEqual: 2014 case EOpLessThan: 2015 case EOpGreaterThan: 2016 case EOpLessThanEqual: 2017 case EOpGreaterThanEqual: 2018 case EOpLogicalAnd: 2019 case EOpLogicalXor: 2020 case EOpLogicalOr: 2021 // No precision specified on bool results. 2022 return EbpUndefined; 2023 2024 default: 2025 // All other operations are evaluated at the higher of the two operands' precisions. 2026 return higherPrecision; 2027 } 2028 } 2029 2030 void TIntermBinary::propagatePrecision(TPrecision precision) 2031 { 2032 getTypePointer()->setPrecision(precision); 2033 2034 if (mOp != EOpComma) 2035 { 2036 PropagatePrecisionIfApplicable(mLeft, precision); 2037 } 2038 2039 if (mOp != EOpIndexDirect && mOp != EOpIndexIndirect && mOp != EOpIndexDirectStruct && 2040 mOp != EOpIndexDirectInterfaceBlock) 2041 { 2042 PropagatePrecisionIfApplicable(mRight, precision); 2043 } 2044 2045 // For indices, always apply highp. This is purely for the purpose of making sure constant and 2046 // constructor nodes are also given a precision, so if they are hoisted to a temp variable, 2047 // there would be a precision to apply to that variable. 2048 if (mOp == EOpIndexDirect || mOp == EOpIndexIndirect) 2049 { 2050 PropagatePrecisionIfApplicable(mRight, EbpHigh); 2051 } 2052 } 2053 2054 bool TIntermConstantUnion::hasConstantValue() const 2055 { 2056 return true; 2057 } 2058 2059 bool TIntermConstantUnion::isConstantNullValue() const 2060 { 2061 const size_t size = mType.getObjectSize(); 2062 for (size_t index = 0; index < size; ++index) 2063 { 2064 if (!mUnionArrayPointer[index].isZero()) 2065 { 2066 return false; 2067 } 2068 } 2069 return true; 2070 } 2071 2072 const TConstantUnion *TIntermConstantUnion::getConstantValue() const 2073 { 2074 return mUnionArrayPointer; 2075 } 2076 2077 const TConstantUnion *TIntermConstantUnion::FoldIndexing(const TType &type, 2078 const TConstantUnion *constArray, 2079 int index) 2080 { 2081 if (type.isArray()) 2082 { 2083 ASSERT(index < static_cast<int>(type.getOutermostArraySize())); 2084 TType arrayElementType(type); 2085 arrayElementType.toArrayElementType(); 2086 size_t arrayElementSize = arrayElementType.getObjectSize(); 2087 return &constArray[arrayElementSize * index]; 2088 } 2089 else if (type.isMatrix()) 2090 { 2091 ASSERT(index < type.getCols()); 2092 const uint8_t size = type.getRows(); 2093 return &constArray[size * index]; 2094 } 2095 else if (type.isVector()) 2096 { 2097 ASSERT(index < type.getNominalSize()); 2098 return &constArray[index]; 2099 } 2100 else 2101 { 2102 UNREACHABLE(); 2103 return nullptr; 2104 } 2105 } 2106 2107 TIntermTyped *TIntermSwizzle::fold(TDiagnostics * /* diagnostics */) 2108 { 2109 TIntermSwizzle *operandSwizzle = mOperand->getAsSwizzleNode(); 2110 if (operandSwizzle) 2111 { 2112 // We need to fold the two swizzles into one, so that repeated swizzling can't cause stack 2113 // overflow in ParseContext::checkCanBeLValue(). 2114 bool hadDuplicateOffsets = operandSwizzle->hasDuplicateOffsets(); 2115 TVector<int> foldedOffsets; 2116 for (int offset : mSwizzleOffsets) 2117 { 2118 // Offset should already be validated. 2119 ASSERT(static_cast<size_t>(offset) < operandSwizzle->mSwizzleOffsets.size()); 2120 foldedOffsets.push_back(operandSwizzle->mSwizzleOffsets[offset]); 2121 } 2122 operandSwizzle->mSwizzleOffsets = foldedOffsets; 2123 operandSwizzle->setType(getType()); 2124 operandSwizzle->setHasFoldedDuplicateOffsets(hadDuplicateOffsets); 2125 return operandSwizzle; 2126 } 2127 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); 2128 if (operandConstant == nullptr) 2129 { 2130 return this; 2131 } 2132 2133 TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()]; 2134 for (size_t i = 0; i < mSwizzleOffsets.size(); ++i) 2135 { 2136 constArray[i] = *TIntermConstantUnion::FoldIndexing( 2137 operandConstant->getType(), operandConstant->getConstantValue(), mSwizzleOffsets.at(i)); 2138 } 2139 return CreateFoldedNode(constArray, this); 2140 } 2141 2142 TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) 2143 { 2144 const TConstantUnion *rightConstant = mRight->getConstantValue(); 2145 switch (mOp) 2146 { 2147 case EOpComma: 2148 { 2149 if (mLeft->hasSideEffects()) 2150 { 2151 return this; 2152 } 2153 return mRight; 2154 } 2155 case EOpIndexDirect: 2156 case EOpIndexDirectStruct: 2157 { 2158 if (rightConstant == nullptr) 2159 { 2160 return this; 2161 } 2162 size_t index = static_cast<size_t>(rightConstant->getIConst()); 2163 TIntermAggregate *leftAggregate = mLeft->getAsAggregate(); 2164 if (leftAggregate && leftAggregate->isConstructor() && leftAggregate->isArray() && 2165 !leftAggregate->hasSideEffects()) 2166 { 2167 ASSERT(index < leftAggregate->getSequence()->size()); 2168 // This transformation can't add complexity as we're eliminating the constructor 2169 // entirely. 2170 return leftAggregate->getSequence()->at(index)->getAsTyped(); 2171 } 2172 2173 // If the indexed value is already a constant union, we can't increase duplication of 2174 // data by folding the indexing. Also fold the node in case it's generally beneficial to 2175 // replace this type of node with a constant union even if that would mean duplicating 2176 // data. 2177 if (mLeft->getAsConstantUnion() || getType().canReplaceWithConstantUnion()) 2178 { 2179 const TConstantUnion *constantValue = getConstantValue(); 2180 if (constantValue == nullptr) 2181 { 2182 return this; 2183 } 2184 return CreateFoldedNode(constantValue, this); 2185 } 2186 return this; 2187 } 2188 case EOpIndexIndirect: 2189 case EOpIndexDirectInterfaceBlock: 2190 case EOpInitialize: 2191 // Can never be constant folded. 2192 return this; 2193 default: 2194 { 2195 if (rightConstant == nullptr) 2196 { 2197 return this; 2198 } 2199 const TConstantUnion *leftConstant = mLeft->getConstantValue(); 2200 if (leftConstant == nullptr) 2201 { 2202 return this; 2203 } 2204 const TConstantUnion *constArray = 2205 TIntermConstantUnion::FoldBinary(mOp, leftConstant, mLeft->getType(), rightConstant, 2206 mRight->getType(), diagnostics, mLeft->getLine()); 2207 if (!constArray) 2208 { 2209 return this; 2210 } 2211 return CreateFoldedNode(constArray, this); 2212 } 2213 } 2214 } 2215 2216 bool TIntermBinary::hasConstantValue() const 2217 { 2218 switch (mOp) 2219 { 2220 case EOpIndexDirect: 2221 case EOpIndexDirectStruct: 2222 { 2223 if (mLeft->hasConstantValue() && mRight->hasConstantValue()) 2224 { 2225 return true; 2226 } 2227 break; 2228 } 2229 default: 2230 break; 2231 } 2232 return false; 2233 } 2234 2235 const TConstantUnion *TIntermBinary::getConstantValue() const 2236 { 2237 if (!hasConstantValue()) 2238 { 2239 return nullptr; 2240 } 2241 2242 const TConstantUnion *leftConstantValue = mLeft->getConstantValue(); 2243 int index = mRight->getConstantValue()->getIConst(); 2244 const TConstantUnion *constIndexingResult = nullptr; 2245 if (mOp == EOpIndexDirect) 2246 { 2247 constIndexingResult = 2248 TIntermConstantUnion::FoldIndexing(mLeft->getType(), leftConstantValue, index); 2249 } 2250 else 2251 { 2252 ASSERT(mOp == EOpIndexDirectStruct); 2253 const TFieldList &fields = mLeft->getType().getStruct()->fields(); 2254 2255 size_t previousFieldsSize = 0; 2256 for (int i = 0; i < index; ++i) 2257 { 2258 previousFieldsSize += fields[i]->type()->getObjectSize(); 2259 } 2260 constIndexingResult = leftConstantValue + previousFieldsSize; 2261 } 2262 return constIndexingResult; 2263 } 2264 2265 const ImmutableString &TIntermBinary::getIndexStructFieldName() const 2266 { 2267 ASSERT(mOp == EOpIndexDirectStruct); 2268 2269 const TType &lhsType = mLeft->getType(); 2270 const TStructure *structure = lhsType.getStruct(); 2271 const int index = mRight->getAsConstantUnion()->getIConst(0); 2272 2273 return structure->fields()[index]->name(); 2274 } 2275 2276 TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) 2277 { 2278 TConstantUnion *constArray = nullptr; 2279 2280 if (mOp == EOpArrayLength) 2281 { 2282 // The size of runtime-sized arrays may only be determined at runtime. 2283 if (mOperand->hasSideEffects() || mOperand->getType().isUnsizedArray()) 2284 { 2285 return this; 2286 } 2287 constArray = new TConstantUnion[1]; 2288 constArray->setIConst(mOperand->getOutermostArraySize()); 2289 } 2290 else 2291 { 2292 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); 2293 if (operandConstant == nullptr) 2294 { 2295 return this; 2296 } 2297 2298 switch (mOp) 2299 { 2300 case EOpAny: 2301 case EOpAll: 2302 case EOpLength: 2303 case EOpTranspose: 2304 case EOpDeterminant: 2305 case EOpInverse: 2306 case EOpPackSnorm2x16: 2307 case EOpUnpackSnorm2x16: 2308 case EOpPackUnorm2x16: 2309 case EOpUnpackUnorm2x16: 2310 case EOpPackHalf2x16: 2311 case EOpUnpackHalf2x16: 2312 case EOpPackUnorm4x8: 2313 case EOpPackSnorm4x8: 2314 case EOpUnpackUnorm4x8: 2315 case EOpUnpackSnorm4x8: 2316 constArray = operandConstant->foldUnaryNonComponentWise(mOp); 2317 break; 2318 default: 2319 constArray = operandConstant->foldUnaryComponentWise(mOp, mFunction, diagnostics); 2320 break; 2321 } 2322 } 2323 if (constArray == nullptr) 2324 { 2325 return this; 2326 } 2327 return CreateFoldedNode(constArray, this); 2328 } 2329 2330 TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) 2331 { 2332 // Make sure that all params are constant before actual constant folding. 2333 for (auto *param : *getSequence()) 2334 { 2335 if (param->getAsConstantUnion() == nullptr) 2336 { 2337 return this; 2338 } 2339 } 2340 const TConstantUnion *constArray = nullptr; 2341 if (isConstructor()) 2342 { 2343 if (mType.canReplaceWithConstantUnion()) 2344 { 2345 constArray = getConstantValue(); 2346 if (constArray && mType.getBasicType() == EbtUInt) 2347 { 2348 // Check if we converted a negative float to uint and issue a warning in that case. 2349 size_t sizeRemaining = mType.getObjectSize(); 2350 for (TIntermNode *arg : mArguments) 2351 { 2352 TIntermTyped *typedArg = arg->getAsTyped(); 2353 if (typedArg->getBasicType() == EbtFloat) 2354 { 2355 const TConstantUnion *argValue = typedArg->getConstantValue(); 2356 size_t castSize = 2357 std::min(typedArg->getType().getObjectSize(), sizeRemaining); 2358 for (size_t i = 0; i < castSize; ++i) 2359 { 2360 if (argValue[i].getFConst() < 0.0f) 2361 { 2362 // ESSL 3.00.6 section 5.4.1. 2363 diagnostics->warning( 2364 mLine, "casting a negative float to uint is undefined", 2365 mType.getBuiltInTypeNameString()); 2366 } 2367 } 2368 } 2369 sizeRemaining -= typedArg->getType().getObjectSize(); 2370 } 2371 } 2372 } 2373 } 2374 else if (CanFoldAggregateBuiltInOp(mOp)) 2375 { 2376 constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics); 2377 } 2378 if (constArray == nullptr) 2379 { 2380 return this; 2381 } 2382 return CreateFoldedNode(constArray, this); 2383 } 2384 2385 // 2386 // The fold functions see if an operation on a constant can be done in place, 2387 // without generating run-time code. 2388 // 2389 // Returns the constant value to keep using or nullptr. 2390 // 2391 const TConstantUnion *TIntermConstantUnion::FoldBinary(TOperator op, 2392 const TConstantUnion *leftArray, 2393 const TType &leftType, 2394 const TConstantUnion *rightArray, 2395 const TType &rightType, 2396 TDiagnostics *diagnostics, 2397 const TSourceLoc &line) 2398 { 2399 ASSERT(leftArray && rightArray); 2400 2401 size_t objectSize = leftType.getObjectSize(); 2402 2403 // for a case like float f = vec4(2, 3, 4, 5) + 1.2; 2404 if (rightType.getObjectSize() == 1 && objectSize > 1) 2405 { 2406 rightArray = Vectorize(*rightArray, objectSize); 2407 } 2408 else if (rightType.getObjectSize() > 1 && objectSize == 1) 2409 { 2410 // for a case like float f = 1.2 + vec4(2, 3, 4, 5); 2411 leftArray = Vectorize(*leftArray, rightType.getObjectSize()); 2412 objectSize = rightType.getObjectSize(); 2413 } 2414 2415 TConstantUnion *resultArray = nullptr; 2416 2417 switch (op) 2418 { 2419 case EOpAdd: 2420 resultArray = new TConstantUnion[objectSize]; 2421 for (size_t i = 0; i < objectSize; i++) 2422 resultArray[i] = 2423 TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line); 2424 break; 2425 case EOpSub: 2426 resultArray = new TConstantUnion[objectSize]; 2427 for (size_t i = 0; i < objectSize; i++) 2428 resultArray[i] = 2429 TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line); 2430 break; 2431 2432 case EOpMul: 2433 case EOpVectorTimesScalar: 2434 case EOpMatrixTimesScalar: 2435 resultArray = new TConstantUnion[objectSize]; 2436 for (size_t i = 0; i < objectSize; i++) 2437 resultArray[i] = 2438 TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line); 2439 break; 2440 2441 case EOpMatrixTimesMatrix: 2442 { 2443 // TODO(jmadll): This code should check for overflows. 2444 ASSERT(leftType.getBasicType() == EbtFloat && rightType.getBasicType() == EbtFloat); 2445 2446 const uint8_t leftCols = leftType.getCols(); 2447 const uint8_t leftRows = leftType.getRows(); 2448 const uint8_t rightCols = rightType.getCols(); 2449 const uint8_t rightRows = rightType.getRows(); 2450 const uint8_t resultCols = rightCols; 2451 const uint8_t resultRows = leftRows; 2452 2453 resultArray = new TConstantUnion[resultCols * resultRows]; 2454 for (uint8_t row = 0; row < resultRows; row++) 2455 { 2456 for (uint8_t column = 0; column < resultCols; column++) 2457 { 2458 resultArray[resultRows * column + row].setFConst(0.0f); 2459 for (uint8_t i = 0; i < leftCols; i++) 2460 { 2461 resultArray[resultRows * column + row].setFConst( 2462 resultArray[resultRows * column + row].getFConst() + 2463 leftArray[i * leftRows + row].getFConst() * 2464 rightArray[column * rightRows + i].getFConst()); 2465 } 2466 } 2467 } 2468 } 2469 break; 2470 2471 case EOpDiv: 2472 case EOpIMod: 2473 { 2474 resultArray = new TConstantUnion[objectSize]; 2475 for (size_t i = 0; i < objectSize; i++) 2476 { 2477 if (IsFloatDivision(leftType.getBasicType(), rightType.getBasicType())) 2478 { 2479 // Float division requested, possibly with implicit conversion 2480 ASSERT(op == EOpDiv); 2481 float dividend = leftArray[i].getFConst(); 2482 float divisor = rightArray[i].getFConst(); 2483 2484 if (divisor == 0.0f) 2485 { 2486 if (dividend == 0.0f) 2487 { 2488 diagnostics->warning(line, 2489 "Zero divided by zero during constant " 2490 "folding generated NaN", 2491 "/"); 2492 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN()); 2493 } 2494 else 2495 { 2496 diagnostics->warning(line, "Divide by zero during constant folding", 2497 "/"); 2498 bool negativeResult = std::signbit(dividend) != std::signbit(divisor); 2499 resultArray[i].setFConst(negativeResult 2500 ? -std::numeric_limits<float>::infinity() 2501 : std::numeric_limits<float>::infinity()); 2502 } 2503 } 2504 else if (gl::isInf(dividend) && gl::isInf(divisor)) 2505 { 2506 diagnostics->warning(line, 2507 "Infinity divided by infinity during constant " 2508 "folding generated NaN", 2509 "/"); 2510 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN()); 2511 } 2512 else 2513 { 2514 float result = dividend / divisor; 2515 if (!gl::isInf(dividend) && gl::isInf(result)) 2516 { 2517 diagnostics->warning( 2518 line, "Constant folded division overflowed to infinity", "/"); 2519 } 2520 resultArray[i].setFConst(result); 2521 } 2522 } 2523 else 2524 { 2525 // Types are either both int or both uint 2526 switch (leftType.getBasicType()) 2527 { 2528 case EbtInt: 2529 { 2530 if (rightArray[i] == 0) 2531 { 2532 diagnostics->warning( 2533 line, "Divide by zero error during constant folding", "/"); 2534 resultArray[i].setIConst(INT_MAX); 2535 } 2536 else 2537 { 2538 int lhs = leftArray[i].getIConst(); 2539 int divisor = rightArray[i].getIConst(); 2540 if (op == EOpDiv) 2541 { 2542 // Check for the special case where the minimum 2543 // representable number is divided by -1. If left alone this 2544 // leads to integer overflow in C++. ESSL 3.00.6 2545 // section 4.1.3 Integers: "However, for the case where the 2546 // minimum representable value is divided by -1, it is 2547 // allowed to return either the minimum representable value 2548 // or the maximum representable value." 2549 if (lhs == -0x7fffffff - 1 && divisor == -1) 2550 { 2551 resultArray[i].setIConst(0x7fffffff); 2552 } 2553 else 2554 { 2555 resultArray[i].setIConst(lhs / divisor); 2556 } 2557 } 2558 else 2559 { 2560 ASSERT(op == EOpIMod); 2561 if (lhs < 0 || divisor < 0) 2562 { 2563 // ESSL 3.00.6 section 5.9: Results of modulus are 2564 // undefined when either one of the operands is 2565 // negative. 2566 diagnostics->warning(line, 2567 "Negative modulus operator operand " 2568 "encountered during constant folding. " 2569 "Results are undefined.", 2570 "%"); 2571 resultArray[i].setIConst(0); 2572 } 2573 else 2574 { 2575 resultArray[i].setIConst(lhs % divisor); 2576 } 2577 } 2578 } 2579 break; 2580 } 2581 case EbtUInt: 2582 { 2583 if (rightArray[i] == 0) 2584 { 2585 diagnostics->warning( 2586 line, "Divide by zero error during constant folding", "/"); 2587 resultArray[i].setUConst(UINT_MAX); 2588 } 2589 else 2590 { 2591 if (op == EOpDiv) 2592 { 2593 resultArray[i].setUConst(leftArray[i].getUConst() / 2594 rightArray[i].getUConst()); 2595 } 2596 else 2597 { 2598 ASSERT(op == EOpIMod); 2599 resultArray[i].setUConst(leftArray[i].getUConst() % 2600 rightArray[i].getUConst()); 2601 } 2602 } 2603 break; 2604 } 2605 default: 2606 UNREACHABLE(); 2607 return nullptr; 2608 } 2609 } 2610 } 2611 } 2612 break; 2613 2614 case EOpMatrixTimesVector: 2615 { 2616 // TODO(jmadll): This code should check for overflows. 2617 ASSERT(rightType.getBasicType() == EbtFloat); 2618 2619 const uint8_t matrixCols = leftType.getCols(); 2620 const uint8_t matrixRows = leftType.getRows(); 2621 2622 resultArray = new TConstantUnion[matrixRows]; 2623 2624 for (uint8_t matrixRow = 0; matrixRow < matrixRows; matrixRow++) 2625 { 2626 resultArray[matrixRow].setFConst(0.0f); 2627 for (uint8_t col = 0; col < matrixCols; col++) 2628 { 2629 resultArray[matrixRow].setFConst( 2630 resultArray[matrixRow].getFConst() + 2631 leftArray[col * matrixRows + matrixRow].getFConst() * 2632 rightArray[col].getFConst()); 2633 } 2634 } 2635 } 2636 break; 2637 2638 case EOpVectorTimesMatrix: 2639 { 2640 // TODO(jmadll): This code should check for overflows. 2641 ASSERT(leftType.getBasicType() == EbtFloat); 2642 2643 const uint8_t matrixCols = rightType.getCols(); 2644 const uint8_t matrixRows = rightType.getRows(); 2645 2646 resultArray = new TConstantUnion[matrixCols]; 2647 2648 for (uint8_t matrixCol = 0; matrixCol < matrixCols; matrixCol++) 2649 { 2650 resultArray[matrixCol].setFConst(0.0f); 2651 for (uint8_t matrixRow = 0; matrixRow < matrixRows; matrixRow++) 2652 { 2653 resultArray[matrixCol].setFConst( 2654 resultArray[matrixCol].getFConst() + 2655 leftArray[matrixRow].getFConst() * 2656 rightArray[matrixCol * matrixRows + matrixRow].getFConst()); 2657 } 2658 } 2659 } 2660 break; 2661 2662 case EOpLogicalAnd: 2663 { 2664 resultArray = new TConstantUnion[objectSize]; 2665 for (size_t i = 0; i < objectSize; i++) 2666 { 2667 resultArray[i] = leftArray[i] && rightArray[i]; 2668 } 2669 } 2670 break; 2671 2672 case EOpLogicalOr: 2673 { 2674 resultArray = new TConstantUnion[objectSize]; 2675 for (size_t i = 0; i < objectSize; i++) 2676 { 2677 resultArray[i] = leftArray[i] || rightArray[i]; 2678 } 2679 } 2680 break; 2681 2682 case EOpLogicalXor: 2683 { 2684 ASSERT(leftType.getBasicType() == EbtBool); 2685 resultArray = new TConstantUnion[objectSize]; 2686 for (size_t i = 0; i < objectSize; i++) 2687 { 2688 resultArray[i].setBConst(leftArray[i] != rightArray[i]); 2689 } 2690 } 2691 break; 2692 2693 case EOpBitwiseAnd: 2694 resultArray = new TConstantUnion[objectSize]; 2695 for (size_t i = 0; i < objectSize; i++) 2696 resultArray[i] = leftArray[i] & rightArray[i]; 2697 break; 2698 case EOpBitwiseXor: 2699 resultArray = new TConstantUnion[objectSize]; 2700 for (size_t i = 0; i < objectSize; i++) 2701 resultArray[i] = leftArray[i] ^ rightArray[i]; 2702 break; 2703 case EOpBitwiseOr: 2704 resultArray = new TConstantUnion[objectSize]; 2705 for (size_t i = 0; i < objectSize; i++) 2706 resultArray[i] = leftArray[i] | rightArray[i]; 2707 break; 2708 case EOpBitShiftLeft: 2709 resultArray = new TConstantUnion[objectSize]; 2710 for (size_t i = 0; i < objectSize; i++) 2711 resultArray[i] = 2712 TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line); 2713 break; 2714 case EOpBitShiftRight: 2715 resultArray = new TConstantUnion[objectSize]; 2716 for (size_t i = 0; i < objectSize; i++) 2717 resultArray[i] = 2718 TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line); 2719 break; 2720 2721 case EOpLessThan: 2722 ASSERT(objectSize == 1); 2723 resultArray = new TConstantUnion[1]; 2724 resultArray->setBConst(*leftArray < *rightArray); 2725 break; 2726 2727 case EOpGreaterThan: 2728 ASSERT(objectSize == 1); 2729 resultArray = new TConstantUnion[1]; 2730 resultArray->setBConst(*leftArray > *rightArray); 2731 break; 2732 2733 case EOpLessThanEqual: 2734 ASSERT(objectSize == 1); 2735 resultArray = new TConstantUnion[1]; 2736 resultArray->setBConst(!(*leftArray > *rightArray)); 2737 break; 2738 2739 case EOpGreaterThanEqual: 2740 ASSERT(objectSize == 1); 2741 resultArray = new TConstantUnion[1]; 2742 resultArray->setBConst(!(*leftArray < *rightArray)); 2743 break; 2744 2745 case EOpEqual: 2746 case EOpNotEqual: 2747 { 2748 resultArray = new TConstantUnion[1]; 2749 bool equal = true; 2750 for (size_t i = 0; i < objectSize; i++) 2751 { 2752 if (leftArray[i] != rightArray[i]) 2753 { 2754 equal = false; 2755 break; // break out of for loop 2756 } 2757 } 2758 if (op == EOpEqual) 2759 { 2760 resultArray->setBConst(equal); 2761 } 2762 else 2763 { 2764 resultArray->setBConst(!equal); 2765 } 2766 } 2767 break; 2768 2769 default: 2770 UNREACHABLE(); 2771 return nullptr; 2772 } 2773 return resultArray; 2774 } 2775 2776 // The fold functions do operations on a constant at GLSL compile time, without generating run-time 2777 // code. Returns the constant value to keep using. Nullptr should not be returned. 2778 TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) 2779 { 2780 // Do operations where the return type may have a different number of components compared to the 2781 // operand type. 2782 2783 const TConstantUnion *operandArray = getConstantValue(); 2784 ASSERT(operandArray); 2785 2786 size_t objectSize = getType().getObjectSize(); 2787 TConstantUnion *resultArray = nullptr; 2788 switch (op) 2789 { 2790 case EOpAny: 2791 ASSERT(getType().getBasicType() == EbtBool); 2792 resultArray = new TConstantUnion(); 2793 resultArray->setBConst(false); 2794 for (size_t i = 0; i < objectSize; i++) 2795 { 2796 if (operandArray[i].getBConst()) 2797 { 2798 resultArray->setBConst(true); 2799 break; 2800 } 2801 } 2802 break; 2803 2804 case EOpAll: 2805 ASSERT(getType().getBasicType() == EbtBool); 2806 resultArray = new TConstantUnion(); 2807 resultArray->setBConst(true); 2808 for (size_t i = 0; i < objectSize; i++) 2809 { 2810 if (!operandArray[i].getBConst()) 2811 { 2812 resultArray->setBConst(false); 2813 break; 2814 } 2815 } 2816 break; 2817 2818 case EOpLength: 2819 ASSERT(getType().getBasicType() == EbtFloat); 2820 resultArray = new TConstantUnion(); 2821 resultArray->setFConst(VectorLength(operandArray, objectSize)); 2822 break; 2823 2824 case EOpTranspose: 2825 { 2826 ASSERT(getType().getBasicType() == EbtFloat); 2827 resultArray = new TConstantUnion[objectSize]; 2828 angle::Matrix<float> result = 2829 GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose(); 2830 SetUnionArrayFromMatrix(result, resultArray); 2831 break; 2832 } 2833 2834 case EOpDeterminant: 2835 { 2836 ASSERT(getType().getBasicType() == EbtFloat); 2837 const uint8_t size = getType().getNominalSize(); 2838 ASSERT(size >= 2 && size <= 4); 2839 resultArray = new TConstantUnion(); 2840 resultArray->setFConst(GetMatrix(operandArray, size).determinant()); 2841 break; 2842 } 2843 2844 case EOpInverse: 2845 { 2846 ASSERT(getType().getBasicType() == EbtFloat); 2847 const uint8_t size = getType().getNominalSize(); 2848 ASSERT(size >= 2 && size <= 4); 2849 resultArray = new TConstantUnion[objectSize]; 2850 angle::Matrix<float> result = GetMatrix(operandArray, size).inverse(); 2851 SetUnionArrayFromMatrix(result, resultArray); 2852 break; 2853 } 2854 2855 case EOpPackSnorm2x16: 2856 ASSERT(getType().getBasicType() == EbtFloat); 2857 ASSERT(getType().getNominalSize() == 2); 2858 resultArray = new TConstantUnion(); 2859 resultArray->setUConst( 2860 gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); 2861 break; 2862 2863 case EOpUnpackSnorm2x16: 2864 { 2865 ASSERT(getType().getBasicType() == EbtUInt); 2866 resultArray = new TConstantUnion[2]; 2867 float f1, f2; 2868 gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2); 2869 resultArray[0].setFConst(f1); 2870 resultArray[1].setFConst(f2); 2871 break; 2872 } 2873 2874 case EOpPackUnorm2x16: 2875 ASSERT(getType().getBasicType() == EbtFloat); 2876 ASSERT(getType().getNominalSize() == 2); 2877 resultArray = new TConstantUnion(); 2878 resultArray->setUConst( 2879 gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); 2880 break; 2881 2882 case EOpUnpackUnorm2x16: 2883 { 2884 ASSERT(getType().getBasicType() == EbtUInt); 2885 resultArray = new TConstantUnion[2]; 2886 float f1, f2; 2887 gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2); 2888 resultArray[0].setFConst(f1); 2889 resultArray[1].setFConst(f2); 2890 break; 2891 } 2892 2893 case EOpPackHalf2x16: 2894 ASSERT(getType().getBasicType() == EbtFloat); 2895 ASSERT(getType().getNominalSize() == 2); 2896 resultArray = new TConstantUnion(); 2897 resultArray->setUConst( 2898 gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); 2899 break; 2900 2901 case EOpUnpackHalf2x16: 2902 { 2903 ASSERT(getType().getBasicType() == EbtUInt); 2904 resultArray = new TConstantUnion[2]; 2905 float f1, f2; 2906 gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2); 2907 resultArray[0].setFConst(f1); 2908 resultArray[1].setFConst(f2); 2909 break; 2910 } 2911 2912 case EOpPackUnorm4x8: 2913 { 2914 ASSERT(getType().getBasicType() == EbtFloat); 2915 resultArray = new TConstantUnion(); 2916 resultArray->setUConst( 2917 gl::PackUnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), 2918 operandArray[2].getFConst(), operandArray[3].getFConst())); 2919 break; 2920 } 2921 case EOpPackSnorm4x8: 2922 { 2923 ASSERT(getType().getBasicType() == EbtFloat); 2924 resultArray = new TConstantUnion(); 2925 resultArray->setUConst( 2926 gl::PackSnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(), 2927 operandArray[2].getFConst(), operandArray[3].getFConst())); 2928 break; 2929 } 2930 case EOpUnpackUnorm4x8: 2931 { 2932 ASSERT(getType().getBasicType() == EbtUInt); 2933 resultArray = new TConstantUnion[4]; 2934 float f[4]; 2935 gl::UnpackUnorm4x8(operandArray[0].getUConst(), f); 2936 for (size_t i = 0; i < 4; ++i) 2937 { 2938 resultArray[i].setFConst(f[i]); 2939 } 2940 break; 2941 } 2942 case EOpUnpackSnorm4x8: 2943 { 2944 ASSERT(getType().getBasicType() == EbtUInt); 2945 resultArray = new TConstantUnion[4]; 2946 float f[4]; 2947 gl::UnpackSnorm4x8(operandArray[0].getUConst(), f); 2948 for (size_t i = 0; i < 4; ++i) 2949 { 2950 resultArray[i].setFConst(f[i]); 2951 } 2952 break; 2953 } 2954 2955 default: 2956 UNREACHABLE(); 2957 break; 2958 } 2959 2960 return resultArray; 2961 } 2962 2963 TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op, 2964 const TFunction *function, 2965 TDiagnostics *diagnostics) 2966 { 2967 // Do unary operations where each component of the result is computed based on the corresponding 2968 // component of the operand. Also folds normalize, though the divisor in that case takes all 2969 // components into account. 2970 2971 const TConstantUnion *operandArray = getConstantValue(); 2972 ASSERT(operandArray); 2973 2974 size_t objectSize = getType().getObjectSize(); 2975 2976 TConstantUnion *resultArray = new TConstantUnion[objectSize]; 2977 for (size_t i = 0; i < objectSize; i++) 2978 { 2979 switch (op) 2980 { 2981 case EOpNegative: 2982 switch (getType().getBasicType()) 2983 { 2984 case EbtFloat: 2985 resultArray[i].setFConst(-operandArray[i].getFConst()); 2986 break; 2987 case EbtInt: 2988 if (operandArray[i] == std::numeric_limits<int>::min()) 2989 { 2990 // The minimum representable integer doesn't have a positive 2991 // counterpart, rather the negation overflows and in ESSL is supposed to 2992 // wrap back to the minimum representable integer. Make sure that we 2993 // don't actually let the negation overflow, which has undefined 2994 // behavior in C++. 2995 resultArray[i].setIConst(std::numeric_limits<int>::min()); 2996 } 2997 else 2998 { 2999 resultArray[i].setIConst(-operandArray[i].getIConst()); 3000 } 3001 break; 3002 case EbtUInt: 3003 if (operandArray[i] == 0x80000000u) 3004 { 3005 resultArray[i].setUConst(0x80000000u); 3006 } 3007 else 3008 { 3009 resultArray[i].setUConst(static_cast<unsigned int>( 3010 -static_cast<int>(operandArray[i].getUConst()))); 3011 } 3012 break; 3013 default: 3014 UNREACHABLE(); 3015 return nullptr; 3016 } 3017 break; 3018 3019 case EOpPositive: 3020 switch (getType().getBasicType()) 3021 { 3022 case EbtFloat: 3023 resultArray[i].setFConst(operandArray[i].getFConst()); 3024 break; 3025 case EbtInt: 3026 resultArray[i].setIConst(operandArray[i].getIConst()); 3027 break; 3028 case EbtUInt: 3029 resultArray[i].setUConst(static_cast<unsigned int>( 3030 static_cast<int>(operandArray[i].getUConst()))); 3031 break; 3032 default: 3033 UNREACHABLE(); 3034 return nullptr; 3035 } 3036 break; 3037 3038 case EOpLogicalNot: 3039 switch (getType().getBasicType()) 3040 { 3041 case EbtBool: 3042 resultArray[i].setBConst(!operandArray[i].getBConst()); 3043 break; 3044 default: 3045 UNREACHABLE(); 3046 return nullptr; 3047 } 3048 break; 3049 3050 case EOpBitwiseNot: 3051 switch (getType().getBasicType()) 3052 { 3053 case EbtInt: 3054 resultArray[i].setIConst(~operandArray[i].getIConst()); 3055 break; 3056 case EbtUInt: 3057 resultArray[i].setUConst(~operandArray[i].getUConst()); 3058 break; 3059 default: 3060 UNREACHABLE(); 3061 return nullptr; 3062 } 3063 break; 3064 3065 case EOpRadians: 3066 ASSERT(getType().getBasicType() == EbtFloat); 3067 resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst()); 3068 break; 3069 3070 case EOpDegrees: 3071 ASSERT(getType().getBasicType() == EbtFloat); 3072 resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst()); 3073 break; 3074 3075 case EOpSin: 3076 foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]); 3077 break; 3078 3079 case EOpCos: 3080 foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]); 3081 break; 3082 3083 case EOpTan: 3084 foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]); 3085 break; 3086 3087 case EOpAsin: 3088 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 3089 // 0. 3090 if (fabsf(operandArray[i].getFConst()) > 1.0f) 3091 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3092 diagnostics, &resultArray[i]); 3093 else 3094 foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]); 3095 break; 3096 3097 case EOpAcos: 3098 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 3099 // 0. 3100 if (fabsf(operandArray[i].getFConst()) > 1.0f) 3101 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3102 diagnostics, &resultArray[i]); 3103 else 3104 foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]); 3105 break; 3106 3107 case EOpAtan: 3108 foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]); 3109 break; 3110 3111 case EOpSinh: 3112 foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]); 3113 break; 3114 3115 case EOpCosh: 3116 foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]); 3117 break; 3118 3119 case EOpTanh: 3120 foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]); 3121 break; 3122 3123 case EOpAsinh: 3124 foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]); 3125 break; 3126 3127 case EOpAcosh: 3128 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0. 3129 if (operandArray[i].getFConst() < 1.0f) 3130 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3131 diagnostics, &resultArray[i]); 3132 else 3133 foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]); 3134 break; 3135 3136 case EOpAtanh: 3137 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 3138 // 0. 3139 if (fabsf(operandArray[i].getFConst()) >= 1.0f) 3140 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3141 diagnostics, &resultArray[i]); 3142 else 3143 foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]); 3144 break; 3145 3146 case EOpAbs: 3147 switch (getType().getBasicType()) 3148 { 3149 case EbtFloat: 3150 resultArray[i].setFConst(fabsf(operandArray[i].getFConst())); 3151 break; 3152 case EbtInt: 3153 resultArray[i].setIConst(abs(operandArray[i].getIConst())); 3154 break; 3155 default: 3156 UNREACHABLE(); 3157 return nullptr; 3158 } 3159 break; 3160 3161 case EOpSign: 3162 switch (getType().getBasicType()) 3163 { 3164 case EbtFloat: 3165 { 3166 float fConst = operandArray[i].getFConst(); 3167 float fResult = 0.0f; 3168 if (fConst > 0.0f) 3169 fResult = 1.0f; 3170 else if (fConst < 0.0f) 3171 fResult = -1.0f; 3172 resultArray[i].setFConst(fResult); 3173 break; 3174 } 3175 case EbtInt: 3176 { 3177 int iConst = operandArray[i].getIConst(); 3178 int iResult = 0; 3179 if (iConst > 0) 3180 iResult = 1; 3181 else if (iConst < 0) 3182 iResult = -1; 3183 resultArray[i].setIConst(iResult); 3184 break; 3185 } 3186 default: 3187 UNREACHABLE(); 3188 return nullptr; 3189 } 3190 break; 3191 3192 case EOpFloor: 3193 foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]); 3194 break; 3195 3196 case EOpTrunc: 3197 foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]); 3198 break; 3199 3200 case EOpRound: 3201 foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]); 3202 break; 3203 3204 case EOpRoundEven: 3205 { 3206 ASSERT(getType().getBasicType() == EbtFloat); 3207 float x = operandArray[i].getFConst(); 3208 float result; 3209 float fractPart = modff(x, &result); 3210 if (fabsf(fractPart) == 0.5f) 3211 result = 2.0f * roundf(x / 2.0f); 3212 else 3213 result = roundf(x); 3214 resultArray[i].setFConst(result); 3215 break; 3216 } 3217 3218 case EOpCeil: 3219 foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]); 3220 break; 3221 3222 case EOpFract: 3223 { 3224 ASSERT(getType().getBasicType() == EbtFloat); 3225 float x = operandArray[i].getFConst(); 3226 resultArray[i].setFConst(x - floorf(x)); 3227 break; 3228 } 3229 3230 case EOpIsnan: 3231 ASSERT(getType().getBasicType() == EbtFloat); 3232 resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst())); 3233 break; 3234 3235 case EOpIsinf: 3236 ASSERT(getType().getBasicType() == EbtFloat); 3237 resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst())); 3238 break; 3239 3240 case EOpFloatBitsToInt: 3241 ASSERT(getType().getBasicType() == EbtFloat); 3242 resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst())); 3243 break; 3244 3245 case EOpFloatBitsToUint: 3246 ASSERT(getType().getBasicType() == EbtFloat); 3247 resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst())); 3248 break; 3249 3250 case EOpIntBitsToFloat: 3251 ASSERT(getType().getBasicType() == EbtInt); 3252 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst())); 3253 break; 3254 3255 case EOpUintBitsToFloat: 3256 ASSERT(getType().getBasicType() == EbtUInt); 3257 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst())); 3258 break; 3259 3260 case EOpExp: 3261 foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]); 3262 break; 3263 3264 case EOpLog: 3265 // For log(x), results are undefined if x <= 0, we are choosing to set result to 0. 3266 if (operandArray[i].getFConst() <= 0.0f) 3267 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3268 diagnostics, &resultArray[i]); 3269 else 3270 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); 3271 break; 3272 3273 case EOpExp2: 3274 foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]); 3275 break; 3276 3277 case EOpLog2: 3278 // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. 3279 // And log2f is not available on some plarforms like old android, so just using 3280 // log(x)/log(2) here. 3281 if (operandArray[i].getFConst() <= 0.0f) 3282 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3283 diagnostics, &resultArray[i]); 3284 else 3285 { 3286 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); 3287 resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f)); 3288 } 3289 break; 3290 3291 case EOpSqrt: 3292 // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. 3293 if (operandArray[i].getFConst() < 0.0f) 3294 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3295 diagnostics, &resultArray[i]); 3296 else 3297 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); 3298 break; 3299 3300 case EOpInversesqrt: 3301 // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(), 3302 // so getting the square root first using builtin function sqrt() and then taking 3303 // its inverse. 3304 // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set 3305 // result to 0. 3306 if (operandArray[i].getFConst() <= 0.0f) 3307 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3308 diagnostics, &resultArray[i]); 3309 else 3310 { 3311 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); 3312 resultArray[i].setFConst(1.0f / resultArray[i].getFConst()); 3313 } 3314 break; 3315 3316 case EOpNotComponentWise: 3317 ASSERT(getType().getBasicType() == EbtBool); 3318 resultArray[i].setBConst(!operandArray[i].getBConst()); 3319 break; 3320 3321 case EOpNormalize: 3322 { 3323 ASSERT(getType().getBasicType() == EbtFloat); 3324 float x = operandArray[i].getFConst(); 3325 float length = VectorLength(operandArray, objectSize); 3326 if (length != 0.0f) 3327 resultArray[i].setFConst(x / length); 3328 else 3329 UndefinedConstantFoldingError(getLine(), function, getType().getBasicType(), 3330 diagnostics, &resultArray[i]); 3331 break; 3332 } 3333 case EOpBitfieldReverse: 3334 { 3335 uint32_t value; 3336 if (getType().getBasicType() == EbtInt) 3337 { 3338 value = static_cast<uint32_t>(operandArray[i].getIConst()); 3339 } 3340 else 3341 { 3342 ASSERT(getType().getBasicType() == EbtUInt); 3343 value = operandArray[i].getUConst(); 3344 } 3345 uint32_t result = gl::BitfieldReverse(value); 3346 if (getType().getBasicType() == EbtInt) 3347 { 3348 resultArray[i].setIConst(static_cast<int32_t>(result)); 3349 } 3350 else 3351 { 3352 resultArray[i].setUConst(result); 3353 } 3354 break; 3355 } 3356 case EOpBitCount: 3357 { 3358 uint32_t value; 3359 if (getType().getBasicType() == EbtInt) 3360 { 3361 value = static_cast<uint32_t>(operandArray[i].getIConst()); 3362 } 3363 else 3364 { 3365 ASSERT(getType().getBasicType() == EbtUInt); 3366 value = operandArray[i].getUConst(); 3367 } 3368 int result = gl::BitCount(value); 3369 resultArray[i].setIConst(result); 3370 break; 3371 } 3372 case EOpFindLSB: 3373 { 3374 uint32_t value; 3375 if (getType().getBasicType() == EbtInt) 3376 { 3377 value = static_cast<uint32_t>(operandArray[i].getIConst()); 3378 } 3379 else 3380 { 3381 ASSERT(getType().getBasicType() == EbtUInt); 3382 value = operandArray[i].getUConst(); 3383 } 3384 resultArray[i].setIConst(gl::FindLSB(value)); 3385 break; 3386 } 3387 case EOpFindMSB: 3388 { 3389 uint32_t value; 3390 if (getType().getBasicType() == EbtInt) 3391 { 3392 int intValue = operandArray[i].getIConst(); 3393 value = static_cast<uint32_t>(intValue); 3394 if (intValue < 0) 3395 { 3396 // Look for zero instead of one in value. This also handles the intValue == 3397 // -1 special case, where the return value needs to be -1. 3398 value = ~value; 3399 } 3400 } 3401 else 3402 { 3403 ASSERT(getType().getBasicType() == EbtUInt); 3404 value = operandArray[i].getUConst(); 3405 } 3406 resultArray[i].setIConst(gl::FindMSB(value)); 3407 break; 3408 } 3409 3410 default: 3411 return nullptr; 3412 } 3413 } 3414 3415 return resultArray; 3416 } 3417 3418 void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter, 3419 FloatTypeUnaryFunc builtinFunc, 3420 TConstantUnion *result) const 3421 { 3422 ASSERT(builtinFunc); 3423 3424 ASSERT(getType().getBasicType() == EbtFloat); 3425 result->setFConst(builtinFunc(parameter.getFConst())); 3426 } 3427 3428 void TIntermConstantUnion::propagatePrecision(TPrecision precision) 3429 { 3430 mType.setPrecision(precision); 3431 } 3432 3433 // static 3434 TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, 3435 TDiagnostics *diagnostics) 3436 { 3437 const TOperator op = aggregate->getOp(); 3438 const TFunction *function = aggregate->getFunction(); 3439 TIntermSequence *arguments = aggregate->getSequence(); 3440 unsigned int argsCount = static_cast<unsigned int>(arguments->size()); 3441 std::vector<const TConstantUnion *> unionArrays(argsCount); 3442 std::vector<size_t> objectSizes(argsCount); 3443 size_t maxObjectSize = 0; 3444 TBasicType basicType = EbtVoid; 3445 TSourceLoc loc; 3446 for (unsigned int i = 0; i < argsCount; i++) 3447 { 3448 TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion(); 3449 ASSERT(argConstant != nullptr); // Should be checked already. 3450 3451 if (i == 0) 3452 { 3453 basicType = argConstant->getType().getBasicType(); 3454 loc = argConstant->getLine(); 3455 } 3456 unionArrays[i] = argConstant->getConstantValue(); 3457 objectSizes[i] = argConstant->getType().getObjectSize(); 3458 if (objectSizes[i] > maxObjectSize) 3459 maxObjectSize = objectSizes[i]; 3460 } 3461 3462 if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct) 3463 { 3464 for (unsigned int i = 0; i < argsCount; i++) 3465 if (objectSizes[i] != maxObjectSize) 3466 unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize); 3467 } 3468 3469 TConstantUnion *resultArray = nullptr; 3470 3471 switch (op) 3472 { 3473 case EOpAtan: 3474 { 3475 ASSERT(basicType == EbtFloat); 3476 resultArray = new TConstantUnion[maxObjectSize]; 3477 for (size_t i = 0; i < maxObjectSize; i++) 3478 { 3479 float y = unionArrays[0][i].getFConst(); 3480 float x = unionArrays[1][i].getFConst(); 3481 // Results are undefined if x and y are both 0. 3482 if (x == 0.0f && y == 0.0f) 3483 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 3484 &resultArray[i]); 3485 else 3486 resultArray[i].setFConst(atan2f(y, x)); 3487 } 3488 break; 3489 } 3490 3491 case EOpPow: 3492 { 3493 ASSERT(basicType == EbtFloat); 3494 resultArray = new TConstantUnion[maxObjectSize]; 3495 for (size_t i = 0; i < maxObjectSize; i++) 3496 { 3497 float x = unionArrays[0][i].getFConst(); 3498 float y = unionArrays[1][i].getFConst(); 3499 // Results are undefined if x < 0. 3500 // Results are undefined if x = 0 and y <= 0. 3501 if (x < 0.0f) 3502 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 3503 &resultArray[i]); 3504 else if (x == 0.0f && y <= 0.0f) 3505 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 3506 &resultArray[i]); 3507 else 3508 resultArray[i].setFConst(powf(x, y)); 3509 } 3510 break; 3511 } 3512 3513 case EOpMod: 3514 { 3515 ASSERT(basicType == EbtFloat); 3516 resultArray = new TConstantUnion[maxObjectSize]; 3517 for (size_t i = 0; i < maxObjectSize; i++) 3518 { 3519 float x = unionArrays[0][i].getFConst(); 3520 float y = unionArrays[1][i].getFConst(); 3521 resultArray[i].setFConst(x - y * floorf(x / y)); 3522 } 3523 break; 3524 } 3525 3526 case EOpMin: 3527 { 3528 resultArray = new TConstantUnion[maxObjectSize]; 3529 for (size_t i = 0; i < maxObjectSize; i++) 3530 { 3531 switch (basicType) 3532 { 3533 case EbtFloat: 3534 resultArray[i].setFConst( 3535 std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); 3536 break; 3537 case EbtInt: 3538 resultArray[i].setIConst( 3539 std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); 3540 break; 3541 case EbtUInt: 3542 resultArray[i].setUConst( 3543 std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); 3544 break; 3545 default: 3546 UNREACHABLE(); 3547 break; 3548 } 3549 } 3550 break; 3551 } 3552 3553 case EOpMax: 3554 { 3555 resultArray = new TConstantUnion[maxObjectSize]; 3556 for (size_t i = 0; i < maxObjectSize; i++) 3557 { 3558 switch (basicType) 3559 { 3560 case EbtFloat: 3561 resultArray[i].setFConst( 3562 std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); 3563 break; 3564 case EbtInt: 3565 resultArray[i].setIConst( 3566 std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); 3567 break; 3568 case EbtUInt: 3569 resultArray[i].setUConst( 3570 std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); 3571 break; 3572 default: 3573 UNREACHABLE(); 3574 break; 3575 } 3576 } 3577 break; 3578 } 3579 3580 case EOpStep: 3581 { 3582 ASSERT(basicType == EbtFloat); 3583 resultArray = new TConstantUnion[maxObjectSize]; 3584 for (size_t i = 0; i < maxObjectSize; i++) 3585 resultArray[i].setFConst( 3586 unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f); 3587 break; 3588 } 3589 3590 case EOpLessThanComponentWise: 3591 { 3592 resultArray = new TConstantUnion[maxObjectSize]; 3593 for (size_t i = 0; i < maxObjectSize; i++) 3594 { 3595 switch (basicType) 3596 { 3597 case EbtFloat: 3598 resultArray[i].setBConst(unionArrays[0][i].getFConst() < 3599 unionArrays[1][i].getFConst()); 3600 break; 3601 case EbtInt: 3602 resultArray[i].setBConst(unionArrays[0][i].getIConst() < 3603 unionArrays[1][i].getIConst()); 3604 break; 3605 case EbtUInt: 3606 resultArray[i].setBConst(unionArrays[0][i].getUConst() < 3607 unionArrays[1][i].getUConst()); 3608 break; 3609 default: 3610 UNREACHABLE(); 3611 break; 3612 } 3613 } 3614 break; 3615 } 3616 3617 case EOpLessThanEqualComponentWise: 3618 { 3619 resultArray = new TConstantUnion[maxObjectSize]; 3620 for (size_t i = 0; i < maxObjectSize; i++) 3621 { 3622 switch (basicType) 3623 { 3624 case EbtFloat: 3625 resultArray[i].setBConst(unionArrays[0][i].getFConst() <= 3626 unionArrays[1][i].getFConst()); 3627 break; 3628 case EbtInt: 3629 resultArray[i].setBConst(unionArrays[0][i].getIConst() <= 3630 unionArrays[1][i].getIConst()); 3631 break; 3632 case EbtUInt: 3633 resultArray[i].setBConst(unionArrays[0][i].getUConst() <= 3634 unionArrays[1][i].getUConst()); 3635 break; 3636 default: 3637 UNREACHABLE(); 3638 break; 3639 } 3640 } 3641 break; 3642 } 3643 3644 case EOpGreaterThanComponentWise: 3645 { 3646 resultArray = new TConstantUnion[maxObjectSize]; 3647 for (size_t i = 0; i < maxObjectSize; i++) 3648 { 3649 switch (basicType) 3650 { 3651 case EbtFloat: 3652 resultArray[i].setBConst(unionArrays[0][i].getFConst() > 3653 unionArrays[1][i].getFConst()); 3654 break; 3655 case EbtInt: 3656 resultArray[i].setBConst(unionArrays[0][i].getIConst() > 3657 unionArrays[1][i].getIConst()); 3658 break; 3659 case EbtUInt: 3660 resultArray[i].setBConst(unionArrays[0][i].getUConst() > 3661 unionArrays[1][i].getUConst()); 3662 break; 3663 default: 3664 UNREACHABLE(); 3665 break; 3666 } 3667 } 3668 break; 3669 } 3670 case EOpGreaterThanEqualComponentWise: 3671 { 3672 resultArray = new TConstantUnion[maxObjectSize]; 3673 for (size_t i = 0; i < maxObjectSize; i++) 3674 { 3675 switch (basicType) 3676 { 3677 case EbtFloat: 3678 resultArray[i].setBConst(unionArrays[0][i].getFConst() >= 3679 unionArrays[1][i].getFConst()); 3680 break; 3681 case EbtInt: 3682 resultArray[i].setBConst(unionArrays[0][i].getIConst() >= 3683 unionArrays[1][i].getIConst()); 3684 break; 3685 case EbtUInt: 3686 resultArray[i].setBConst(unionArrays[0][i].getUConst() >= 3687 unionArrays[1][i].getUConst()); 3688 break; 3689 default: 3690 UNREACHABLE(); 3691 break; 3692 } 3693 } 3694 } 3695 break; 3696 3697 case EOpEqualComponentWise: 3698 { 3699 resultArray = new TConstantUnion[maxObjectSize]; 3700 for (size_t i = 0; i < maxObjectSize; i++) 3701 { 3702 switch (basicType) 3703 { 3704 case EbtFloat: 3705 resultArray[i].setBConst(unionArrays[0][i].getFConst() == 3706 unionArrays[1][i].getFConst()); 3707 break; 3708 case EbtInt: 3709 resultArray[i].setBConst(unionArrays[0][i].getIConst() == 3710 unionArrays[1][i].getIConst()); 3711 break; 3712 case EbtUInt: 3713 resultArray[i].setBConst(unionArrays[0][i].getUConst() == 3714 unionArrays[1][i].getUConst()); 3715 break; 3716 case EbtBool: 3717 resultArray[i].setBConst(unionArrays[0][i].getBConst() == 3718 unionArrays[1][i].getBConst()); 3719 break; 3720 default: 3721 UNREACHABLE(); 3722 break; 3723 } 3724 } 3725 break; 3726 } 3727 3728 case EOpNotEqualComponentWise: 3729 { 3730 resultArray = new TConstantUnion[maxObjectSize]; 3731 for (size_t i = 0; i < maxObjectSize; i++) 3732 { 3733 switch (basicType) 3734 { 3735 case EbtFloat: 3736 resultArray[i].setBConst(unionArrays[0][i].getFConst() != 3737 unionArrays[1][i].getFConst()); 3738 break; 3739 case EbtInt: 3740 resultArray[i].setBConst(unionArrays[0][i].getIConst() != 3741 unionArrays[1][i].getIConst()); 3742 break; 3743 case EbtUInt: 3744 resultArray[i].setBConst(unionArrays[0][i].getUConst() != 3745 unionArrays[1][i].getUConst()); 3746 break; 3747 case EbtBool: 3748 resultArray[i].setBConst(unionArrays[0][i].getBConst() != 3749 unionArrays[1][i].getBConst()); 3750 break; 3751 default: 3752 UNREACHABLE(); 3753 break; 3754 } 3755 } 3756 break; 3757 } 3758 3759 case EOpDistance: 3760 { 3761 ASSERT(basicType == EbtFloat); 3762 TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize]; 3763 resultArray = new TConstantUnion(); 3764 for (size_t i = 0; i < maxObjectSize; i++) 3765 { 3766 float x = unionArrays[0][i].getFConst(); 3767 float y = unionArrays[1][i].getFConst(); 3768 distanceArray[i].setFConst(x - y); 3769 } 3770 resultArray->setFConst(VectorLength(distanceArray, maxObjectSize)); 3771 break; 3772 } 3773 3774 case EOpDot: 3775 ASSERT(basicType == EbtFloat); 3776 resultArray = new TConstantUnion(); 3777 resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize)); 3778 break; 3779 3780 case EOpCross: 3781 { 3782 ASSERT(basicType == EbtFloat && maxObjectSize == 3); 3783 resultArray = new TConstantUnion[maxObjectSize]; 3784 float x0 = unionArrays[0][0].getFConst(); 3785 float x1 = unionArrays[0][1].getFConst(); 3786 float x2 = unionArrays[0][2].getFConst(); 3787 float y0 = unionArrays[1][0].getFConst(); 3788 float y1 = unionArrays[1][1].getFConst(); 3789 float y2 = unionArrays[1][2].getFConst(); 3790 resultArray[0].setFConst(x1 * y2 - y1 * x2); 3791 resultArray[1].setFConst(x2 * y0 - y2 * x0); 3792 resultArray[2].setFConst(x0 * y1 - y0 * x1); 3793 break; 3794 } 3795 3796 case EOpReflect: 3797 { 3798 ASSERT(basicType == EbtFloat); 3799 // genType reflect (genType I, genType N) : 3800 // For the incident vector I and surface orientation N, returns the reflection 3801 // direction: 3802 // I - 2 * dot(N, I) * N. 3803 resultArray = new TConstantUnion[maxObjectSize]; 3804 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); 3805 for (size_t i = 0; i < maxObjectSize; i++) 3806 { 3807 float result = unionArrays[0][i].getFConst() - 3808 2.0f * dotProduct * unionArrays[1][i].getFConst(); 3809 resultArray[i].setFConst(result); 3810 } 3811 break; 3812 } 3813 3814 case EOpMatrixCompMult: 3815 { 3816 ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() && 3817 (*arguments)[1]->getAsTyped()->isMatrix()); 3818 // Perform component-wise matrix multiplication. 3819 resultArray = new TConstantUnion[maxObjectSize]; 3820 const uint8_t rows = (*arguments)[0]->getAsTyped()->getRows(); 3821 const uint8_t cols = (*arguments)[0]->getAsTyped()->getCols(); 3822 angle::Matrix<float> lhs = GetMatrix(unionArrays[0], rows, cols); 3823 angle::Matrix<float> rhs = GetMatrix(unionArrays[1], rows, cols); 3824 angle::Matrix<float> result = lhs.compMult(rhs); 3825 SetUnionArrayFromMatrix(result, resultArray); 3826 break; 3827 } 3828 3829 case EOpOuterProduct: 3830 { 3831 ASSERT(basicType == EbtFloat); 3832 size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize(); 3833 size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize(); 3834 resultArray = new TConstantUnion[numRows * numCols]; 3835 angle::Matrix<float> result = 3836 GetMatrix(unionArrays[0], static_cast<int>(numRows), 1) 3837 .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols))); 3838 SetUnionArrayFromMatrix(result, resultArray); 3839 break; 3840 } 3841 3842 case EOpClamp: 3843 { 3844 resultArray = new TConstantUnion[maxObjectSize]; 3845 for (size_t i = 0; i < maxObjectSize; i++) 3846 { 3847 switch (basicType) 3848 { 3849 case EbtFloat: 3850 { 3851 float x = unionArrays[0][i].getFConst(); 3852 float min = unionArrays[1][i].getFConst(); 3853 float max = unionArrays[2][i].getFConst(); 3854 // Results are undefined if min > max. 3855 if (min > max) 3856 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 3857 &resultArray[i]); 3858 else 3859 resultArray[i].setFConst(gl::clamp(x, min, max)); 3860 break; 3861 } 3862 3863 case EbtInt: 3864 { 3865 int x = unionArrays[0][i].getIConst(); 3866 int min = unionArrays[1][i].getIConst(); 3867 int max = unionArrays[2][i].getIConst(); 3868 // Results are undefined if min > max. 3869 if (min > max) 3870 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 3871 &resultArray[i]); 3872 else 3873 resultArray[i].setIConst(gl::clamp(x, min, max)); 3874 break; 3875 } 3876 case EbtUInt: 3877 { 3878 unsigned int x = unionArrays[0][i].getUConst(); 3879 unsigned int min = unionArrays[1][i].getUConst(); 3880 unsigned int max = unionArrays[2][i].getUConst(); 3881 // Results are undefined if min > max. 3882 if (min > max) 3883 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 3884 &resultArray[i]); 3885 else 3886 resultArray[i].setUConst(gl::clamp(x, min, max)); 3887 break; 3888 } 3889 default: 3890 UNREACHABLE(); 3891 break; 3892 } 3893 } 3894 break; 3895 } 3896 3897 case EOpMix: 3898 { 3899 resultArray = new TConstantUnion[maxObjectSize]; 3900 for (size_t i = 0; i < maxObjectSize; i++) 3901 { 3902 TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType(); 3903 if (type == EbtFloat) 3904 { 3905 ASSERT(basicType == EbtFloat); 3906 float x = unionArrays[0][i].getFConst(); 3907 float y = unionArrays[1][i].getFConst(); 3908 3909 // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a. 3910 float a = unionArrays[2][i].getFConst(); 3911 resultArray[i].setFConst(x * (1.0f - a) + y * a); 3912 } 3913 else // 3rd parameter is EbtBool 3914 { 3915 ASSERT(type == EbtBool); 3916 // Selects which vector each returned component comes from. 3917 // For a component of a that is false, the corresponding component of x is 3918 // returned. 3919 // For a component of a that is true, the corresponding component of y is 3920 // returned. 3921 bool a = unionArrays[2][i].getBConst(); 3922 switch (basicType) 3923 { 3924 case EbtFloat: 3925 { 3926 float x = unionArrays[0][i].getFConst(); 3927 float y = unionArrays[1][i].getFConst(); 3928 resultArray[i].setFConst(a ? y : x); 3929 } 3930 break; 3931 case EbtInt: 3932 { 3933 int x = unionArrays[0][i].getIConst(); 3934 int y = unionArrays[1][i].getIConst(); 3935 resultArray[i].setIConst(a ? y : x); 3936 } 3937 break; 3938 case EbtUInt: 3939 { 3940 unsigned int x = unionArrays[0][i].getUConst(); 3941 unsigned int y = unionArrays[1][i].getUConst(); 3942 resultArray[i].setUConst(a ? y : x); 3943 } 3944 break; 3945 case EbtBool: 3946 { 3947 bool x = unionArrays[0][i].getBConst(); 3948 bool y = unionArrays[1][i].getBConst(); 3949 resultArray[i].setBConst(a ? y : x); 3950 } 3951 break; 3952 default: 3953 UNREACHABLE(); 3954 break; 3955 } 3956 } 3957 } 3958 break; 3959 } 3960 3961 case EOpSmoothstep: 3962 { 3963 ASSERT(basicType == EbtFloat); 3964 resultArray = new TConstantUnion[maxObjectSize]; 3965 for (size_t i = 0; i < maxObjectSize; i++) 3966 { 3967 float edge0 = unionArrays[0][i].getFConst(); 3968 float edge1 = unionArrays[1][i].getFConst(); 3969 float x = unionArrays[2][i].getFConst(); 3970 // Results are undefined if edge0 >= edge1. 3971 if (edge0 >= edge1) 3972 { 3973 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 3974 &resultArray[i]); 3975 } 3976 else 3977 { 3978 // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth 3979 // Hermite interpolation between 0 and 1 when edge0 < x < edge1. 3980 float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); 3981 resultArray[i].setFConst(t * t * (3.0f - 2.0f * t)); 3982 } 3983 } 3984 break; 3985 } 3986 3987 case EOpFma: 3988 { 3989 ASSERT(basicType == EbtFloat); 3990 resultArray = new TConstantUnion[maxObjectSize]; 3991 for (size_t i = 0; i < maxObjectSize; i++) 3992 { 3993 float a = unionArrays[0][i].getFConst(); 3994 float b = unionArrays[1][i].getFConst(); 3995 float c = unionArrays[2][i].getFConst(); 3996 3997 // Returns a * b + c. 3998 resultArray[i].setFConst(a * b + c); 3999 } 4000 break; 4001 } 4002 4003 case EOpLdexp: 4004 { 4005 resultArray = new TConstantUnion[maxObjectSize]; 4006 for (size_t i = 0; i < maxObjectSize; i++) 4007 { 4008 float x = unionArrays[0][i].getFConst(); 4009 int exp = unionArrays[1][i].getIConst(); 4010 if (exp > 128) 4011 { 4012 UndefinedConstantFoldingError(loc, function, basicType, diagnostics, 4013 &resultArray[i]); 4014 } 4015 else 4016 { 4017 resultArray[i].setFConst(gl::Ldexp(x, exp)); 4018 } 4019 } 4020 break; 4021 } 4022 4023 case EOpFaceforward: 4024 { 4025 ASSERT(basicType == EbtFloat); 4026 // genType faceforward(genType N, genType I, genType Nref) : 4027 // If dot(Nref, I) < 0 return N, otherwise return -N. 4028 resultArray = new TConstantUnion[maxObjectSize]; 4029 float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize); 4030 for (size_t i = 0; i < maxObjectSize; i++) 4031 { 4032 if (dotProduct < 0) 4033 resultArray[i].setFConst(unionArrays[0][i].getFConst()); 4034 else 4035 resultArray[i].setFConst(-unionArrays[0][i].getFConst()); 4036 } 4037 break; 4038 } 4039 4040 case EOpRefract: 4041 { 4042 ASSERT(basicType == EbtFloat); 4043 // genType refract(genType I, genType N, float eta) : 4044 // For the incident vector I and surface normal N, and the ratio of indices of 4045 // refraction eta, 4046 // return the refraction vector. The result is computed by 4047 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) 4048 // if (k < 0.0) 4049 // return genType(0.0) 4050 // else 4051 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N 4052 resultArray = new TConstantUnion[maxObjectSize]; 4053 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); 4054 for (size_t i = 0; i < maxObjectSize; i++) 4055 { 4056 float eta = unionArrays[2][i].getFConst(); 4057 float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct); 4058 if (k < 0.0f) 4059 resultArray[i].setFConst(0.0f); 4060 else 4061 resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() - 4062 (eta * dotProduct + sqrtf(k)) * 4063 unionArrays[1][i].getFConst()); 4064 } 4065 break; 4066 } 4067 case EOpBitfieldExtract: 4068 { 4069 resultArray = new TConstantUnion[maxObjectSize]; 4070 for (size_t i = 0; i < maxObjectSize; ++i) 4071 { 4072 int offset = unionArrays[1][0].getIConst(); 4073 int bits = unionArrays[2][0].getIConst(); 4074 if (bits == 0) 4075 { 4076 if (aggregate->getBasicType() == EbtInt) 4077 { 4078 resultArray[i].setIConst(0); 4079 } 4080 else 4081 { 4082 ASSERT(aggregate->getBasicType() == EbtUInt); 4083 resultArray[i].setUConst(0); 4084 } 4085 } 4086 else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) 4087 { 4088 UndefinedConstantFoldingError(loc, function, aggregate->getBasicType(), 4089 diagnostics, &resultArray[i]); 4090 } 4091 else 4092 { 4093 // bits can be 32 here, so we need to avoid bit shift overflow. 4094 uint32_t maskMsb = 1u << (bits - 1); 4095 uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset; 4096 if (aggregate->getBasicType() == EbtInt) 4097 { 4098 uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst()); 4099 uint32_t resultUnsigned = (value & mask) >> offset; 4100 if ((resultUnsigned & maskMsb) != 0) 4101 { 4102 // The most significant bits (from bits+1 to the most significant bit) 4103 // should be set to 1. 4104 uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits; 4105 resultUnsigned |= higherBitsMask; 4106 } 4107 resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned)); 4108 } 4109 else 4110 { 4111 ASSERT(aggregate->getBasicType() == EbtUInt); 4112 uint32_t value = unionArrays[0][i].getUConst(); 4113 resultArray[i].setUConst((value & mask) >> offset); 4114 } 4115 } 4116 } 4117 break; 4118 } 4119 case EOpBitfieldInsert: 4120 { 4121 resultArray = new TConstantUnion[maxObjectSize]; 4122 for (size_t i = 0; i < maxObjectSize; ++i) 4123 { 4124 int offset = unionArrays[2][0].getIConst(); 4125 int bits = unionArrays[3][0].getIConst(); 4126 if (bits == 0) 4127 { 4128 if (aggregate->getBasicType() == EbtInt) 4129 { 4130 int32_t base = unionArrays[0][i].getIConst(); 4131 resultArray[i].setIConst(base); 4132 } 4133 else 4134 { 4135 ASSERT(aggregate->getBasicType() == EbtUInt); 4136 uint32_t base = unionArrays[0][i].getUConst(); 4137 resultArray[i].setUConst(base); 4138 } 4139 } 4140 else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32) 4141 { 4142 UndefinedConstantFoldingError(loc, function, aggregate->getBasicType(), 4143 diagnostics, &resultArray[i]); 4144 } 4145 else 4146 { 4147 // bits can be 32 here, so we need to avoid bit shift overflow. 4148 uint32_t maskMsb = 1u << (bits - 1); 4149 uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset; 4150 uint32_t baseMask = ~insertMask; 4151 if (aggregate->getBasicType() == EbtInt) 4152 { 4153 uint32_t base = static_cast<uint32_t>(unionArrays[0][i].getIConst()); 4154 uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst()); 4155 uint32_t resultUnsigned = 4156 (base & baseMask) | ((insert << offset) & insertMask); 4157 resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned)); 4158 } 4159 else 4160 { 4161 ASSERT(aggregate->getBasicType() == EbtUInt); 4162 uint32_t base = unionArrays[0][i].getUConst(); 4163 uint32_t insert = unionArrays[1][i].getUConst(); 4164 resultArray[i].setUConst((base & baseMask) | 4165 ((insert << offset) & insertMask)); 4166 } 4167 } 4168 } 4169 break; 4170 } 4171 case EOpDFdx: 4172 case EOpDFdy: 4173 case EOpFwidth: 4174 ASSERT(basicType == EbtFloat); 4175 resultArray = new TConstantUnion[maxObjectSize]; 4176 for (size_t i = 0; i < maxObjectSize; i++) 4177 { 4178 // Derivatives of constant arguments should be 0. 4179 resultArray[i].setFConst(0.0f); 4180 } 4181 break; 4182 4183 default: 4184 UNREACHABLE(); 4185 return nullptr; 4186 } 4187 return resultArray; 4188 } 4189 4190 bool TIntermConstantUnion::IsFloatDivision(TBasicType t1, TBasicType t2) 4191 { 4192 ImplicitTypeConversion conversion = GetConversion(t1, t2); 4193 ASSERT(conversion != ImplicitTypeConversion::Invalid); 4194 if (conversion == ImplicitTypeConversion::Same) 4195 { 4196 if (t1 == EbtFloat) 4197 return true; 4198 return false; 4199 } 4200 ASSERT(t1 == EbtFloat || t2 == EbtFloat); 4201 return true; 4202 } 4203 4204 // TIntermPreprocessorDirective implementation. 4205 TIntermPreprocessorDirective::TIntermPreprocessorDirective(PreprocessorDirective directive, 4206 ImmutableString command) 4207 : mDirective(directive), mCommand(std::move(command)) 4208 {} 4209 4210 TIntermPreprocessorDirective::TIntermPreprocessorDirective(const TIntermPreprocessorDirective &node) 4211 : TIntermPreprocessorDirective(node.mDirective, node.mCommand) 4212 {} 4213 4214 TIntermPreprocessorDirective::~TIntermPreprocessorDirective() = default; 4215 4216 size_t TIntermPreprocessorDirective::getChildCount() const 4217 { 4218 return 0; 4219 } 4220 4221 TIntermNode *TIntermPreprocessorDirective::getChildNode(size_t index) const 4222 { 4223 UNREACHABLE(); 4224 return nullptr; 4225 } 4226 } // namespace sh