1 // 2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 // Copyright (C) 2012-2015 LunarG, Inc. 4 // Copyright (C) 2015-2018 Google, Inc. 5 // Copyright (C) 2017 ARM Limited. 6 // 7 // All rights reserved. 8 // 9 // Redistribution and use in source and binary forms, with or without 10 // modification, are permitted provided that the following conditions 11 // are met: 12 // 13 // Redistributions of source code must retain the above copyright 14 // notice, this list of conditions and the following disclaimer. 15 // 16 // Redistributions in binary form must reproduce the above 17 // copyright notice, this list of conditions and the following 18 // disclaimer in the documentation and/or other materials provided 19 // with the distribution. 20 // 21 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 22 // contributors may be used to endorse or promote products derived 23 // from this software without specific prior written permission. 24 // 25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 // POSSIBILITY OF SUCH DAMAGE. 37 // 38 39 // 40 // Build the intermediate representation. 41 // 42 43 #include "localintermediate.h" 44 #include "RemoveTree.h" 45 #include "SymbolTable.h" 46 #include "propagateNoContraction.h" 47 48 #include <cfloat> 49 #include <utility> 50 #include <tuple> 51 52 namespace glslang { 53 54 //////////////////////////////////////////////////////////////////////////// 55 // 56 // First set of functions are to help build the intermediate representation. 57 // These functions are not member functions of the nodes. 58 // They are called from parser productions. 59 // 60 ///////////////////////////////////////////////////////////////////////////// 61 62 // 63 // Add a terminal node for an identifier in an expression. 64 // 65 // Returns the added node. 66 // 67 68 TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, 69 TIntermTyped* constSubtree, const TSourceLoc& loc) 70 { 71 TIntermSymbol* node = new TIntermSymbol(id, name, type); 72 node->setLoc(loc); 73 node->setConstArray(constArray); 74 node->setConstSubtree(constSubtree); 75 76 return node; 77 } 78 79 TIntermSymbol* TIntermediate::addSymbol(const TIntermSymbol& intermSymbol) 80 { 81 return addSymbol(intermSymbol.getId(), 82 intermSymbol.getName(), 83 intermSymbol.getType(), 84 intermSymbol.getConstArray(), 85 intermSymbol.getConstSubtree(), 86 intermSymbol.getLoc()); 87 } 88 89 TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable) 90 { 91 glslang::TSourceLoc loc; // just a null location 92 loc.init(); 93 94 return addSymbol(variable, loc); 95 } 96 97 TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc) 98 { 99 return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc); 100 } 101 102 TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc) 103 { 104 TConstUnionArray unionArray; // just a null constant 105 106 return addSymbol(0, "", type, unionArray, nullptr, loc); 107 } 108 109 // 110 // Connect two nodes with a new parent that does a binary operation on the nodes. 111 // 112 // Returns the added node. 113 // 114 // Returns nullptr if the working conversions and promotions could not be found. 115 // 116 TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) 117 { 118 // No operations work on blocks 119 if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) 120 return nullptr; 121 122 // Try converting the children's base types to compatible types. 123 auto children = addConversion(op, left, right); 124 left = std::get<0>(children); 125 right = std::get<1>(children); 126 127 if (left == nullptr || right == nullptr) 128 return nullptr; 129 130 // Convert the children's type shape to be compatible. 131 addBiShapeConversion(op, left, right); 132 if (left == nullptr || right == nullptr) 133 return nullptr; 134 135 // 136 // Need a new node holding things together. Make 137 // one and promote it to the right type. 138 // 139 TIntermBinary* node = addBinaryNode(op, left, right, loc); 140 if (! promote(node)) 141 return nullptr; 142 143 node->updatePrecision(); 144 145 // 146 // If they are both (non-specialization) constants, they must be folded. 147 // (Unless it's the sequence (comma) operator, but that's handled in addComma().) 148 // 149 TIntermConstantUnion *leftTempConstant = node->getLeft()->getAsConstantUnion(); 150 TIntermConstantUnion *rightTempConstant = node->getRight()->getAsConstantUnion(); 151 if (leftTempConstant && rightTempConstant) { 152 TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant); 153 if (folded) 154 return folded; 155 } 156 157 // If can propagate spec-constantness and if the operation is an allowed 158 // specialization-constant operation, make a spec-constant. 159 if (specConstantPropagates(*node->getLeft(), *node->getRight()) && isSpecializationOperation(*node)) 160 node->getWritableType().getQualifier().makeSpecConstant(); 161 162 // If must propagate nonuniform, make a nonuniform. 163 if ((node->getLeft()->getQualifier().nonUniform || node->getRight()->getQualifier().nonUniform) && 164 isNonuniformPropagating(node->getOp())) 165 node->getWritableType().getQualifier().nonUniform = true; 166 167 return node; 168 } 169 170 // 171 // Low level: add binary node (no promotions or other argument modifications) 172 // 173 TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const 174 { 175 // build the node 176 TIntermBinary* node = new TIntermBinary(op); 177 if (loc.line == 0) 178 loc = left->getLoc(); 179 node->setLoc(loc); 180 node->setLeft(left); 181 node->setRight(right); 182 183 return node; 184 } 185 186 // 187 // like non-type form, but sets node's type. 188 // 189 TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const 190 { 191 TIntermBinary* node = addBinaryNode(op, left, right, loc); 192 node->setType(type); 193 return node; 194 } 195 196 // 197 // Low level: add unary node (no promotions or other argument modifications) 198 // 199 TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const 200 { 201 TIntermUnary* node = new TIntermUnary(op); 202 if (loc.line == 0) 203 loc = child->getLoc(); 204 node->setLoc(loc); 205 node->setOperand(child); 206 207 return node; 208 } 209 210 // 211 // like non-type form, but sets node's type. 212 // 213 TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const 214 { 215 TIntermUnary* node = addUnaryNode(op, child, loc); 216 node->setType(type); 217 return node; 218 } 219 220 // 221 // Connect two nodes through an assignment. 222 // 223 // Returns the added node. 224 // 225 // Returns nullptr if the 'right' type could not be converted to match the 'left' type, 226 // or the resulting operation cannot be properly promoted. 227 // 228 TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) 229 { 230 // No block assignment 231 if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) 232 return nullptr; 233 234 // 235 // Like adding binary math, except the conversion can only go 236 // from right to left. 237 // 238 239 // convert base types, nullptr return means not possible 240 right = addConversion(op, left->getType(), right); 241 if (right == nullptr) 242 return nullptr; 243 244 // convert shape 245 right = addUniShapeConversion(op, left->getType(), right); 246 247 // build the node 248 TIntermBinary* node = addBinaryNode(op, left, right, loc); 249 250 if (! promote(node)) 251 return nullptr; 252 253 node->updatePrecision(); 254 255 return node; 256 } 257 258 // 259 // Connect two nodes through an index operator, where the left node is the base 260 // of an array or struct, and the right node is a direct or indirect offset. 261 // 262 // Returns the added node. 263 // The caller should set the type of the returned node. 264 // 265 TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc) 266 { 267 // caller should set the type 268 return addBinaryNode(op, base, index, loc); 269 } 270 271 // 272 // Add one node as the parent of another that it operates on. 273 // 274 // Returns the added node. 275 // 276 TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc) 277 { 278 if (child == 0) 279 return nullptr; 280 281 if (child->getType().getBasicType() == EbtBlock) 282 return nullptr; 283 284 switch (op) { 285 case EOpLogicalNot: 286 if (source == EShSourceHlsl) { 287 break; // HLSL can promote logical not 288 } 289 290 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { 291 return nullptr; 292 } 293 break; 294 295 case EOpPostIncrement: 296 case EOpPreIncrement: 297 case EOpPostDecrement: 298 case EOpPreDecrement: 299 case EOpNegative: 300 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) 301 return nullptr; 302 default: break; // some compilers want this 303 } 304 305 // 306 // Do we need to promote the operand? 307 // 308 TBasicType newType = EbtVoid; 309 switch (op) { 310 case EOpConstructInt8: newType = EbtInt8; break; 311 case EOpConstructUint8: newType = EbtUint8; break; 312 case EOpConstructInt16: newType = EbtInt16; break; 313 case EOpConstructUint16: newType = EbtUint16; break; 314 case EOpConstructInt: newType = EbtInt; break; 315 case EOpConstructUint: newType = EbtUint; break; 316 case EOpConstructInt64: newType = EbtInt64; break; 317 case EOpConstructUint64: newType = EbtUint64; break; 318 case EOpConstructBool: newType = EbtBool; break; 319 case EOpConstructFloat: newType = EbtFloat; break; 320 case EOpConstructDouble: newType = EbtDouble; break; 321 case EOpConstructFloat16: newType = EbtFloat16; break; 322 default: break; // some compilers want this 323 } 324 325 if (newType != EbtVoid) { 326 child = addConversion(op, TType(newType, EvqTemporary, child->getVectorSize(), 327 child->getMatrixCols(), 328 child->getMatrixRows(), 329 child->isVector()), 330 child); 331 if (child == nullptr) 332 return nullptr; 333 } 334 335 // 336 // For constructors, we are now done, it was all in the conversion. 337 // TODO: but, did this bypass constant folding? 338 // 339 switch (op) { 340 case EOpConstructInt8: 341 case EOpConstructUint8: 342 case EOpConstructInt16: 343 case EOpConstructUint16: 344 case EOpConstructInt: 345 case EOpConstructUint: 346 case EOpConstructInt64: 347 case EOpConstructUint64: 348 case EOpConstructBool: 349 case EOpConstructFloat: 350 case EOpConstructDouble: 351 case EOpConstructFloat16: 352 return child; 353 default: break; // some compilers want this 354 } 355 356 // 357 // Make a new node for the operator. 358 // 359 TIntermUnary* node = addUnaryNode(op, child, loc); 360 361 if (! promote(node)) 362 return nullptr; 363 364 node->updatePrecision(); 365 366 // If it's a (non-specialization) constant, it must be folded. 367 if (node->getOperand()->getAsConstantUnion()) 368 return node->getOperand()->getAsConstantUnion()->fold(op, node->getType()); 369 370 // If it's a specialization constant, the result is too, 371 // if the operation is allowed for specialization constants. 372 if (node->getOperand()->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node)) 373 node->getWritableType().getQualifier().makeSpecConstant(); 374 375 // If must propagate nonuniform, make a nonuniform. 376 if (node->getOperand()->getQualifier().nonUniform && isNonuniformPropagating(node->getOp())) 377 node->getWritableType().getQualifier().nonUniform = true; 378 379 return node; 380 } 381 382 TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOperator op, bool unary, 383 TIntermNode* childNode, const TType& returnType) 384 { 385 if (unary) { 386 // 387 // Treat it like a unary operator. 388 // addUnaryMath() should get the type correct on its own; 389 // including constness (which would differ from the prototype). 390 // 391 TIntermTyped* child = childNode->getAsTyped(); 392 if (child == nullptr) 393 return nullptr; 394 395 if (child->getAsConstantUnion()) { 396 TIntermTyped* folded = child->getAsConstantUnion()->fold(op, returnType); 397 if (folded) 398 return folded; 399 } 400 401 return addUnaryNode(op, child, child->getLoc(), returnType); 402 } else { 403 // setAggregateOperater() calls fold() for constant folding 404 TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc); 405 406 return node; 407 } 408 } 409 410 // 411 // This is the safe way to change the operator on an aggregate, as it 412 // does lots of error checking and fixing. Especially for establishing 413 // a function call's operation on it's set of parameters. Sequences 414 // of instructions are also aggregates, but they just directly set 415 // their operator to EOpSequence. 416 // 417 // Returns an aggregate node, which could be the one passed in if 418 // it was already an aggregate. 419 // 420 TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc) 421 { 422 TIntermAggregate* aggNode; 423 424 // 425 // Make sure we have an aggregate. If not turn it into one. 426 // 427 if (node != nullptr) { 428 aggNode = node->getAsAggregate(); 429 if (aggNode == nullptr || aggNode->getOp() != EOpNull) { 430 // 431 // Make an aggregate containing this node. 432 // 433 aggNode = new TIntermAggregate(); 434 aggNode->getSequence().push_back(node); 435 if (loc.line == 0) 436 loc = node->getLoc(); 437 } 438 } else 439 aggNode = new TIntermAggregate(); 440 441 // 442 // Set the operator. 443 // 444 aggNode->setOperator(op); 445 if (loc.line != 0) 446 aggNode->setLoc(loc); 447 448 aggNode->setType(type); 449 450 return fold(aggNode); 451 } 452 453 bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const 454 { 455 // 456 // Does the base type even allow the operation? 457 // 458 switch (node->getBasicType()) { 459 case EbtVoid: 460 return false; 461 case EbtAtomicUint: 462 case EbtSampler: 463 #ifdef NV_EXTENSIONS 464 case EbtAccStructNV: 465 #endif 466 // opaque types can be passed to functions 467 if (op == EOpFunction) 468 break; 469 470 // HLSL can assign samplers directly (no constructor) 471 if (source == EShSourceHlsl && node->getBasicType() == EbtSampler) 472 break; 473 474 // samplers can get assigned via a sampler constructor 475 // (well, not yet, but code in the rest of this function is ready for it) 476 if (node->getBasicType() == EbtSampler && op == EOpAssign && 477 node->getAsOperator() != nullptr && node->getAsOperator()->getOp() == EOpConstructTextureSampler) 478 break; 479 480 // otherwise, opaque types can't even be operated on, let alone converted 481 return false; 482 default: 483 break; 484 } 485 486 return true; 487 } 488 489 // This is 'mechanism' here, it does any conversion told. 490 // It is about basic type, not about shape. 491 // The policy comes from the shader or the calling code. 492 TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped* node) const 493 { 494 // 495 // Add a new newNode for the conversion. 496 // 497 TIntermUnary* newNode = nullptr; 498 499 TOperator newOp = EOpNull; 500 501 switch (convertTo) { 502 case EbtDouble: 503 switch (node->getBasicType()) { 504 case EbtInt8: newOp = EOpConvInt8ToDouble; break; 505 case EbtUint8: newOp = EOpConvUint8ToDouble; break; 506 case EbtInt16: newOp = EOpConvInt16ToDouble; break; 507 case EbtUint16: newOp = EOpConvUint16ToDouble; break; 508 case EbtInt: newOp = EOpConvIntToDouble; break; 509 case EbtUint: newOp = EOpConvUintToDouble; break; 510 case EbtBool: newOp = EOpConvBoolToDouble; break; 511 case EbtFloat: newOp = EOpConvFloatToDouble; break; 512 case EbtFloat16: newOp = EOpConvFloat16ToDouble; break; 513 case EbtInt64: newOp = EOpConvInt64ToDouble; break; 514 case EbtUint64: newOp = EOpConvUint64ToDouble; break; 515 default: 516 return nullptr; 517 } 518 break; 519 case EbtFloat: 520 switch (node->getBasicType()) { 521 case EbtInt8: newOp = EOpConvInt8ToFloat; break; 522 case EbtUint8: newOp = EOpConvUint8ToFloat; break; 523 case EbtInt16: newOp = EOpConvInt16ToFloat; break; 524 case EbtUint16: newOp = EOpConvUint16ToFloat; break; 525 case EbtInt: newOp = EOpConvIntToFloat; break; 526 case EbtUint: newOp = EOpConvUintToFloat; break; 527 case EbtBool: newOp = EOpConvBoolToFloat; break; 528 case EbtDouble: newOp = EOpConvDoubleToFloat; break; 529 case EbtFloat16: newOp = EOpConvFloat16ToFloat; break; 530 case EbtInt64: newOp = EOpConvInt64ToFloat; break; 531 case EbtUint64: newOp = EOpConvUint64ToFloat; break; 532 default: 533 return nullptr; 534 } 535 break; 536 case EbtFloat16: 537 switch (node->getBasicType()) { 538 case EbtInt8: newOp = EOpConvInt8ToFloat16; break; 539 case EbtUint8: newOp = EOpConvUint8ToFloat16; break; 540 case EbtInt16: newOp = EOpConvInt16ToFloat16; break; 541 case EbtUint16: newOp = EOpConvUint16ToFloat16; break; 542 case EbtInt: newOp = EOpConvIntToFloat16; break; 543 case EbtUint: newOp = EOpConvUintToFloat16; break; 544 case EbtBool: newOp = EOpConvBoolToFloat16; break; 545 case EbtFloat: newOp = EOpConvFloatToFloat16; break; 546 case EbtDouble: newOp = EOpConvDoubleToFloat16; break; 547 case EbtInt64: newOp = EOpConvInt64ToFloat16; break; 548 case EbtUint64: newOp = EOpConvUint64ToFloat16; break; 549 default: 550 return nullptr; 551 } 552 break; 553 case EbtBool: 554 switch (node->getBasicType()) { 555 case EbtInt8: newOp = EOpConvInt8ToBool; break; 556 case EbtUint8: newOp = EOpConvUint8ToBool; break; 557 case EbtInt16: newOp = EOpConvInt16ToBool; break; 558 case EbtUint16: newOp = EOpConvUint16ToBool; break; 559 case EbtInt: newOp = EOpConvIntToBool; break; 560 case EbtUint: newOp = EOpConvUintToBool; break; 561 case EbtFloat: newOp = EOpConvFloatToBool; break; 562 case EbtDouble: newOp = EOpConvDoubleToBool; break; 563 case EbtFloat16: newOp = EOpConvFloat16ToBool; break; 564 case EbtInt64: newOp = EOpConvInt64ToBool; break; 565 case EbtUint64: newOp = EOpConvUint64ToBool; break; 566 default: 567 return nullptr; 568 } 569 break; 570 case EbtInt8: 571 switch (node->getBasicType()) { 572 case EbtUint8: newOp = EOpConvUint8ToInt8; break; 573 case EbtInt16: newOp = EOpConvInt16ToInt8; break; 574 case EbtUint16: newOp = EOpConvUint16ToInt8; break; 575 case EbtInt: newOp = EOpConvIntToInt8; break; 576 case EbtUint: newOp = EOpConvUintToInt8; break; 577 case EbtInt64: newOp = EOpConvInt64ToInt8; break; 578 case EbtUint64: newOp = EOpConvUint64ToInt8; break; 579 case EbtBool: newOp = EOpConvBoolToInt8; break; 580 case EbtFloat: newOp = EOpConvFloatToInt8; break; 581 case EbtDouble: newOp = EOpConvDoubleToInt8; break; 582 case EbtFloat16: newOp = EOpConvFloat16ToInt8; break; 583 default: 584 return nullptr; 585 } 586 break; 587 case EbtUint8: 588 switch (node->getBasicType()) { 589 case EbtInt8: newOp = EOpConvInt8ToUint8; break; 590 case EbtInt16: newOp = EOpConvInt16ToUint8; break; 591 case EbtUint16: newOp = EOpConvUint16ToUint8; break; 592 case EbtInt: newOp = EOpConvIntToUint8; break; 593 case EbtUint: newOp = EOpConvUintToUint8; break; 594 case EbtInt64: newOp = EOpConvInt64ToUint8; break; 595 case EbtUint64: newOp = EOpConvUint64ToUint8; break; 596 case EbtBool: newOp = EOpConvBoolToUint8; break; 597 case EbtFloat: newOp = EOpConvFloatToUint8; break; 598 case EbtDouble: newOp = EOpConvDoubleToUint8; break; 599 case EbtFloat16: newOp = EOpConvFloat16ToUint8; break; 600 default: 601 return nullptr; 602 } 603 break; 604 605 case EbtInt16: 606 switch (node->getBasicType()) { 607 case EbtUint8: newOp = EOpConvUint8ToInt16; break; 608 case EbtInt8: newOp = EOpConvInt8ToInt16; break; 609 case EbtUint16: newOp = EOpConvUint16ToInt16; break; 610 case EbtInt: newOp = EOpConvIntToInt16; break; 611 case EbtUint: newOp = EOpConvUintToInt16; break; 612 case EbtInt64: newOp = EOpConvInt64ToInt16; break; 613 case EbtUint64: newOp = EOpConvUint64ToInt16; break; 614 case EbtBool: newOp = EOpConvBoolToInt16; break; 615 case EbtFloat: newOp = EOpConvFloatToInt16; break; 616 case EbtDouble: newOp = EOpConvDoubleToInt16; break; 617 case EbtFloat16: newOp = EOpConvFloat16ToInt16; break; 618 default: 619 return nullptr; 620 } 621 break; 622 case EbtUint16: 623 switch (node->getBasicType()) { 624 case EbtInt8: newOp = EOpConvInt8ToUint16; break; 625 case EbtUint8: newOp = EOpConvUint8ToUint16; break; 626 case EbtInt16: newOp = EOpConvInt16ToUint16; break; 627 case EbtInt: newOp = EOpConvIntToUint16; break; 628 case EbtUint: newOp = EOpConvUintToUint16; break; 629 case EbtInt64: newOp = EOpConvInt64ToUint16; break; 630 case EbtUint64: newOp = EOpConvUint64ToUint16; break; 631 case EbtBool: newOp = EOpConvBoolToUint16; break; 632 case EbtFloat: newOp = EOpConvFloatToUint16; break; 633 case EbtDouble: newOp = EOpConvDoubleToUint16; break; 634 case EbtFloat16: newOp = EOpConvFloat16ToUint16; break; 635 default: 636 return nullptr; 637 } 638 break; 639 640 case EbtInt: 641 switch (node->getBasicType()) { 642 case EbtInt8: newOp = EOpConvInt8ToInt; break; 643 case EbtUint8: newOp = EOpConvUint8ToInt; break; 644 case EbtInt16: newOp = EOpConvInt16ToInt; break; 645 case EbtUint16: newOp = EOpConvUint16ToInt; break; 646 case EbtUint: newOp = EOpConvUintToInt; break; 647 case EbtBool: newOp = EOpConvBoolToInt; break; 648 case EbtFloat: newOp = EOpConvFloatToInt; break; 649 case EbtDouble: newOp = EOpConvDoubleToInt; break; 650 case EbtFloat16: newOp = EOpConvFloat16ToInt; break; 651 case EbtInt64: newOp = EOpConvInt64ToInt; break; 652 case EbtUint64: newOp = EOpConvUint64ToInt; break; 653 default: 654 return nullptr; 655 } 656 break; 657 case EbtUint: 658 switch (node->getBasicType()) { 659 case EbtInt8: newOp = EOpConvInt8ToUint; break; 660 case EbtUint8: newOp = EOpConvUint8ToUint; break; 661 case EbtInt16: newOp = EOpConvInt16ToUint; break; 662 case EbtUint16: newOp = EOpConvUint16ToUint; break; 663 case EbtInt: newOp = EOpConvIntToUint; break; 664 case EbtBool: newOp = EOpConvBoolToUint; break; 665 case EbtFloat: newOp = EOpConvFloatToUint; break; 666 case EbtDouble: newOp = EOpConvDoubleToUint; break; 667 case EbtFloat16: newOp = EOpConvFloat16ToUint; break; 668 case EbtInt64: newOp = EOpConvInt64ToUint; break; 669 case EbtUint64: newOp = EOpConvUint64ToUint; break; 670 default: 671 return nullptr; 672 } 673 break; 674 case EbtInt64: 675 switch (node->getBasicType()) { 676 case EbtInt8: newOp = EOpConvInt8ToInt64; break; 677 case EbtUint8: newOp = EOpConvUint8ToInt64; break; 678 case EbtInt16: newOp = EOpConvInt16ToInt64; break; 679 case EbtUint16: newOp = EOpConvUint16ToInt64; break; 680 case EbtInt: newOp = EOpConvIntToInt64; break; 681 case EbtUint: newOp = EOpConvUintToInt64; break; 682 case EbtBool: newOp = EOpConvBoolToInt64; break; 683 case EbtFloat: newOp = EOpConvFloatToInt64; break; 684 case EbtDouble: newOp = EOpConvDoubleToInt64; break; 685 case EbtFloat16: newOp = EOpConvFloat16ToInt64; break; 686 case EbtUint64: newOp = EOpConvUint64ToInt64; break; 687 default: 688 return nullptr; 689 } 690 break; 691 case EbtUint64: 692 switch (node->getBasicType()) { 693 case EbtInt8: newOp = EOpConvInt8ToUint64; break; 694 case EbtUint8: newOp = EOpConvUint8ToUint64; break; 695 case EbtInt16: newOp = EOpConvInt16ToUint64; break; 696 case EbtUint16: newOp = EOpConvUint16ToUint64; break; 697 case EbtInt: newOp = EOpConvIntToUint64; break; 698 case EbtUint: newOp = EOpConvUintToUint64; break; 699 case EbtBool: newOp = EOpConvBoolToUint64; break; 700 case EbtFloat: newOp = EOpConvFloatToUint64; break; 701 case EbtDouble: newOp = EOpConvDoubleToUint64; break; 702 case EbtFloat16: newOp = EOpConvFloat16ToUint64; break; 703 case EbtInt64: newOp = EOpConvInt64ToUint64; break; 704 default: 705 return nullptr; 706 } 707 break; 708 default: 709 return nullptr; 710 } 711 712 TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows()); 713 newNode = addUnaryNode(newOp, node, node->getLoc(), newType); 714 715 if (node->getAsConstantUnion()) { 716 TIntermTyped* folded = node->getAsConstantUnion()->fold(newOp, newType); 717 if (folded) 718 return folded; 719 } 720 721 // Propagate specialization-constant-ness, if allowed 722 if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode)) 723 newNode->getWritableType().getQualifier().makeSpecConstant(); 724 725 return newNode; 726 } 727 728 // For converting a pair of operands to a binary operation to compatible 729 // types with each other, relative to the operation in 'op'. 730 // This does not cover assignment operations, which is asymmetric in that the 731 // left type is not changeable. 732 // See addConversion(op, type, node) for assignments and unary operation 733 // conversions. 734 // 735 // Generally, this is focused on basic type conversion, not shape conversion. 736 // See addShapeConversion() for shape conversions. 737 // 738 // Returns the converted pair of nodes. 739 // Returns <nullptr, nullptr> when there is no conversion. 740 std::tuple<TIntermTyped*, TIntermTyped*> 741 TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const 742 { 743 if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1)) 744 return std::make_tuple(nullptr, nullptr); 745 746 if (node0->getType() != node1->getType()) { 747 // If differing structure, then no conversions. 748 if (node0->isStruct() || node1->isStruct()) 749 return std::make_tuple(nullptr, nullptr); 750 751 // If differing arrays, then no conversions. 752 if (node0->getType().isArray() || node1->getType().isArray()) 753 return std::make_tuple(nullptr, nullptr); 754 } 755 756 auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes); 757 758 switch (op) { 759 // 760 // List all the binary ops that can implicitly convert one operand to the other's type; 761 // This implements the 'policy' for implicit type conversion. 762 // 763 case EOpLessThan: 764 case EOpGreaterThan: 765 case EOpLessThanEqual: 766 case EOpGreaterThanEqual: 767 case EOpEqual: 768 case EOpNotEqual: 769 770 case EOpAdd: 771 case EOpSub: 772 case EOpMul: 773 case EOpDiv: 774 case EOpMod: 775 776 case EOpVectorTimesScalar: 777 case EOpVectorTimesMatrix: 778 case EOpMatrixTimesVector: 779 case EOpMatrixTimesScalar: 780 781 case EOpAnd: 782 case EOpInclusiveOr: 783 case EOpExclusiveOr: 784 785 case EOpSequence: // used by ?: 786 787 if (node0->getBasicType() == node1->getBasicType()) 788 return std::make_tuple(node0, node1); 789 790 promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op); 791 if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes) 792 return std::make_tuple(nullptr, nullptr); 793 794 break; 795 796 case EOpLogicalAnd: 797 case EOpLogicalOr: 798 case EOpLogicalXor: 799 if (source == EShSourceHlsl) 800 promoteTo = std::make_tuple(EbtBool, EbtBool); 801 else 802 return std::make_tuple(node0, node1); 803 break; 804 805 // There are no conversions needed for GLSL; the shift amount just needs to be an 806 // integer type, as does the base. 807 // HLSL can promote bools to ints to make this work. 808 case EOpLeftShift: 809 case EOpRightShift: 810 if (source == EShSourceHlsl) { 811 TBasicType node0BasicType = node0->getBasicType(); 812 if (node0BasicType == EbtBool) 813 node0BasicType = EbtInt; 814 if (node1->getBasicType() == EbtBool) 815 promoteTo = std::make_tuple(node0BasicType, EbtInt); 816 else 817 promoteTo = std::make_tuple(node0BasicType, node1->getBasicType()); 818 } else { 819 if (isTypeInt(node0->getBasicType()) && isTypeInt(node1->getBasicType())) 820 return std::make_tuple(node0, node1); 821 else 822 return std::make_tuple(nullptr, nullptr); 823 } 824 break; 825 826 default: 827 if (node0->getType() == node1->getType()) 828 return std::make_tuple(node0, node1); 829 830 return std::make_tuple(nullptr, nullptr); 831 } 832 833 TIntermTyped* newNode0; 834 TIntermTyped* newNode1; 835 836 if (std::get<0>(promoteTo) != node0->getType().getBasicType()) { 837 if (node0->getAsConstantUnion()) 838 newNode0 = promoteConstantUnion(std::get<0>(promoteTo), node0->getAsConstantUnion()); 839 else 840 newNode0 = createConversion(std::get<0>(promoteTo), node0); 841 } else 842 newNode0 = node0; 843 844 if (std::get<1>(promoteTo) != node1->getType().getBasicType()) { 845 if (node1->getAsConstantUnion()) 846 newNode1 = promoteConstantUnion(std::get<1>(promoteTo), node1->getAsConstantUnion()); 847 else 848 newNode1 = createConversion(std::get<1>(promoteTo), node1); 849 } else 850 newNode1 = node1; 851 852 return std::make_tuple(newNode0, newNode1); 853 } 854 855 // 856 // Convert the node's type to the given type, as allowed by the operation involved: 'op'. 857 // For implicit conversions, 'op' is not the requested conversion, it is the explicit 858 // operation requiring the implicit conversion. 859 // 860 // Binary operation conversions should be handled by addConversion(op, node, node), not here. 861 // 862 // Returns a node representing the conversion, which could be the same 863 // node passed in if no conversion was needed. 864 // 865 // Generally, this is focused on basic type conversion, not shape conversion. 866 // See addShapeConversion() for shape conversions. 867 // 868 // Return nullptr if a conversion can't be done. 869 // 870 TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) const 871 { 872 if (!isConversionAllowed(op, node)) 873 return nullptr; 874 875 // Otherwise, if types are identical, no problem 876 if (type == node->getType()) 877 return node; 878 879 // If one's a structure, then no conversions. 880 if (type.isStruct() || node->isStruct()) 881 return nullptr; 882 883 // If one's an array, then no conversions. 884 if (type.isArray() || node->getType().isArray()) 885 return nullptr; 886 887 // Note: callers are responsible for other aspects of shape, 888 // like vector and matrix sizes. 889 890 TBasicType promoteTo; 891 // GL_EXT_shader_16bit_storage can't do OpConstantComposite with 892 // 16-bit types, so disable promotion for those types. 893 bool canPromoteConstant = true; 894 895 switch (op) { 896 // 897 // Explicit conversions (unary operations) 898 // 899 case EOpConstructBool: 900 promoteTo = EbtBool; 901 break; 902 case EOpConstructFloat: 903 promoteTo = EbtFloat; 904 break; 905 case EOpConstructDouble: 906 promoteTo = EbtDouble; 907 break; 908 case EOpConstructFloat16: 909 promoteTo = EbtFloat16; 910 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || 911 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); 912 break; 913 case EOpConstructInt8: 914 promoteTo = EbtInt8; 915 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || 916 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); 917 break; 918 case EOpConstructUint8: 919 promoteTo = EbtUint8; 920 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || 921 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); 922 break; 923 case EOpConstructInt16: 924 promoteTo = EbtInt16; 925 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || 926 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); 927 break; 928 case EOpConstructUint16: 929 promoteTo = EbtUint16; 930 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || 931 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); 932 break; 933 case EOpConstructInt: 934 promoteTo = EbtInt; 935 break; 936 case EOpConstructUint: 937 promoteTo = EbtUint; 938 break; 939 case EOpConstructInt64: 940 promoteTo = EbtInt64; 941 break; 942 case EOpConstructUint64: 943 promoteTo = EbtUint64; 944 break; 945 946 case EOpLogicalNot: 947 948 case EOpFunctionCall: 949 950 case EOpReturn: 951 case EOpAssign: 952 case EOpAddAssign: 953 case EOpSubAssign: 954 case EOpMulAssign: 955 case EOpVectorTimesScalarAssign: 956 case EOpMatrixTimesScalarAssign: 957 case EOpDivAssign: 958 case EOpModAssign: 959 case EOpAndAssign: 960 case EOpInclusiveOrAssign: 961 case EOpExclusiveOrAssign: 962 963 case EOpAtan: 964 case EOpClamp: 965 case EOpCross: 966 case EOpDistance: 967 case EOpDot: 968 case EOpDst: 969 case EOpFaceForward: 970 case EOpFma: 971 case EOpFrexp: 972 case EOpLdexp: 973 case EOpMix: 974 case EOpLit: 975 case EOpMax: 976 case EOpMin: 977 case EOpModf: 978 case EOpPow: 979 case EOpReflect: 980 case EOpRefract: 981 case EOpSmoothStep: 982 case EOpStep: 983 984 case EOpSequence: 985 case EOpConstructStruct: 986 987 if (type.getBasicType() == EbtReference || node->getType().getBasicType() == EbtReference) { 988 // types must match to assign a reference 989 if (type == node->getType()) 990 return node; 991 else 992 return nullptr; 993 } 994 995 if (type.getBasicType() == node->getType().getBasicType()) 996 return node; 997 998 if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op)) 999 promoteTo = type.getBasicType(); 1000 else 1001 return nullptr; 1002 break; 1003 1004 // For GLSL, there are no conversions needed; the shift amount just needs to be an 1005 // integer type, as do the base/result. 1006 // HLSL can convert the shift from a bool to an int. 1007 case EOpLeftShiftAssign: 1008 case EOpRightShiftAssign: 1009 { 1010 if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool) 1011 promoteTo = type.getBasicType(); 1012 else { 1013 if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType())) 1014 return node; 1015 else 1016 return nullptr; 1017 } 1018 break; 1019 } 1020 1021 default: 1022 // default is to require a match; all exceptions should have case statements above 1023 1024 if (type.getBasicType() == node->getType().getBasicType()) 1025 return node; 1026 else 1027 return nullptr; 1028 } 1029 1030 if (canPromoteConstant && node->getAsConstantUnion()) 1031 return promoteConstantUnion(promoteTo, node->getAsConstantUnion()); 1032 1033 // 1034 // Add a new newNode for the conversion. 1035 // 1036 TIntermTyped* newNode = createConversion(promoteTo, node); 1037 1038 return newNode; 1039 } 1040 1041 // Convert the node's shape of type for the given type, as allowed by the 1042 // operation involved: 'op'. This is for situations where there is only one 1043 // direction to consider doing the shape conversion. 1044 // 1045 // This implements policy, it call addShapeConversion() for the mechanism. 1046 // 1047 // Generally, the AST represents allowed GLSL shapes, so this isn't needed 1048 // for GLSL. Bad shapes are caught in conversion or promotion. 1049 // 1050 // Return 'node' if no conversion was done. Promotion handles final shape 1051 // checking. 1052 // 1053 TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node) 1054 { 1055 // some source languages don't do this 1056 switch (source) { 1057 case EShSourceHlsl: 1058 break; 1059 case EShSourceGlsl: 1060 default: 1061 return node; 1062 } 1063 1064 // some operations don't do this 1065 switch (op) { 1066 case EOpFunctionCall: 1067 case EOpReturn: 1068 break; 1069 1070 case EOpMulAssign: 1071 // want to support vector *= scalar native ops in AST and lower, not smear, similarly for 1072 // matrix *= scalar, etc. 1073 1074 case EOpAddAssign: 1075 case EOpSubAssign: 1076 case EOpDivAssign: 1077 case EOpAndAssign: 1078 case EOpInclusiveOrAssign: 1079 case EOpExclusiveOrAssign: 1080 case EOpRightShiftAssign: 1081 case EOpLeftShiftAssign: 1082 if (node->getVectorSize() == 1) 1083 return node; 1084 break; 1085 1086 case EOpAssign: 1087 break; 1088 1089 case EOpMix: 1090 break; 1091 1092 default: 1093 return node; 1094 } 1095 1096 return addShapeConversion(type, node); 1097 } 1098 1099 // Convert the nodes' shapes to be compatible for the operation 'op'. 1100 // 1101 // This implements policy, it call addShapeConversion() for the mechanism. 1102 // 1103 // Generally, the AST represents allowed GLSL shapes, so this isn't needed 1104 // for GLSL. Bad shapes are caught in conversion or promotion. 1105 // 1106 void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode) 1107 { 1108 // some source languages don't do this 1109 switch (source) { 1110 case EShSourceHlsl: 1111 break; 1112 case EShSourceGlsl: 1113 default: 1114 return; 1115 } 1116 1117 // some operations don't do this 1118 // 'break' will mean attempt bidirectional conversion 1119 switch (op) { 1120 case EOpMulAssign: 1121 case EOpAssign: 1122 case EOpAddAssign: 1123 case EOpSubAssign: 1124 case EOpDivAssign: 1125 case EOpAndAssign: 1126 case EOpInclusiveOrAssign: 1127 case EOpExclusiveOrAssign: 1128 case EOpRightShiftAssign: 1129 case EOpLeftShiftAssign: 1130 // switch to unidirectional conversion (the lhs can't change) 1131 rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode); 1132 return; 1133 1134 case EOpMul: 1135 // matrix multiply does not change shapes 1136 if (lhsNode->isMatrix() && rhsNode->isMatrix()) 1137 return; 1138 case EOpAdd: 1139 case EOpSub: 1140 case EOpDiv: 1141 // want to support vector * scalar native ops in AST and lower, not smear, similarly for 1142 // matrix * vector, etc. 1143 if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1) 1144 return; 1145 break; 1146 1147 case EOpRightShift: 1148 case EOpLeftShift: 1149 // can natively support the right operand being a scalar and the left a vector, 1150 // but not the reverse 1151 if (rhsNode->getVectorSize() == 1) 1152 return; 1153 break; 1154 1155 case EOpLessThan: 1156 case EOpGreaterThan: 1157 case EOpLessThanEqual: 1158 case EOpGreaterThanEqual: 1159 1160 case EOpEqual: 1161 case EOpNotEqual: 1162 1163 case EOpLogicalAnd: 1164 case EOpLogicalOr: 1165 case EOpLogicalXor: 1166 1167 case EOpAnd: 1168 case EOpInclusiveOr: 1169 case EOpExclusiveOr: 1170 1171 case EOpMix: 1172 break; 1173 1174 default: 1175 return; 1176 } 1177 1178 // Do bidirectional conversions 1179 if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) { 1180 if (lhsNode->getType().isScalarOrVec1()) 1181 lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); 1182 else 1183 rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); 1184 } 1185 lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); 1186 rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); 1187 } 1188 1189 // Convert the node's shape of type for the given type, as allowed by the 1190 // operation involved: 'op'. 1191 // 1192 // Generally, the AST represents allowed GLSL shapes, so this isn't needed 1193 // for GLSL. Bad shapes are caught in conversion or promotion. 1194 // 1195 // Return 'node' if no conversion was done. Promotion handles final shape 1196 // checking. 1197 // 1198 TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node) 1199 { 1200 // no conversion needed 1201 if (node->getType() == type) 1202 return node; 1203 1204 // structures and arrays don't change shape, either to or from 1205 if (node->getType().isStruct() || node->getType().isArray() || 1206 type.isStruct() || type.isArray()) 1207 return node; 1208 1209 // The new node that handles the conversion 1210 TOperator constructorOp = mapTypeToConstructorOp(type); 1211 1212 if (source == EShSourceHlsl) { 1213 // HLSL rules for scalar, vector and matrix conversions: 1214 // 1) scalar can become anything, initializing every component with its value 1215 // 2) vector and matrix can become scalar, first element is used (warning: truncation) 1216 // 3) matrix can become matrix with less rows and/or columns (warning: truncation) 1217 // 4) vector can become vector with less rows size (warning: truncation) 1218 // 5a) vector 4 can become 2x2 matrix (special case) (same packing layout, its a reinterpret) 1219 // 5b) 2x2 matrix can become vector 4 (special case) (same packing layout, its a reinterpret) 1220 1221 const TType &sourceType = node->getType(); 1222 1223 // rule 1 for scalar to matrix is special 1224 if (sourceType.isScalarOrVec1() && type.isMatrix()) { 1225 1226 // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its 1227 // own devices, the constructor from a scalar would populate the diagonal. This forces replication 1228 // to every matrix element. 1229 1230 // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here 1231 // repeatedly, so we copy it to a temp, then use the temp. 1232 const int matSize = type.computeNumComponents(); 1233 TIntermAggregate* rhsAggregate = new TIntermAggregate(); 1234 1235 const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr); 1236 1237 if (!isSimple) { 1238 assert(0); // TODO: use node replicator service when available. 1239 } 1240 1241 for (int x = 0; x < matSize; ++x) 1242 rhsAggregate->getSequence().push_back(node); 1243 1244 return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc()); 1245 } 1246 1247 // rule 1 and 2 1248 if ((sourceType.isScalar() && !type.isScalar()) || (!sourceType.isScalar() && type.isScalar())) 1249 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); 1250 1251 // rule 3 and 5b 1252 if (sourceType.isMatrix()) { 1253 // rule 3 1254 if (type.isMatrix()) { 1255 if ((sourceType.getMatrixCols() != type.getMatrixCols() || sourceType.getMatrixRows() != type.getMatrixRows()) && 1256 sourceType.getMatrixCols() >= type.getMatrixCols() && sourceType.getMatrixRows() >= type.getMatrixRows()) 1257 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); 1258 // rule 5b 1259 } else if (type.isVector()) { 1260 if (type.getVectorSize() == 4 && sourceType.getMatrixCols() == 2 && sourceType.getMatrixRows() == 2) 1261 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); 1262 } 1263 } 1264 1265 // rule 4 and 5a 1266 if (sourceType.isVector()) { 1267 // rule 4 1268 if (type.isVector()) 1269 { 1270 if (sourceType.getVectorSize() > type.getVectorSize()) 1271 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); 1272 // rule 5a 1273 } else if (type.isMatrix()) { 1274 if (sourceType.getVectorSize() == 4 && type.getMatrixCols() == 2 && type.getMatrixRows() == 2) 1275 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); 1276 } 1277 } 1278 } 1279 1280 // scalar -> vector or vec1 -> vector or 1281 // vector -> scalar or 1282 // bigger vector -> smaller vector 1283 if ((node->getType().isScalarOrVec1() && type.isVector()) || 1284 (node->getType().isVector() && type.isScalar()) || 1285 (node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize())) 1286 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); 1287 1288 return node; 1289 } 1290 1291 bool TIntermediate::isIntegralPromotion(TBasicType from, TBasicType to) const 1292 { 1293 // integral promotions 1294 if (to == EbtInt) { 1295 switch(from) { 1296 case EbtInt8: 1297 case EbtInt16: 1298 case EbtUint8: 1299 case EbtUint16: 1300 return true; 1301 default: 1302 break; 1303 } 1304 } 1305 return false; 1306 } 1307 1308 bool TIntermediate::isFPPromotion(TBasicType from, TBasicType to) const 1309 { 1310 // floating-point promotions 1311 if (to == EbtDouble) { 1312 switch(from) { 1313 case EbtFloat16: 1314 case EbtFloat: 1315 return true; 1316 default: 1317 break; 1318 } 1319 } 1320 return false; 1321 } 1322 1323 bool TIntermediate::isIntegralConversion(TBasicType from, TBasicType to) const 1324 { 1325 switch (from) { 1326 case EbtInt8: 1327 switch (to) { 1328 case EbtUint8: 1329 case EbtInt16: 1330 case EbtUint16: 1331 case EbtUint: 1332 case EbtInt64: 1333 case EbtUint64: 1334 return true; 1335 default: 1336 break; 1337 } 1338 break; 1339 case EbtUint8: 1340 switch (to) { 1341 case EbtInt16: 1342 case EbtUint16: 1343 case EbtUint: 1344 case EbtInt64: 1345 case EbtUint64: 1346 return true; 1347 default: 1348 break; 1349 } 1350 break; 1351 case EbtInt16: 1352 switch(to) { 1353 case EbtUint16: 1354 case EbtUint: 1355 case EbtInt64: 1356 case EbtUint64: 1357 return true; 1358 default: 1359 break; 1360 } 1361 break; 1362 case EbtUint16: 1363 switch(to) { 1364 case EbtUint: 1365 case EbtInt64: 1366 case EbtUint64: 1367 return true; 1368 default: 1369 break; 1370 } 1371 break; 1372 case EbtInt: 1373 switch(to) { 1374 case EbtUint: 1375 return version >= 400 || (source == EShSourceHlsl); 1376 case EbtInt64: 1377 case EbtUint64: 1378 return true; 1379 default: 1380 break; 1381 } 1382 break; 1383 case EbtUint: 1384 switch(to) { 1385 case EbtInt64: 1386 case EbtUint64: 1387 return true; 1388 default: 1389 break; 1390 } 1391 break; 1392 case EbtInt64: 1393 if (to == EbtUint64) { 1394 return true; 1395 } 1396 break; 1397 default: 1398 break; 1399 } 1400 return false; 1401 } 1402 1403 bool TIntermediate::isFPConversion(TBasicType from, TBasicType to) const 1404 { 1405 if (to == EbtFloat && from == EbtFloat16) { 1406 return true; 1407 } else { 1408 return false; 1409 } 1410 } 1411 1412 bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const 1413 { 1414 switch (from) { 1415 case EbtInt8: 1416 case EbtUint8: 1417 case EbtInt16: 1418 case EbtUint16: 1419 switch (to) { 1420 case EbtFloat16: 1421 case EbtFloat: 1422 case EbtDouble: 1423 return true; 1424 default: 1425 break; 1426 } 1427 break; 1428 case EbtInt: 1429 case EbtUint: 1430 switch(to) { 1431 case EbtFloat: 1432 case EbtDouble: 1433 return true; 1434 default: 1435 break; 1436 } 1437 break; 1438 case EbtInt64: 1439 case EbtUint64: 1440 if (to == EbtDouble) { 1441 return true; 1442 } 1443 break; 1444 1445 default: 1446 break; 1447 } 1448 return false; 1449 } 1450 1451 // 1452 // See if the 'from' type is allowed to be implicitly converted to the 1453 // 'to' type. This is not about vector/array/struct, only about basic type. 1454 // 1455 bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const 1456 { 1457 if (profile == EEsProfile || version == 110) 1458 return false; 1459 1460 if (from == to) 1461 return true; 1462 1463 // TODO: Move more policies into language-specific handlers. 1464 // Some languages allow more general (or potentially, more specific) conversions under some conditions. 1465 if (source == EShSourceHlsl) { 1466 const bool fromConvertable = (from == EbtFloat || from == EbtDouble || from == EbtInt || from == EbtUint || from == EbtBool); 1467 const bool toConvertable = (to == EbtFloat || to == EbtDouble || to == EbtInt || to == EbtUint || to == EbtBool); 1468 1469 if (fromConvertable && toConvertable) { 1470 switch (op) { 1471 case EOpAndAssign: // assignments can perform arbitrary conversions 1472 case EOpInclusiveOrAssign: // ... 1473 case EOpExclusiveOrAssign: // ... 1474 case EOpAssign: // ... 1475 case EOpAddAssign: // ... 1476 case EOpSubAssign: // ... 1477 case EOpMulAssign: // ... 1478 case EOpVectorTimesScalarAssign: // ... 1479 case EOpMatrixTimesScalarAssign: // ... 1480 case EOpDivAssign: // ... 1481 case EOpModAssign: // ... 1482 case EOpReturn: // function returns can also perform arbitrary conversions 1483 case EOpFunctionCall: // conversion of a calling parameter 1484 case EOpLogicalNot: 1485 case EOpLogicalAnd: 1486 case EOpLogicalOr: 1487 case EOpLogicalXor: 1488 case EOpConstructStruct: 1489 return true; 1490 default: 1491 break; 1492 } 1493 } 1494 } 1495 1496 bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || 1497 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) || 1498 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) || 1499 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) || 1500 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) || 1501 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) || 1502 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) || 1503 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64); 1504 1505 if (explicitTypesEnabled) { 1506 // integral promotions 1507 if (isIntegralPromotion(from, to)) { 1508 return true; 1509 } 1510 1511 // floating-point promotions 1512 if (isFPPromotion(from, to)) { 1513 return true; 1514 } 1515 1516 // integral conversions 1517 if (isIntegralConversion(from, to)) { 1518 return true; 1519 } 1520 1521 // floating-point conversions 1522 if (isFPConversion(from, to)) { 1523 return true; 1524 } 1525 1526 // floating-integral conversions 1527 if (isFPIntegralConversion(from, to)) { 1528 return true; 1529 } 1530 1531 // hlsl supported conversions 1532 if (source == EShSourceHlsl) { 1533 if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat)) 1534 return true; 1535 } 1536 } else { 1537 switch (to) { 1538 case EbtDouble: 1539 switch (from) { 1540 case EbtInt: 1541 case EbtUint: 1542 case EbtInt64: 1543 case EbtUint64: 1544 case EbtFloat: 1545 case EbtDouble: 1546 return true; 1547 #ifdef AMD_EXTENSIONS 1548 case EbtInt16: 1549 case EbtUint16: 1550 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1551 case EbtFloat16: 1552 return extensionRequested(E_GL_AMD_gpu_shader_half_float); 1553 #endif 1554 default: 1555 return false; 1556 } 1557 case EbtFloat: 1558 switch (from) { 1559 case EbtInt: 1560 case EbtUint: 1561 case EbtFloat: 1562 return true; 1563 case EbtBool: 1564 return (source == EShSourceHlsl); 1565 #ifdef AMD_EXTENSIONS 1566 case EbtInt16: 1567 case EbtUint16: 1568 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1569 #endif 1570 case EbtFloat16: 1571 return 1572 #ifdef AMD_EXTENSIONS 1573 extensionRequested(E_GL_AMD_gpu_shader_half_float) || 1574 #endif 1575 (source == EShSourceHlsl); 1576 default: 1577 return false; 1578 } 1579 case EbtUint: 1580 switch (from) { 1581 case EbtInt: 1582 return version >= 400 || (source == EShSourceHlsl); 1583 case EbtUint: 1584 return true; 1585 case EbtBool: 1586 return (source == EShSourceHlsl); 1587 #ifdef AMD_EXTENSIONS 1588 case EbtInt16: 1589 case EbtUint16: 1590 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1591 #endif 1592 default: 1593 return false; 1594 } 1595 case EbtInt: 1596 switch (from) { 1597 case EbtInt: 1598 return true; 1599 case EbtBool: 1600 return (source == EShSourceHlsl); 1601 #ifdef AMD_EXTENSIONS 1602 case EbtInt16: 1603 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1604 #endif 1605 default: 1606 return false; 1607 } 1608 case EbtUint64: 1609 switch (from) { 1610 case EbtInt: 1611 case EbtUint: 1612 case EbtInt64: 1613 case EbtUint64: 1614 return true; 1615 #ifdef AMD_EXTENSIONS 1616 case EbtInt16: 1617 case EbtUint16: 1618 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1619 #endif 1620 default: 1621 return false; 1622 } 1623 case EbtInt64: 1624 switch (from) { 1625 case EbtInt: 1626 case EbtInt64: 1627 return true; 1628 #ifdef AMD_EXTENSIONS 1629 case EbtInt16: 1630 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1631 #endif 1632 default: 1633 return false; 1634 } 1635 case EbtFloat16: 1636 #ifdef AMD_EXTENSIONS 1637 switch (from) { 1638 case EbtInt16: 1639 case EbtUint16: 1640 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1641 case EbtFloat16: 1642 return extensionRequested(E_GL_AMD_gpu_shader_half_float); 1643 default: 1644 break; 1645 } 1646 #endif 1647 return false; 1648 case EbtUint16: 1649 #ifdef AMD_EXTENSIONS 1650 switch (from) { 1651 case EbtInt16: 1652 case EbtUint16: 1653 return extensionRequested(E_GL_AMD_gpu_shader_int16); 1654 default: 1655 break; 1656 } 1657 #endif 1658 return false; 1659 default: 1660 return false; 1661 } 1662 } 1663 1664 return false; 1665 } 1666 1667 static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBasicType uintType) { 1668 switch(sintType) { 1669 case EbtInt8: 1670 switch(uintType) { 1671 case EbtUint8: 1672 case EbtUint16: 1673 case EbtUint: 1674 case EbtUint64: 1675 return false; 1676 default: 1677 assert(false); 1678 return false; 1679 } 1680 break; 1681 case EbtInt16: 1682 switch(uintType) { 1683 case EbtUint8: 1684 return true; 1685 case EbtUint16: 1686 case EbtUint: 1687 case EbtUint64: 1688 return false; 1689 default: 1690 assert(false); 1691 return false; 1692 } 1693 break; 1694 case EbtInt: 1695 switch(uintType) { 1696 case EbtUint8: 1697 case EbtUint16: 1698 return true; 1699 case EbtUint: 1700 return false; 1701 default: 1702 assert(false); 1703 return false; 1704 } 1705 break; 1706 case EbtInt64: 1707 switch(uintType) { 1708 case EbtUint8: 1709 case EbtUint16: 1710 case EbtUint: 1711 return true; 1712 case EbtUint64: 1713 return false; 1714 default: 1715 assert(false); 1716 return false; 1717 } 1718 break; 1719 default: 1720 assert(false); 1721 return false; 1722 } 1723 } 1724 1725 1726 static TBasicType getCorrespondingUnsignedType(TBasicType type) { 1727 switch(type) { 1728 case EbtInt8: 1729 return EbtUint8; 1730 case EbtInt16: 1731 return EbtUint16; 1732 case EbtInt: 1733 return EbtUint; 1734 case EbtInt64: 1735 return EbtUint64; 1736 default: 1737 assert(false); 1738 return EbtNumTypes; 1739 } 1740 } 1741 1742 // Implements the following rules 1743 // - If either operand has type float64_t or derived from float64_t, 1744 // the other shall be converted to float64_t or derived type. 1745 // - Otherwise, if either operand has type float32_t or derived from 1746 // float32_t, the other shall be converted to float32_t or derived type. 1747 // - Otherwise, if either operand has type float16_t or derived from 1748 // float16_t, the other shall be converted to float16_t or derived type. 1749 // - Otherwise, if both operands have integer types the following rules 1750 // shall be applied to the operands: 1751 // - If both operands have the same type, no further conversion 1752 // is needed. 1753 // - Otherwise, if both operands have signed integer types or both 1754 // have unsigned integer types, the operand with the type of lesser 1755 // integer conversion rank shall be converted to the type of the 1756 // operand with greater rank. 1757 // - Otherwise, if the operand that has unsigned integer type has rank 1758 // greater than or equal to the rank of the type of the other 1759 // operand, the operand with signed integer type shall be converted 1760 // to the type of the operand with unsigned integer type. 1761 // - Otherwise, if the type of the operand with signed integer type can 1762 // represent all of the values of the type of the operand with 1763 // unsigned integer type, the operand with unsigned integer type 1764 // shall be converted to the type of the operand with signed 1765 // integer type. 1766 // - Otherwise, both operands shall be converted to the unsigned 1767 // integer type corresponding to the type of the operand with signed 1768 // integer type. 1769 1770 std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const 1771 { 1772 TBasicType res0 = EbtNumTypes; 1773 TBasicType res1 = EbtNumTypes; 1774 1775 if (profile == EEsProfile || version == 110) 1776 return std::make_tuple(res0, res1);; 1777 1778 if (source == EShSourceHlsl) { 1779 if (canImplicitlyPromote(type1, type0, op)) { 1780 res0 = type0; 1781 res1 = type0; 1782 } else if (canImplicitlyPromote(type0, type1, op)) { 1783 res0 = type1; 1784 res1 = type1; 1785 } 1786 return std::make_tuple(res0, res1); 1787 } 1788 1789 if ((type0 == EbtDouble && canImplicitlyPromote(type1, EbtDouble, op)) || 1790 (type1 == EbtDouble && canImplicitlyPromote(type0, EbtDouble, op)) ) { 1791 res0 = EbtDouble; 1792 res1 = EbtDouble; 1793 } else if ((type0 == EbtFloat && canImplicitlyPromote(type1, EbtFloat, op)) || 1794 (type1 == EbtFloat && canImplicitlyPromote(type0, EbtFloat, op)) ) { 1795 res0 = EbtFloat; 1796 res1 = EbtFloat; 1797 } else if ((type0 == EbtFloat16 && canImplicitlyPromote(type1, EbtFloat16, op)) || 1798 (type1 == EbtFloat16 && canImplicitlyPromote(type0, EbtFloat16, op)) ) { 1799 res0 = EbtFloat16; 1800 res1 = EbtFloat16; 1801 } else if (isTypeInt(type0) && isTypeInt(type1) && 1802 (canImplicitlyPromote(type0, type1, op) || canImplicitlyPromote(type1, type0, op))) { 1803 if ((isTypeSignedInt(type0) && isTypeSignedInt(type1)) || 1804 (isTypeUnsignedInt(type0) && isTypeUnsignedInt(type1))) { 1805 if (getTypeRank(type0) < getTypeRank(type1)) { 1806 res0 = type1; 1807 res1 = type1; 1808 } else { 1809 res0 = type0; 1810 res1 = type0; 1811 } 1812 } else if (isTypeUnsignedInt(type0) && (getTypeRank(type0) > getTypeRank(type1))) { 1813 res0 = type0; 1814 res1 = type0; 1815 } else if (isTypeUnsignedInt(type1) && (getTypeRank(type1) > getTypeRank(type0))) { 1816 res0 = type1; 1817 res1 = type1; 1818 } else if (isTypeSignedInt(type0)) { 1819 if (canSignedIntTypeRepresentAllUnsignedValues(type0, type1)) { 1820 res0 = type0; 1821 res1 = type0; 1822 } else { 1823 res0 = getCorrespondingUnsignedType(type0); 1824 res1 = getCorrespondingUnsignedType(type0); 1825 } 1826 } else if (isTypeSignedInt(type1)) { 1827 if (canSignedIntTypeRepresentAllUnsignedValues(type1, type0)) { 1828 res0 = type1; 1829 res1 = type1; 1830 } else { 1831 res0 = getCorrespondingUnsignedType(type1); 1832 res1 = getCorrespondingUnsignedType(type1); 1833 } 1834 } 1835 } 1836 1837 return std::make_tuple(res0, res1); 1838 } 1839 1840 // 1841 // Given a type, find what operation would fully construct it. 1842 // 1843 TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const 1844 { 1845 TOperator op = EOpNull; 1846 1847 if (type.getQualifier().nonUniform) 1848 return EOpConstructNonuniform; 1849 1850 switch (type.getBasicType()) { 1851 case EbtStruct: 1852 op = EOpConstructStruct; 1853 break; 1854 case EbtSampler: 1855 if (type.getSampler().combined) 1856 op = EOpConstructTextureSampler; 1857 break; 1858 case EbtFloat: 1859 if (type.isMatrix()) { 1860 switch (type.getMatrixCols()) { 1861 case 2: 1862 switch (type.getMatrixRows()) { 1863 case 2: op = EOpConstructMat2x2; break; 1864 case 3: op = EOpConstructMat2x3; break; 1865 case 4: op = EOpConstructMat2x4; break; 1866 default: break; // some compilers want this 1867 } 1868 break; 1869 case 3: 1870 switch (type.getMatrixRows()) { 1871 case 2: op = EOpConstructMat3x2; break; 1872 case 3: op = EOpConstructMat3x3; break; 1873 case 4: op = EOpConstructMat3x4; break; 1874 default: break; // some compilers want this 1875 } 1876 break; 1877 case 4: 1878 switch (type.getMatrixRows()) { 1879 case 2: op = EOpConstructMat4x2; break; 1880 case 3: op = EOpConstructMat4x3; break; 1881 case 4: op = EOpConstructMat4x4; break; 1882 default: break; // some compilers want this 1883 } 1884 break; 1885 default: break; // some compilers want this 1886 } 1887 } else { 1888 switch(type.getVectorSize()) { 1889 case 1: op = EOpConstructFloat; break; 1890 case 2: op = EOpConstructVec2; break; 1891 case 3: op = EOpConstructVec3; break; 1892 case 4: op = EOpConstructVec4; break; 1893 default: break; // some compilers want this 1894 } 1895 } 1896 break; 1897 case EbtDouble: 1898 if (type.getMatrixCols()) { 1899 switch (type.getMatrixCols()) { 1900 case 2: 1901 switch (type.getMatrixRows()) { 1902 case 2: op = EOpConstructDMat2x2; break; 1903 case 3: op = EOpConstructDMat2x3; break; 1904 case 4: op = EOpConstructDMat2x4; break; 1905 default: break; // some compilers want this 1906 } 1907 break; 1908 case 3: 1909 switch (type.getMatrixRows()) { 1910 case 2: op = EOpConstructDMat3x2; break; 1911 case 3: op = EOpConstructDMat3x3; break; 1912 case 4: op = EOpConstructDMat3x4; break; 1913 default: break; // some compilers want this 1914 } 1915 break; 1916 case 4: 1917 switch (type.getMatrixRows()) { 1918 case 2: op = EOpConstructDMat4x2; break; 1919 case 3: op = EOpConstructDMat4x3; break; 1920 case 4: op = EOpConstructDMat4x4; break; 1921 default: break; // some compilers want this 1922 } 1923 break; 1924 } 1925 } else { 1926 switch(type.getVectorSize()) { 1927 case 1: op = EOpConstructDouble; break; 1928 case 2: op = EOpConstructDVec2; break; 1929 case 3: op = EOpConstructDVec3; break; 1930 case 4: op = EOpConstructDVec4; break; 1931 default: break; // some compilers want this 1932 } 1933 } 1934 break; 1935 case EbtFloat16: 1936 if (type.getMatrixCols()) { 1937 switch (type.getMatrixCols()) { 1938 case 2: 1939 switch (type.getMatrixRows()) { 1940 case 2: op = EOpConstructF16Mat2x2; break; 1941 case 3: op = EOpConstructF16Mat2x3; break; 1942 case 4: op = EOpConstructF16Mat2x4; break; 1943 default: break; // some compilers want this 1944 } 1945 break; 1946 case 3: 1947 switch (type.getMatrixRows()) { 1948 case 2: op = EOpConstructF16Mat3x2; break; 1949 case 3: op = EOpConstructF16Mat3x3; break; 1950 case 4: op = EOpConstructF16Mat3x4; break; 1951 default: break; // some compilers want this 1952 } 1953 break; 1954 case 4: 1955 switch (type.getMatrixRows()) { 1956 case 2: op = EOpConstructF16Mat4x2; break; 1957 case 3: op = EOpConstructF16Mat4x3; break; 1958 case 4: op = EOpConstructF16Mat4x4; break; 1959 default: break; // some compilers want this 1960 } 1961 break; 1962 } 1963 } 1964 else { 1965 switch (type.getVectorSize()) { 1966 case 1: op = EOpConstructFloat16; break; 1967 case 2: op = EOpConstructF16Vec2; break; 1968 case 3: op = EOpConstructF16Vec3; break; 1969 case 4: op = EOpConstructF16Vec4; break; 1970 default: break; // some compilers want this 1971 } 1972 } 1973 break; 1974 case EbtInt8: 1975 switch(type.getVectorSize()) { 1976 case 1: op = EOpConstructInt8; break; 1977 case 2: op = EOpConstructI8Vec2; break; 1978 case 3: op = EOpConstructI8Vec3; break; 1979 case 4: op = EOpConstructI8Vec4; break; 1980 default: break; // some compilers want this 1981 } 1982 break; 1983 case EbtUint8: 1984 switch(type.getVectorSize()) { 1985 case 1: op = EOpConstructUint8; break; 1986 case 2: op = EOpConstructU8Vec2; break; 1987 case 3: op = EOpConstructU8Vec3; break; 1988 case 4: op = EOpConstructU8Vec4; break; 1989 default: break; // some compilers want this 1990 } 1991 break; 1992 case EbtInt16: 1993 switch(type.getVectorSize()) { 1994 case 1: op = EOpConstructInt16; break; 1995 case 2: op = EOpConstructI16Vec2; break; 1996 case 3: op = EOpConstructI16Vec3; break; 1997 case 4: op = EOpConstructI16Vec4; break; 1998 default: break; // some compilers want this 1999 } 2000 break; 2001 case EbtUint16: 2002 switch(type.getVectorSize()) { 2003 case 1: op = EOpConstructUint16; break; 2004 case 2: op = EOpConstructU16Vec2; break; 2005 case 3: op = EOpConstructU16Vec3; break; 2006 case 4: op = EOpConstructU16Vec4; break; 2007 default: break; // some compilers want this 2008 } 2009 break; 2010 case EbtInt: 2011 if (type.getMatrixCols()) { 2012 switch (type.getMatrixCols()) { 2013 case 2: 2014 switch (type.getMatrixRows()) { 2015 case 2: op = EOpConstructIMat2x2; break; 2016 case 3: op = EOpConstructIMat2x3; break; 2017 case 4: op = EOpConstructIMat2x4; break; 2018 default: break; // some compilers want this 2019 } 2020 break; 2021 case 3: 2022 switch (type.getMatrixRows()) { 2023 case 2: op = EOpConstructIMat3x2; break; 2024 case 3: op = EOpConstructIMat3x3; break; 2025 case 4: op = EOpConstructIMat3x4; break; 2026 default: break; // some compilers want this 2027 } 2028 break; 2029 case 4: 2030 switch (type.getMatrixRows()) { 2031 case 2: op = EOpConstructIMat4x2; break; 2032 case 3: op = EOpConstructIMat4x3; break; 2033 case 4: op = EOpConstructIMat4x4; break; 2034 default: break; // some compilers want this 2035 } 2036 break; 2037 } 2038 } else { 2039 switch(type.getVectorSize()) { 2040 case 1: op = EOpConstructInt; break; 2041 case 2: op = EOpConstructIVec2; break; 2042 case 3: op = EOpConstructIVec3; break; 2043 case 4: op = EOpConstructIVec4; break; 2044 default: break; // some compilers want this 2045 } 2046 } 2047 break; 2048 case EbtUint: 2049 if (type.getMatrixCols()) { 2050 switch (type.getMatrixCols()) { 2051 case 2: 2052 switch (type.getMatrixRows()) { 2053 case 2: op = EOpConstructUMat2x2; break; 2054 case 3: op = EOpConstructUMat2x3; break; 2055 case 4: op = EOpConstructUMat2x4; break; 2056 default: break; // some compilers want this 2057 } 2058 break; 2059 case 3: 2060 switch (type.getMatrixRows()) { 2061 case 2: op = EOpConstructUMat3x2; break; 2062 case 3: op = EOpConstructUMat3x3; break; 2063 case 4: op = EOpConstructUMat3x4; break; 2064 default: break; // some compilers want this 2065 } 2066 break; 2067 case 4: 2068 switch (type.getMatrixRows()) { 2069 case 2: op = EOpConstructUMat4x2; break; 2070 case 3: op = EOpConstructUMat4x3; break; 2071 case 4: op = EOpConstructUMat4x4; break; 2072 default: break; // some compilers want this 2073 } 2074 break; 2075 } 2076 } else { 2077 switch(type.getVectorSize()) { 2078 case 1: op = EOpConstructUint; break; 2079 case 2: op = EOpConstructUVec2; break; 2080 case 3: op = EOpConstructUVec3; break; 2081 case 4: op = EOpConstructUVec4; break; 2082 default: break; // some compilers want this 2083 } 2084 } 2085 break; 2086 case EbtInt64: 2087 switch(type.getVectorSize()) { 2088 case 1: op = EOpConstructInt64; break; 2089 case 2: op = EOpConstructI64Vec2; break; 2090 case 3: op = EOpConstructI64Vec3; break; 2091 case 4: op = EOpConstructI64Vec4; break; 2092 default: break; // some compilers want this 2093 } 2094 break; 2095 case EbtUint64: 2096 switch(type.getVectorSize()) { 2097 case 1: op = EOpConstructUint64; break; 2098 case 2: op = EOpConstructU64Vec2; break; 2099 case 3: op = EOpConstructU64Vec3; break; 2100 case 4: op = EOpConstructU64Vec4; break; 2101 default: break; // some compilers want this 2102 } 2103 break; 2104 case EbtBool: 2105 if (type.getMatrixCols()) { 2106 switch (type.getMatrixCols()) { 2107 case 2: 2108 switch (type.getMatrixRows()) { 2109 case 2: op = EOpConstructBMat2x2; break; 2110 case 3: op = EOpConstructBMat2x3; break; 2111 case 4: op = EOpConstructBMat2x4; break; 2112 default: break; // some compilers want this 2113 } 2114 break; 2115 case 3: 2116 switch (type.getMatrixRows()) { 2117 case 2: op = EOpConstructBMat3x2; break; 2118 case 3: op = EOpConstructBMat3x3; break; 2119 case 4: op = EOpConstructBMat3x4; break; 2120 default: break; // some compilers want this 2121 } 2122 break; 2123 case 4: 2124 switch (type.getMatrixRows()) { 2125 case 2: op = EOpConstructBMat4x2; break; 2126 case 3: op = EOpConstructBMat4x3; break; 2127 case 4: op = EOpConstructBMat4x4; break; 2128 default: break; // some compilers want this 2129 } 2130 break; 2131 } 2132 } else { 2133 switch(type.getVectorSize()) { 2134 case 1: op = EOpConstructBool; break; 2135 case 2: op = EOpConstructBVec2; break; 2136 case 3: op = EOpConstructBVec3; break; 2137 case 4: op = EOpConstructBVec4; break; 2138 default: break; // some compilers want this 2139 } 2140 } 2141 break; 2142 case EbtReference: 2143 op = EOpConstructReference; 2144 break; 2145 default: 2146 break; 2147 } 2148 2149 return op; 2150 } 2151 2152 // 2153 // Safe way to combine two nodes into an aggregate. Works with null pointers, 2154 // a node that's not a aggregate yet, etc. 2155 // 2156 // Returns the resulting aggregate, unless nullptr was passed in for 2157 // both existing nodes. 2158 // 2159 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right) 2160 { 2161 if (left == nullptr && right == nullptr) 2162 return nullptr; 2163 2164 TIntermAggregate* aggNode = nullptr; 2165 if (left != nullptr) 2166 aggNode = left->getAsAggregate(); 2167 if (aggNode == nullptr || aggNode->getOp() != EOpNull) { 2168 aggNode = new TIntermAggregate; 2169 if (left != nullptr) 2170 aggNode->getSequence().push_back(left); 2171 } 2172 2173 if (right != nullptr) 2174 aggNode->getSequence().push_back(right); 2175 2176 return aggNode; 2177 } 2178 2179 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc) 2180 { 2181 TIntermAggregate* aggNode = growAggregate(left, right); 2182 if (aggNode) 2183 aggNode->setLoc(loc); 2184 2185 return aggNode; 2186 } 2187 2188 // 2189 // Turn an existing node into an aggregate. 2190 // 2191 // Returns an aggregate, unless nullptr was passed in for the existing node. 2192 // 2193 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node) 2194 { 2195 if (node == nullptr) 2196 return nullptr; 2197 2198 TIntermAggregate* aggNode = new TIntermAggregate; 2199 aggNode->getSequence().push_back(node); 2200 aggNode->setLoc(node->getLoc()); 2201 2202 return aggNode; 2203 } 2204 2205 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& loc) 2206 { 2207 if (node == nullptr) 2208 return nullptr; 2209 2210 TIntermAggregate* aggNode = new TIntermAggregate; 2211 aggNode->getSequence().push_back(node); 2212 aggNode->setLoc(loc); 2213 2214 return aggNode; 2215 } 2216 2217 // 2218 // Make an aggregate with an empty sequence. 2219 // 2220 TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc) 2221 { 2222 TIntermAggregate* aggNode = new TIntermAggregate; 2223 aggNode->setLoc(loc); 2224 2225 return aggNode; 2226 } 2227 2228 // 2229 // For "if" test nodes. There are three children; a condition, 2230 // a true path, and a false path. The two paths are in the 2231 // nodePair. 2232 // 2233 // Returns the selection node created. 2234 // 2235 TIntermSelection* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc) 2236 { 2237 // 2238 // Don't prune the false path for compile-time constants; it's needed 2239 // for static access analysis. 2240 // 2241 2242 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); 2243 node->setLoc(loc); 2244 2245 return node; 2246 } 2247 2248 TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc) 2249 { 2250 // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators 2251 // ... are not included in the operators that can create a constant expression. 2252 // 2253 // if (left->getType().getQualifier().storage == EvqConst && 2254 // right->getType().getQualifier().storage == EvqConst) { 2255 2256 // return right; 2257 //} 2258 2259 TIntermTyped *commaAggregate = growAggregate(left, right, loc); 2260 commaAggregate->getAsAggregate()->setOperator(EOpComma); 2261 commaAggregate->setType(right->getType()); 2262 commaAggregate->getWritableType().getQualifier().makeTemporary(); 2263 2264 return commaAggregate; 2265 } 2266 2267 TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type, const TString* name, const TSourceLoc& loc) 2268 { 2269 TIntermMethod* method = new TIntermMethod(object, type, *name); 2270 method->setLoc(loc); 2271 2272 return method; 2273 } 2274 2275 // 2276 // For "?:" test nodes. There are three children; a condition, 2277 // a true path, and a false path. The two paths are specified 2278 // as separate parameters. For vector 'cond', the true and false 2279 // are not paths, but vectors to mix. 2280 // 2281 // Specialization constant operations include 2282 // - The ternary operator ( ? : ) 2283 // 2284 // Returns the selection node created, or nullptr if one could not be. 2285 // 2286 TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, 2287 const TSourceLoc& loc) 2288 { 2289 // If it's void, go to the if-then-else selection() 2290 if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) { 2291 TIntermNodePair pair = { trueBlock, falseBlock }; 2292 TIntermSelection* selection = addSelection(cond, pair, loc); 2293 if (getSource() == EShSourceHlsl) 2294 selection->setNoShortCircuit(); 2295 2296 return selection; 2297 } 2298 2299 // 2300 // Get compatible types. 2301 // 2302 auto children = addConversion(EOpSequence, trueBlock, falseBlock); 2303 trueBlock = std::get<0>(children); 2304 falseBlock = std::get<1>(children); 2305 2306 if (trueBlock == nullptr || falseBlock == nullptr) 2307 return nullptr; 2308 2309 // Handle a vector condition as a mix 2310 if (!cond->getType().isScalarOrVec1()) { 2311 TType targetVectorType(trueBlock->getType().getBasicType(), EvqTemporary, 2312 cond->getType().getVectorSize()); 2313 // smear true/false operands as needed 2314 trueBlock = addUniShapeConversion(EOpMix, targetVectorType, trueBlock); 2315 falseBlock = addUniShapeConversion(EOpMix, targetVectorType, falseBlock); 2316 2317 // After conversion, types have to match. 2318 if (falseBlock->getType() != trueBlock->getType()) 2319 return nullptr; 2320 2321 // make the mix operation 2322 TIntermAggregate* mix = makeAggregate(loc); 2323 mix = growAggregate(mix, falseBlock); 2324 mix = growAggregate(mix, trueBlock); 2325 mix = growAggregate(mix, cond); 2326 mix->setType(targetVectorType); 2327 mix->setOp(EOpMix); 2328 2329 return mix; 2330 } 2331 2332 // Now have a scalar condition... 2333 2334 // Convert true and false expressions to matching types 2335 addBiShapeConversion(EOpMix, trueBlock, falseBlock); 2336 2337 // After conversion, types have to match. 2338 if (falseBlock->getType() != trueBlock->getType()) 2339 return nullptr; 2340 2341 // Eliminate the selection when the condition is a scalar and all operands are constant. 2342 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { 2343 if (cond->getAsConstantUnion()->getConstArray()[0].getBConst()) 2344 return trueBlock; 2345 else 2346 return falseBlock; 2347 } 2348 2349 // 2350 // Make a selection node. 2351 // 2352 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); 2353 node->setLoc(loc); 2354 node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision); 2355 2356 if ((cond->getQualifier().isConstant() && specConstantPropagates(*trueBlock, *falseBlock)) || 2357 (cond->getQualifier().isSpecConstant() && trueBlock->getQualifier().isConstant() && 2358 falseBlock->getQualifier().isConstant())) 2359 node->getQualifier().makeSpecConstant(); 2360 else 2361 node->getQualifier().makeTemporary(); 2362 2363 if (getSource() == EShSourceHlsl) 2364 node->setNoShortCircuit(); 2365 2366 return node; 2367 } 2368 2369 // 2370 // Constant terminal nodes. Has a union that contains bool, float or int constants 2371 // 2372 // Returns the constant union node created. 2373 // 2374 2375 TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, const TSourceLoc& loc, bool literal) const 2376 { 2377 TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t); 2378 node->getQualifier().storage = EvqConst; 2379 node->setLoc(loc); 2380 if (literal) 2381 node->setLiteral(); 2382 2383 return node; 2384 } 2385 TIntermConstantUnion* TIntermediate::addConstantUnion(signed char i8, const TSourceLoc& loc, bool literal) const 2386 { 2387 TConstUnionArray unionArray(1); 2388 unionArray[0].setI8Const(i8); 2389 2390 return addConstantUnion(unionArray, TType(EbtInt8, EvqConst), loc, literal); 2391 } 2392 2393 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned char u8, const TSourceLoc& loc, bool literal) const 2394 { 2395 TConstUnionArray unionArray(1); 2396 unionArray[0].setUConst(u8); 2397 2398 return addConstantUnion(unionArray, TType(EbtUint8, EvqConst), loc, literal); 2399 } 2400 2401 TIntermConstantUnion* TIntermediate::addConstantUnion(signed short i16, const TSourceLoc& loc, bool literal) const 2402 { 2403 TConstUnionArray unionArray(1); 2404 unionArray[0].setI16Const(i16); 2405 2406 return addConstantUnion(unionArray, TType(EbtInt16, EvqConst), loc, literal); 2407 } 2408 2409 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned short u16, const TSourceLoc& loc, bool literal) const 2410 { 2411 TConstUnionArray unionArray(1); 2412 unionArray[0].setU16Const(u16); 2413 2414 return addConstantUnion(unionArray, TType(EbtUint16, EvqConst), loc, literal); 2415 } 2416 2417 TIntermConstantUnion* TIntermediate::addConstantUnion(int i, const TSourceLoc& loc, bool literal) const 2418 { 2419 TConstUnionArray unionArray(1); 2420 unionArray[0].setIConst(i); 2421 2422 return addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc, literal); 2423 } 2424 2425 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned int u, const TSourceLoc& loc, bool literal) const 2426 { 2427 TConstUnionArray unionArray(1); 2428 unionArray[0].setUConst(u); 2429 2430 return addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc, literal); 2431 } 2432 2433 TIntermConstantUnion* TIntermediate::addConstantUnion(long long i64, const TSourceLoc& loc, bool literal) const 2434 { 2435 TConstUnionArray unionArray(1); 2436 unionArray[0].setI64Const(i64); 2437 2438 return addConstantUnion(unionArray, TType(EbtInt64, EvqConst), loc, literal); 2439 } 2440 2441 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, const TSourceLoc& loc, bool literal) const 2442 { 2443 TConstUnionArray unionArray(1); 2444 unionArray[0].setU64Const(u64); 2445 2446 return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal); 2447 } 2448 2449 TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const 2450 { 2451 TConstUnionArray unionArray(1); 2452 unionArray[0].setBConst(b); 2453 2454 return addConstantUnion(unionArray, TType(EbtBool, EvqConst), loc, literal); 2455 } 2456 2457 TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseType, const TSourceLoc& loc, bool literal) const 2458 { 2459 assert(baseType == EbtFloat || baseType == EbtDouble || baseType == EbtFloat16); 2460 2461 TConstUnionArray unionArray(1); 2462 unionArray[0].setDConst(d); 2463 2464 return addConstantUnion(unionArray, TType(baseType, EvqConst), loc, literal); 2465 } 2466 2467 TIntermConstantUnion* TIntermediate::addConstantUnion(const TString* s, const TSourceLoc& loc, bool literal) const 2468 { 2469 TConstUnionArray unionArray(1); 2470 unionArray[0].setSConst(s); 2471 2472 return addConstantUnion(unionArray, TType(EbtString, EvqConst), loc, literal); 2473 } 2474 2475 // Put vector swizzle selectors onto the given sequence 2476 void TIntermediate::pushSelector(TIntermSequence& sequence, const TVectorSelector& selector, const TSourceLoc& loc) 2477 { 2478 TIntermConstantUnion* constIntNode = addConstantUnion(selector, loc); 2479 sequence.push_back(constIntNode); 2480 } 2481 2482 // Put matrix swizzle selectors onto the given sequence 2483 void TIntermediate::pushSelector(TIntermSequence& sequence, const TMatrixSelector& selector, const TSourceLoc& loc) 2484 { 2485 TIntermConstantUnion* constIntNode = addConstantUnion(selector.coord1, loc); 2486 sequence.push_back(constIntNode); 2487 constIntNode = addConstantUnion(selector.coord2, loc); 2488 sequence.push_back(constIntNode); 2489 } 2490 2491 // Make an aggregate node that has a sequence of all selectors. 2492 template TIntermTyped* TIntermediate::addSwizzle<TVectorSelector>(TSwizzleSelectors<TVectorSelector>& selector, const TSourceLoc& loc); 2493 template TIntermTyped* TIntermediate::addSwizzle<TMatrixSelector>(TSwizzleSelectors<TMatrixSelector>& selector, const TSourceLoc& loc); 2494 template<typename selectorType> 2495 TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors<selectorType>& selector, const TSourceLoc& loc) 2496 { 2497 TIntermAggregate* node = new TIntermAggregate(EOpSequence); 2498 2499 node->setLoc(loc); 2500 TIntermSequence &sequenceVector = node->getSequence(); 2501 2502 for (int i = 0; i < selector.size(); i++) 2503 pushSelector(sequenceVector, selector[i], loc); 2504 2505 return node; 2506 } 2507 2508 // 2509 // Follow the left branches down to the root of an l-value 2510 // expression (just "." and []). 2511 // 2512 // Return the base of the l-value (where following indexing quits working). 2513 // Return nullptr if a chain following dereferences cannot be followed. 2514 // 2515 // 'swizzleOkay' says whether or not it is okay to consider a swizzle 2516 // a valid part of the dereference chain. 2517 // 2518 const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay) 2519 { 2520 do { 2521 const TIntermBinary* binary = node->getAsBinaryNode(); 2522 if (binary == nullptr) 2523 return node; 2524 TOperator op = binary->getOp(); 2525 if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle && op != EOpMatrixSwizzle) 2526 return nullptr; 2527 if (! swizzleOkay) { 2528 if (op == EOpVectorSwizzle || op == EOpMatrixSwizzle) 2529 return nullptr; 2530 if ((op == EOpIndexDirect || op == EOpIndexIndirect) && 2531 (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) && 2532 ! binary->getLeft()->getType().isArray()) 2533 return nullptr; 2534 } 2535 node = node->getAsBinaryNode()->getLeft(); 2536 } while (true); 2537 } 2538 2539 // 2540 // Create while and do-while loop nodes. 2541 // 2542 TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, 2543 const TSourceLoc& loc) 2544 { 2545 TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst); 2546 node->setLoc(loc); 2547 2548 return node; 2549 } 2550 2551 // 2552 // Create a for-loop sequence. 2553 // 2554 TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, 2555 TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TIntermLoop*& node) 2556 { 2557 node = new TIntermLoop(body, test, terminal, testFirst); 2558 node->setLoc(loc); 2559 2560 // make a sequence of the initializer and statement, but try to reuse the 2561 // aggregate already created for whatever is in the initializer, if there is one 2562 TIntermAggregate* loopSequence = (initializer == nullptr || 2563 initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc) 2564 : initializer->getAsAggregate(); 2565 if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence) 2566 loopSequence->setOp(EOpNull); 2567 loopSequence = growAggregate(loopSequence, node); 2568 loopSequence->setOperator(EOpSequence); 2569 2570 return loopSequence; 2571 } 2572 2573 // 2574 // Add branches. 2575 // 2576 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& loc) 2577 { 2578 return addBranch(branchOp, nullptr, loc); 2579 } 2580 2581 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& loc) 2582 { 2583 TIntermBranch* node = new TIntermBranch(branchOp, expression); 2584 node->setLoc(loc); 2585 2586 return node; 2587 } 2588 2589 // 2590 // This is to be executed after the final root is put on top by the parsing 2591 // process. 2592 // 2593 bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/) 2594 { 2595 if (root == nullptr) 2596 return true; 2597 2598 // Finish off the top-level sequence 2599 TIntermAggregate* aggRoot = root->getAsAggregate(); 2600 if (aggRoot && aggRoot->getOp() == EOpNull) 2601 aggRoot->setOperator(EOpSequence); 2602 2603 // Propagate 'noContraction' label in backward from 'precise' variables. 2604 glslang::PropagateNoContraction(*this); 2605 2606 switch (textureSamplerTransformMode) { 2607 case EShTexSampTransKeep: 2608 break; 2609 case EShTexSampTransUpgradeTextureRemoveSampler: 2610 performTextureUpgradeAndSamplerRemovalTransformation(root); 2611 break; 2612 } 2613 2614 return true; 2615 } 2616 2617 void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable) 2618 { 2619 // Add top-level nodes for declarations that must be checked cross 2620 // compilation unit by a linker, yet might not have been referenced 2621 // by the AST. 2622 // 2623 // Almost entirely, translation of symbols is driven by what's present 2624 // in the AST traversal, not by translating the symbol table. 2625 // 2626 // However, there are some special cases: 2627 // - From the specification: "Special built-in inputs gl_VertexID and 2628 // gl_InstanceID are also considered active vertex attributes." 2629 // - Linker-based type mismatch error reporting needs to see all 2630 // uniforms/ins/outs variables and blocks. 2631 // - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active. 2632 // 2633 2634 // if (ftransformUsed) { 2635 // TODO: 1.1 lowering functionality: track ftransform() usage 2636 // addSymbolLinkageNode(root, symbolTable, "gl_Vertex"); 2637 // addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix"); 2638 //} 2639 2640 if (language == EShLangVertex) { 2641 // the names won't be found in the symbol table unless the versions are right, 2642 // so version logic does not need to be repeated here 2643 addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID"); 2644 addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID"); 2645 } 2646 2647 // Add a child to the root node for the linker objects 2648 linkage->setOperator(EOpLinkerObjects); 2649 treeRoot = growAggregate(treeRoot, linkage); 2650 } 2651 2652 // 2653 // Add the given name or symbol to the list of nodes at the end of the tree used 2654 // for link-time checking and external linkage. 2655 // 2656 2657 void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name) 2658 { 2659 TSymbol* symbol = symbolTable.find(name); 2660 if (symbol) 2661 addSymbolLinkageNode(linkage, *symbol->getAsVariable()); 2662 } 2663 2664 void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol& symbol) 2665 { 2666 const TVariable* variable = symbol.getAsVariable(); 2667 if (! variable) { 2668 // This must be a member of an anonymous block, and we need to add the whole block 2669 const TAnonMember* anon = symbol.getAsAnonMember(); 2670 variable = &anon->getAnonContainer(); 2671 } 2672 TIntermSymbol* node = addSymbol(*variable); 2673 linkage = growAggregate(linkage, node); 2674 } 2675 2676 // 2677 // Add a caller->callee relationship to the call graph. 2678 // Assumes the strings are unique per signature. 2679 // 2680 void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& caller, const TString& callee) 2681 { 2682 // Duplicates are okay, but faster to not keep them, and they come grouped by caller, 2683 // as long as new ones are push on the same end we check on for duplicates 2684 for (TGraph::const_iterator call = callGraph.begin(); call != callGraph.end(); ++call) { 2685 if (call->caller != caller) 2686 break; 2687 if (call->callee == callee) 2688 return; 2689 } 2690 2691 callGraph.push_front(TCall(caller, callee)); 2692 } 2693 2694 // 2695 // This deletes the tree. 2696 // 2697 void TIntermediate::removeTree() 2698 { 2699 if (treeRoot) 2700 RemoveAllTreeNodes(treeRoot); 2701 } 2702 2703 // 2704 // Implement the part of KHR_vulkan_glsl that lists the set of operations 2705 // that can result in a specialization constant operation. 2706 // 2707 // "5.x Specialization Constant Operations" 2708 // 2709 // Only some operations discussed in this section may be applied to a 2710 // specialization constant and still yield a result that is as 2711 // specialization constant. The operations allowed are listed below. 2712 // When a specialization constant is operated on with one of these 2713 // operators and with another constant or specialization constant, the 2714 // result is implicitly a specialization constant. 2715 // 2716 // - int(), uint(), and bool() constructors for type conversions 2717 // from any of the following types to any of the following types: 2718 // * int 2719 // * uint 2720 // * bool 2721 // - vector versions of the above conversion constructors 2722 // - allowed implicit conversions of the above 2723 // - swizzles (e.g., foo.yx) 2724 // - The following when applied to integer or unsigned integer types: 2725 // * unary negative ( - ) 2726 // * binary operations ( + , - , * , / , % ) 2727 // * shift ( <<, >> ) 2728 // * bitwise operations ( & , | , ^ ) 2729 // - The following when applied to integer or unsigned integer scalar types: 2730 // * comparison ( == , != , > , >= , < , <= ) 2731 // - The following when applied to the Boolean scalar type: 2732 // * not ( ! ) 2733 // * logical operations ( && , || , ^^ ) 2734 // * comparison ( == , != )" 2735 // 2736 // This function just handles binary and unary nodes. Construction 2737 // rules are handled in construction paths that are not covered by the unary 2738 // and binary paths, while required conversions will still show up here 2739 // as unary converters in the from a construction operator. 2740 // 2741 bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const 2742 { 2743 // The operations resulting in floating point are quite limited 2744 // (However, some floating-point operations result in bool, like ">", 2745 // so are handled later.) 2746 if (node.getType().isFloatingDomain()) { 2747 switch (node.getOp()) { 2748 case EOpIndexDirect: 2749 case EOpIndexIndirect: 2750 case EOpIndexDirectStruct: 2751 case EOpVectorSwizzle: 2752 case EOpConvFloatToDouble: 2753 case EOpConvDoubleToFloat: 2754 case EOpConvFloat16ToFloat: 2755 case EOpConvFloatToFloat16: 2756 case EOpConvFloat16ToDouble: 2757 case EOpConvDoubleToFloat16: 2758 return true; 2759 default: 2760 return false; 2761 } 2762 } 2763 2764 // Check for floating-point arguments 2765 if (const TIntermBinary* bin = node.getAsBinaryNode()) 2766 if (bin->getLeft() ->getType().isFloatingDomain() || 2767 bin->getRight()->getType().isFloatingDomain()) 2768 return false; 2769 2770 // So, for now, we can assume everything left is non-floating-point... 2771 2772 // Now check for integer/bool-based operations 2773 switch (node.getOp()) { 2774 2775 // dereference/swizzle 2776 case EOpIndexDirect: 2777 case EOpIndexIndirect: 2778 case EOpIndexDirectStruct: 2779 case EOpVectorSwizzle: 2780 2781 // (u)int* -> bool 2782 case EOpConvInt8ToBool: 2783 case EOpConvInt16ToBool: 2784 case EOpConvIntToBool: 2785 case EOpConvInt64ToBool: 2786 case EOpConvUint8ToBool: 2787 case EOpConvUint16ToBool: 2788 case EOpConvUintToBool: 2789 case EOpConvUint64ToBool: 2790 2791 // bool -> (u)int* 2792 case EOpConvBoolToInt8: 2793 case EOpConvBoolToInt16: 2794 case EOpConvBoolToInt: 2795 case EOpConvBoolToInt64: 2796 case EOpConvBoolToUint8: 2797 case EOpConvBoolToUint16: 2798 case EOpConvBoolToUint: 2799 case EOpConvBoolToUint64: 2800 2801 // int8_t -> (u)int* 2802 case EOpConvInt8ToInt16: 2803 case EOpConvInt8ToInt: 2804 case EOpConvInt8ToInt64: 2805 case EOpConvInt8ToUint8: 2806 case EOpConvInt8ToUint16: 2807 case EOpConvInt8ToUint: 2808 case EOpConvInt8ToUint64: 2809 2810 // int16_t -> (u)int* 2811 case EOpConvInt16ToInt8: 2812 case EOpConvInt16ToInt: 2813 case EOpConvInt16ToInt64: 2814 case EOpConvInt16ToUint8: 2815 case EOpConvInt16ToUint16: 2816 case EOpConvInt16ToUint: 2817 case EOpConvInt16ToUint64: 2818 2819 // int32_t -> (u)int* 2820 case EOpConvIntToInt8: 2821 case EOpConvIntToInt16: 2822 case EOpConvIntToInt64: 2823 case EOpConvIntToUint8: 2824 case EOpConvIntToUint16: 2825 case EOpConvIntToUint: 2826 case EOpConvIntToUint64: 2827 2828 // int64_t -> (u)int* 2829 case EOpConvInt64ToInt8: 2830 case EOpConvInt64ToInt16: 2831 case EOpConvInt64ToInt: 2832 case EOpConvInt64ToUint8: 2833 case EOpConvInt64ToUint16: 2834 case EOpConvInt64ToUint: 2835 case EOpConvInt64ToUint64: 2836 2837 // uint8_t -> (u)int* 2838 case EOpConvUint8ToInt8: 2839 case EOpConvUint8ToInt16: 2840 case EOpConvUint8ToInt: 2841 case EOpConvUint8ToInt64: 2842 case EOpConvUint8ToUint16: 2843 case EOpConvUint8ToUint: 2844 case EOpConvUint8ToUint64: 2845 2846 // uint16_t -> (u)int* 2847 case EOpConvUint16ToInt8: 2848 case EOpConvUint16ToInt16: 2849 case EOpConvUint16ToInt: 2850 case EOpConvUint16ToInt64: 2851 case EOpConvUint16ToUint8: 2852 case EOpConvUint16ToUint: 2853 case EOpConvUint16ToUint64: 2854 2855 // uint32_t -> (u)int* 2856 case EOpConvUintToInt8: 2857 case EOpConvUintToInt16: 2858 case EOpConvUintToInt: 2859 case EOpConvUintToInt64: 2860 case EOpConvUintToUint8: 2861 case EOpConvUintToUint16: 2862 case EOpConvUintToUint64: 2863 2864 // uint64_t -> (u)int* 2865 case EOpConvUint64ToInt8: 2866 case EOpConvUint64ToInt16: 2867 case EOpConvUint64ToInt: 2868 case EOpConvUint64ToInt64: 2869 case EOpConvUint64ToUint8: 2870 case EOpConvUint64ToUint16: 2871 case EOpConvUint64ToUint: 2872 2873 // unary operations 2874 case EOpNegative: 2875 case EOpLogicalNot: 2876 case EOpBitwiseNot: 2877 2878 // binary operations 2879 case EOpAdd: 2880 case EOpSub: 2881 case EOpMul: 2882 case EOpVectorTimesScalar: 2883 case EOpDiv: 2884 case EOpMod: 2885 case EOpRightShift: 2886 case EOpLeftShift: 2887 case EOpAnd: 2888 case EOpInclusiveOr: 2889 case EOpExclusiveOr: 2890 case EOpLogicalOr: 2891 case EOpLogicalXor: 2892 case EOpLogicalAnd: 2893 case EOpEqual: 2894 case EOpNotEqual: 2895 case EOpLessThan: 2896 case EOpGreaterThan: 2897 case EOpLessThanEqual: 2898 case EOpGreaterThanEqual: 2899 return true; 2900 default: 2901 return false; 2902 } 2903 } 2904 2905 // Is the operation one that must propagate nonuniform? 2906 bool TIntermediate::isNonuniformPropagating(TOperator op) const 2907 { 2908 // "* All Operators in Section 5.1 (Operators), except for assignment, 2909 // arithmetic assignment, and sequence 2910 // * Component selection in Section 5.5 2911 // * Matrix components in Section 5.6 2912 // * Structure and Array Operations in Section 5.7, except for the length 2913 // method." 2914 switch (op) { 2915 case EOpPostIncrement: 2916 case EOpPostDecrement: 2917 case EOpPreIncrement: 2918 case EOpPreDecrement: 2919 2920 case EOpNegative: 2921 case EOpLogicalNot: 2922 case EOpVectorLogicalNot: 2923 case EOpBitwiseNot: 2924 2925 case EOpAdd: 2926 case EOpSub: 2927 case EOpMul: 2928 case EOpDiv: 2929 case EOpMod: 2930 case EOpRightShift: 2931 case EOpLeftShift: 2932 case EOpAnd: 2933 case EOpInclusiveOr: 2934 case EOpExclusiveOr: 2935 case EOpEqual: 2936 case EOpNotEqual: 2937 case EOpLessThan: 2938 case EOpGreaterThan: 2939 case EOpLessThanEqual: 2940 case EOpGreaterThanEqual: 2941 case EOpVectorTimesScalar: 2942 case EOpVectorTimesMatrix: 2943 case EOpMatrixTimesVector: 2944 case EOpMatrixTimesScalar: 2945 2946 case EOpLogicalOr: 2947 case EOpLogicalXor: 2948 case EOpLogicalAnd: 2949 2950 case EOpIndexDirect: 2951 case EOpIndexIndirect: 2952 case EOpIndexDirectStruct: 2953 case EOpVectorSwizzle: 2954 return true; 2955 2956 default: 2957 break; 2958 } 2959 2960 return false; 2961 } 2962 2963 //////////////////////////////////////////////////////////////// 2964 // 2965 // Member functions of the nodes used for building the tree. 2966 // 2967 //////////////////////////////////////////////////////////////// 2968 2969 // 2970 // Say whether or not an operation node changes the value of a variable. 2971 // 2972 // Returns true if state is modified. 2973 // 2974 bool TIntermOperator::modifiesState() const 2975 { 2976 switch (op) { 2977 case EOpPostIncrement: 2978 case EOpPostDecrement: 2979 case EOpPreIncrement: 2980 case EOpPreDecrement: 2981 case EOpAssign: 2982 case EOpAddAssign: 2983 case EOpSubAssign: 2984 case EOpMulAssign: 2985 case EOpVectorTimesMatrixAssign: 2986 case EOpVectorTimesScalarAssign: 2987 case EOpMatrixTimesScalarAssign: 2988 case EOpMatrixTimesMatrixAssign: 2989 case EOpDivAssign: 2990 case EOpModAssign: 2991 case EOpAndAssign: 2992 case EOpInclusiveOrAssign: 2993 case EOpExclusiveOrAssign: 2994 case EOpLeftShiftAssign: 2995 case EOpRightShiftAssign: 2996 return true; 2997 default: 2998 return false; 2999 } 3000 } 3001 3002 // 3003 // returns true if the operator is for one of the constructors 3004 // 3005 bool TIntermOperator::isConstructor() const 3006 { 3007 return op > EOpConstructGuardStart && op < EOpConstructGuardEnd; 3008 } 3009 3010 // 3011 // Make sure the type of an operator is appropriate for its 3012 // combination of operation and operand type. This will invoke 3013 // promoteUnary, promoteBinary, etc as needed. 3014 // 3015 // Returns false if nothing makes sense. 3016 // 3017 bool TIntermediate::promote(TIntermOperator* node) 3018 { 3019 if (node == nullptr) 3020 return false; 3021 3022 if (node->getAsUnaryNode()) 3023 return promoteUnary(*node->getAsUnaryNode()); 3024 3025 if (node->getAsBinaryNode()) 3026 return promoteBinary(*node->getAsBinaryNode()); 3027 3028 if (node->getAsAggregate()) 3029 return promoteAggregate(*node->getAsAggregate()); 3030 3031 return false; 3032 } 3033 3034 // 3035 // See TIntermediate::promote 3036 // 3037 bool TIntermediate::promoteUnary(TIntermUnary& node) 3038 { 3039 const TOperator op = node.getOp(); 3040 TIntermTyped* operand = node.getOperand(); 3041 3042 switch (op) { 3043 case EOpLogicalNot: 3044 // Convert operand to a boolean type 3045 if (operand->getBasicType() != EbtBool) { 3046 // Add constructor to boolean type. If that fails, we can't do it, so return false. 3047 TIntermTyped* converted = addConversion(op, TType(EbtBool), operand); 3048 if (converted == nullptr) 3049 return false; 3050 3051 // Use the result of converting the node to a bool. 3052 node.setOperand(operand = converted); // also updates stack variable 3053 } 3054 break; 3055 case EOpBitwiseNot: 3056 if (!isTypeInt(operand->getBasicType())) 3057 return false; 3058 break; 3059 case EOpNegative: 3060 case EOpPostIncrement: 3061 case EOpPostDecrement: 3062 case EOpPreIncrement: 3063 case EOpPreDecrement: 3064 if (!isTypeInt(operand->getBasicType()) && 3065 operand->getBasicType() != EbtFloat && 3066 operand->getBasicType() != EbtFloat16 && 3067 operand->getBasicType() != EbtDouble) 3068 3069 return false; 3070 break; 3071 3072 default: 3073 if (operand->getBasicType() != EbtFloat) 3074 3075 return false; 3076 } 3077 3078 node.setType(operand->getType()); 3079 node.getWritableType().getQualifier().makeTemporary(); 3080 3081 return true; 3082 } 3083 3084 void TIntermUnary::updatePrecision() 3085 { 3086 if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { 3087 if (operand->getQualifier().precision > getQualifier().precision) 3088 getQualifier().precision = operand->getQualifier().precision; 3089 } 3090 } 3091 3092 // 3093 // See TIntermediate::promote 3094 // 3095 bool TIntermediate::promoteBinary(TIntermBinary& node) 3096 { 3097 TOperator op = node.getOp(); 3098 TIntermTyped* left = node.getLeft(); 3099 TIntermTyped* right = node.getRight(); 3100 3101 // Arrays and structures have to be exact matches. 3102 if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct) 3103 && left->getType() != right->getType()) 3104 return false; 3105 3106 // Base assumption: just make the type the same as the left 3107 // operand. Only deviations from this will be coded. 3108 node.setType(left->getType()); 3109 node.getWritableType().getQualifier().clear(); 3110 3111 // Composite and opaque types don't having pending operator changes, e.g., 3112 // array, structure, and samplers. Just establish final type and correctness. 3113 if (left->isArray() || left->getBasicType() == EbtStruct || left->getBasicType() == EbtSampler) { 3114 switch (op) { 3115 case EOpEqual: 3116 case EOpNotEqual: 3117 if (left->getBasicType() == EbtSampler) { 3118 // can't compare samplers 3119 return false; 3120 } else { 3121 // Promote to conditional 3122 node.setType(TType(EbtBool)); 3123 } 3124 3125 return true; 3126 3127 case EOpAssign: 3128 // Keep type from above 3129 3130 return true; 3131 3132 default: 3133 return false; 3134 } 3135 } 3136 3137 // 3138 // We now have only scalars, vectors, and matrices to worry about. 3139 // 3140 3141 // HLSL implicitly promotes bool -> int for numeric operations. 3142 // (Implicit conversions to make the operands match each other's types were already done.) 3143 if (getSource() == EShSourceHlsl && 3144 (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)) { 3145 switch (op) { 3146 case EOpLessThan: 3147 case EOpGreaterThan: 3148 case EOpLessThanEqual: 3149 case EOpGreaterThanEqual: 3150 3151 case EOpRightShift: 3152 case EOpLeftShift: 3153 3154 case EOpMod: 3155 3156 case EOpAnd: 3157 case EOpInclusiveOr: 3158 case EOpExclusiveOr: 3159 3160 case EOpAdd: 3161 case EOpSub: 3162 case EOpDiv: 3163 case EOpMul: 3164 if (left->getBasicType() == EbtBool) 3165 left = createConversion(EbtInt, left); 3166 if (right->getBasicType() == EbtBool) 3167 right = createConversion(EbtInt, right); 3168 if (left == nullptr || right == nullptr) 3169 return false; 3170 node.setLeft(left); 3171 node.setRight(right); 3172 3173 // Update the original base assumption on result type.. 3174 node.setType(left->getType()); 3175 node.getWritableType().getQualifier().clear(); 3176 3177 break; 3178 3179 default: 3180 break; 3181 } 3182 } 3183 3184 // Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that) 3185 switch (op) { 3186 case EOpLessThan: 3187 case EOpGreaterThan: 3188 case EOpLessThanEqual: 3189 case EOpGreaterThanEqual: 3190 // Relational comparisons need numeric types and will promote to scalar Boolean. 3191 if (left->getBasicType() == EbtBool) 3192 return false; 3193 3194 node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize())); 3195 break; 3196 3197 case EOpEqual: 3198 case EOpNotEqual: 3199 if (getSource() == EShSourceHlsl) { 3200 const int resultWidth = std::max(left->getVectorSize(), right->getVectorSize()); 3201 3202 // In HLSL, == or != on vectors means component-wise comparison. 3203 if (resultWidth > 1) { 3204 op = (op == EOpEqual) ? EOpVectorEqual : EOpVectorNotEqual; 3205 node.setOp(op); 3206 } 3207 3208 node.setType(TType(EbtBool, EvqTemporary, resultWidth)); 3209 } else { 3210 // All the above comparisons result in a bool (but not the vector compares) 3211 node.setType(TType(EbtBool)); 3212 } 3213 break; 3214 3215 case EOpLogicalAnd: 3216 case EOpLogicalOr: 3217 case EOpLogicalXor: 3218 // logical ops operate only on Booleans or vectors of Booleans. 3219 if (left->getBasicType() != EbtBool || left->isMatrix()) 3220 return false; 3221 3222 if (getSource() == EShSourceGlsl) { 3223 // logical ops operate only on scalar Booleans and will promote to scalar Boolean. 3224 if (left->isVector()) 3225 return false; 3226 } 3227 3228 node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize())); 3229 break; 3230 3231 case EOpRightShift: 3232 case EOpLeftShift: 3233 case EOpRightShiftAssign: 3234 case EOpLeftShiftAssign: 3235 3236 case EOpMod: 3237 case EOpModAssign: 3238 3239 case EOpAnd: 3240 case EOpInclusiveOr: 3241 case EOpExclusiveOr: 3242 case EOpAndAssign: 3243 case EOpInclusiveOrAssign: 3244 case EOpExclusiveOrAssign: 3245 if (getSource() == EShSourceHlsl) 3246 break; 3247 3248 // Check for integer-only operands. 3249 if (!isTypeInt(left->getBasicType()) && !isTypeInt(right->getBasicType())) 3250 return false; 3251 if (left->isMatrix() || right->isMatrix()) 3252 return false; 3253 3254 break; 3255 3256 case EOpAdd: 3257 case EOpSub: 3258 case EOpDiv: 3259 case EOpMul: 3260 case EOpAddAssign: 3261 case EOpSubAssign: 3262 case EOpMulAssign: 3263 case EOpDivAssign: 3264 // check for non-Boolean operands 3265 if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool) 3266 return false; 3267 3268 default: 3269 break; 3270 } 3271 3272 // Compare left and right, and finish with the cases where the operand types must match 3273 switch (op) { 3274 case EOpLessThan: 3275 case EOpGreaterThan: 3276 case EOpLessThanEqual: 3277 case EOpGreaterThanEqual: 3278 3279 case EOpEqual: 3280 case EOpNotEqual: 3281 case EOpVectorEqual: 3282 case EOpVectorNotEqual: 3283 3284 case EOpLogicalAnd: 3285 case EOpLogicalOr: 3286 case EOpLogicalXor: 3287 return left->getType() == right->getType(); 3288 3289 case EOpMod: 3290 case EOpModAssign: 3291 3292 case EOpAnd: 3293 case EOpInclusiveOr: 3294 case EOpExclusiveOr: 3295 case EOpAndAssign: 3296 case EOpInclusiveOrAssign: 3297 case EOpExclusiveOrAssign: 3298 3299 case EOpAdd: 3300 case EOpSub: 3301 case EOpDiv: 3302 3303 case EOpAddAssign: 3304 case EOpSubAssign: 3305 case EOpDivAssign: 3306 // Quick out in case the types do match 3307 if (left->getType() == right->getType()) 3308 return true; 3309 3310 // Fall through 3311 3312 case EOpMul: 3313 case EOpMulAssign: 3314 // At least the basic type has to match 3315 if (left->getBasicType() != right->getBasicType()) 3316 return false; 3317 3318 default: 3319 break; 3320 } 3321 3322 // Finish handling the case, for all ops, where both operands are scalars. 3323 if (left->isScalar() && right->isScalar()) 3324 return true; 3325 3326 // Finish handling the case, for all ops, where there are two vectors of different sizes 3327 if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1) 3328 return false; 3329 3330 // 3331 // We now have a mix of scalars, vectors, or matrices, for non-relational operations. 3332 // 3333 3334 // Can these two operands be combined, what is the resulting type? 3335 TBasicType basicType = left->getBasicType(); 3336 switch (op) { 3337 case EOpMul: 3338 if (!left->isMatrix() && right->isMatrix()) { 3339 if (left->isVector()) { 3340 if (left->getVectorSize() != right->getMatrixRows()) 3341 return false; 3342 node.setOp(op = EOpVectorTimesMatrix); 3343 node.setType(TType(basicType, EvqTemporary, right->getMatrixCols())); 3344 } else { 3345 node.setOp(op = EOpMatrixTimesScalar); 3346 node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows())); 3347 } 3348 } else if (left->isMatrix() && !right->isMatrix()) { 3349 if (right->isVector()) { 3350 if (left->getMatrixCols() != right->getVectorSize()) 3351 return false; 3352 node.setOp(op = EOpMatrixTimesVector); 3353 node.setType(TType(basicType, EvqTemporary, left->getMatrixRows())); 3354 } else { 3355 node.setOp(op = EOpMatrixTimesScalar); 3356 } 3357 } else if (left->isMatrix() && right->isMatrix()) { 3358 if (left->getMatrixCols() != right->getMatrixRows()) 3359 return false; 3360 node.setOp(op = EOpMatrixTimesMatrix); 3361 node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows())); 3362 } else if (! left->isMatrix() && ! right->isMatrix()) { 3363 if (left->isVector() && right->isVector()) { 3364 ; // leave as component product 3365 } else if (left->isVector() || right->isVector()) { 3366 node.setOp(op = EOpVectorTimesScalar); 3367 if (right->isVector()) 3368 node.setType(TType(basicType, EvqTemporary, right->getVectorSize())); 3369 } 3370 } else { 3371 return false; 3372 } 3373 break; 3374 case EOpMulAssign: 3375 if (! left->isMatrix() && right->isMatrix()) { 3376 if (left->isVector()) { 3377 if (left->getVectorSize() != right->getMatrixRows() || left->getVectorSize() != right->getMatrixCols()) 3378 return false; 3379 node.setOp(op = EOpVectorTimesMatrixAssign); 3380 } else { 3381 return false; 3382 } 3383 } else if (left->isMatrix() && !right->isMatrix()) { 3384 if (right->isVector()) { 3385 return false; 3386 } else { 3387 node.setOp(op = EOpMatrixTimesScalarAssign); 3388 } 3389 } else if (left->isMatrix() && right->isMatrix()) { 3390 if (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixCols() != right->getMatrixRows()) 3391 return false; 3392 node.setOp(op = EOpMatrixTimesMatrixAssign); 3393 } else if (!left->isMatrix() && !right->isMatrix()) { 3394 if (left->isVector() && right->isVector()) { 3395 // leave as component product 3396 } else if (left->isVector() || right->isVector()) { 3397 if (! left->isVector()) 3398 return false; 3399 node.setOp(op = EOpVectorTimesScalarAssign); 3400 } 3401 } else { 3402 return false; 3403 } 3404 break; 3405 3406 case EOpRightShift: 3407 case EOpLeftShift: 3408 case EOpRightShiftAssign: 3409 case EOpLeftShiftAssign: 3410 if (right->isVector() && (! left->isVector() || right->getVectorSize() != left->getVectorSize())) 3411 return false; 3412 break; 3413 3414 case EOpAssign: 3415 if (left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()) 3416 return false; 3417 // fall through 3418 3419 case EOpAdd: 3420 case EOpSub: 3421 case EOpDiv: 3422 case EOpMod: 3423 case EOpAnd: 3424 case EOpInclusiveOr: 3425 case EOpExclusiveOr: 3426 case EOpAddAssign: 3427 case EOpSubAssign: 3428 case EOpDivAssign: 3429 case EOpModAssign: 3430 case EOpAndAssign: 3431 case EOpInclusiveOrAssign: 3432 case EOpExclusiveOrAssign: 3433 3434 if ((left->isMatrix() && right->isVector()) || 3435 (left->isVector() && right->isMatrix()) || 3436 left->getBasicType() != right->getBasicType()) 3437 return false; 3438 if (left->isMatrix() && right->isMatrix() && (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows())) 3439 return false; 3440 if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize()) 3441 return false; 3442 if (right->isVector() || right->isMatrix()) { 3443 node.getWritableType().shallowCopy(right->getType()); 3444 node.getWritableType().getQualifier().makeTemporary(); 3445 } 3446 break; 3447 3448 default: 3449 return false; 3450 } 3451 3452 // 3453 // One more check for assignment. 3454 // 3455 switch (op) { 3456 // The resulting type has to match the left operand. 3457 case EOpAssign: 3458 case EOpAddAssign: 3459 case EOpSubAssign: 3460 case EOpMulAssign: 3461 case EOpDivAssign: 3462 case EOpModAssign: 3463 case EOpAndAssign: 3464 case EOpInclusiveOrAssign: 3465 case EOpExclusiveOrAssign: 3466 case EOpLeftShiftAssign: 3467 case EOpRightShiftAssign: 3468 if (node.getType() != left->getType()) 3469 return false; 3470 break; 3471 default: 3472 break; 3473 } 3474 3475 return true; 3476 } 3477 3478 // 3479 // See TIntermediate::promote 3480 // 3481 bool TIntermediate::promoteAggregate(TIntermAggregate& node) 3482 { 3483 TOperator op = node.getOp(); 3484 TIntermSequence& args = node.getSequence(); 3485 const int numArgs = static_cast<int>(args.size()); 3486 3487 // Presently, only hlsl does intrinsic promotions. 3488 if (getSource() != EShSourceHlsl) 3489 return true; 3490 3491 // set of opcodes that can be promoted in this manner. 3492 switch (op) { 3493 case EOpAtan: 3494 case EOpClamp: 3495 case EOpCross: 3496 case EOpDistance: 3497 case EOpDot: 3498 case EOpDst: 3499 case EOpFaceForward: 3500 // case EOpFindMSB: TODO: 3501 // case EOpFindLSB: TODO: 3502 case EOpFma: 3503 case EOpMod: 3504 case EOpFrexp: 3505 case EOpLdexp: 3506 case EOpMix: 3507 case EOpLit: 3508 case EOpMax: 3509 case EOpMin: 3510 case EOpModf: 3511 // case EOpGenMul: TODO: 3512 case EOpPow: 3513 case EOpReflect: 3514 case EOpRefract: 3515 // case EOpSinCos: TODO: 3516 case EOpSmoothStep: 3517 case EOpStep: 3518 break; 3519 default: 3520 return true; 3521 } 3522 3523 // TODO: array and struct behavior 3524 3525 // Try converting all nodes to the given node's type 3526 TIntermSequence convertedArgs(numArgs, nullptr); 3527 3528 // Try to convert all types to the nonConvArg type. 3529 for (int nonConvArg = 0; nonConvArg < numArgs; ++nonConvArg) { 3530 // Try converting all args to this arg's type 3531 for (int convArg = 0; convArg < numArgs; ++convArg) { 3532 convertedArgs[convArg] = addConversion(op, args[nonConvArg]->getAsTyped()->getType(), 3533 args[convArg]->getAsTyped()); 3534 } 3535 3536 // If we successfully converted all the args, use the result. 3537 if (std::all_of(convertedArgs.begin(), convertedArgs.end(), 3538 [](const TIntermNode* node) { return node != nullptr; })) { 3539 3540 std::swap(args, convertedArgs); 3541 return true; 3542 } 3543 } 3544 3545 return false; 3546 } 3547 3548 void TIntermBinary::updatePrecision() 3549 { 3550 if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { 3551 getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision); 3552 if (getQualifier().precision != EpqNone) { 3553 left->propagatePrecision(getQualifier().precision); 3554 right->propagatePrecision(getQualifier().precision); 3555 } 3556 } 3557 } 3558 3559 void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision) 3560 { 3561 if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16)) 3562 return; 3563 3564 getQualifier().precision = newPrecision; 3565 3566 TIntermBinary* binaryNode = getAsBinaryNode(); 3567 if (binaryNode) { 3568 binaryNode->getLeft()->propagatePrecision(newPrecision); 3569 binaryNode->getRight()->propagatePrecision(newPrecision); 3570 3571 return; 3572 } 3573 3574 TIntermUnary* unaryNode = getAsUnaryNode(); 3575 if (unaryNode) { 3576 unaryNode->getOperand()->propagatePrecision(newPrecision); 3577 3578 return; 3579 } 3580 3581 TIntermAggregate* aggregateNode = getAsAggregate(); 3582 if (aggregateNode) { 3583 TIntermSequence operands = aggregateNode->getSequence(); 3584 for (unsigned int i = 0; i < operands.size(); ++i) { 3585 TIntermTyped* typedNode = operands[i]->getAsTyped(); 3586 if (! typedNode) 3587 break; 3588 typedNode->propagatePrecision(newPrecision); 3589 } 3590 3591 return; 3592 } 3593 3594 TIntermSelection* selectionNode = getAsSelectionNode(); 3595 if (selectionNode) { 3596 TIntermTyped* typedNode = selectionNode->getTrueBlock()->getAsTyped(); 3597 if (typedNode) { 3598 typedNode->propagatePrecision(newPrecision); 3599 typedNode = selectionNode->getFalseBlock()->getAsTyped(); 3600 if (typedNode) 3601 typedNode->propagatePrecision(newPrecision); 3602 } 3603 3604 return; 3605 } 3606 } 3607 3608 TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) const 3609 { 3610 const TConstUnionArray& rightUnionArray = node->getConstArray(); 3611 int size = node->getType().computeNumComponents(); 3612 3613 TConstUnionArray leftUnionArray(size); 3614 3615 for (int i=0; i < size; i++) { 3616 switch (promoteTo) { 3617 case EbtFloat: 3618 switch (node->getType().getBasicType()) { 3619 case EbtInt: 3620 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst())); 3621 break; 3622 case EbtUint: 3623 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst())); 3624 break; 3625 case EbtInt64: 3626 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const())); 3627 break; 3628 case EbtUint64: 3629 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const())); 3630 break; 3631 case EbtBool: 3632 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst())); 3633 break; 3634 case EbtFloat: 3635 case EbtDouble: 3636 case EbtFloat16: 3637 leftUnionArray[i] = rightUnionArray[i]; 3638 break; 3639 default: 3640 return node; 3641 } 3642 break; 3643 case EbtDouble: 3644 switch (node->getType().getBasicType()) { 3645 case EbtInt: 3646 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst())); 3647 break; 3648 case EbtUint: 3649 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst())); 3650 break; 3651 case EbtInt64: 3652 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const())); 3653 break; 3654 case EbtUint64: 3655 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const())); 3656 break; 3657 case EbtBool: 3658 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst())); 3659 break; 3660 case EbtFloat: 3661 case EbtDouble: 3662 case EbtFloat16: 3663 leftUnionArray[i] = rightUnionArray[i]; 3664 break; 3665 default: 3666 return node; 3667 } 3668 break; 3669 case EbtFloat16: 3670 switch (node->getType().getBasicType()) { 3671 case EbtInt: 3672 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst())); 3673 break; 3674 case EbtUint: 3675 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst())); 3676 break; 3677 case EbtInt64: 3678 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const())); 3679 break; 3680 case EbtUint64: 3681 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const())); 3682 break; 3683 case EbtBool: 3684 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst())); 3685 break; 3686 case EbtFloat: 3687 case EbtDouble: 3688 case EbtFloat16: 3689 leftUnionArray[i] = rightUnionArray[i]; 3690 break; 3691 default: 3692 return node; 3693 } 3694 break; 3695 case EbtInt: 3696 switch (node->getType().getBasicType()) { 3697 case EbtInt: 3698 leftUnionArray[i] = rightUnionArray[i]; 3699 break; 3700 case EbtUint: 3701 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getUConst())); 3702 break; 3703 case EbtInt64: 3704 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getI64Const())); 3705 break; 3706 case EbtUint64: 3707 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getU64Const())); 3708 break; 3709 case EbtBool: 3710 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst())); 3711 break; 3712 case EbtFloat: 3713 case EbtDouble: 3714 case EbtFloat16: 3715 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getDConst())); 3716 break; 3717 default: 3718 return node; 3719 } 3720 break; 3721 case EbtUint: 3722 switch (node->getType().getBasicType()) { 3723 case EbtInt: 3724 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getIConst())); 3725 break; 3726 case EbtUint: 3727 leftUnionArray[i] = rightUnionArray[i]; 3728 break; 3729 case EbtInt64: 3730 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getI64Const())); 3731 break; 3732 case EbtUint64: 3733 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getU64Const())); 3734 break; 3735 case EbtBool: 3736 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getBConst())); 3737 break; 3738 case EbtFloat: 3739 case EbtDouble: 3740 case EbtFloat16: 3741 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getDConst())); 3742 break; 3743 default: 3744 return node; 3745 } 3746 break; 3747 case EbtBool: 3748 switch (node->getType().getBasicType()) { 3749 case EbtInt: 3750 leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0); 3751 break; 3752 case EbtUint: 3753 leftUnionArray[i].setBConst(rightUnionArray[i].getUConst() != 0); 3754 break; 3755 case EbtInt64: 3756 leftUnionArray[i].setBConst(rightUnionArray[i].getI64Const() != 0); 3757 break; 3758 case EbtUint64: 3759 leftUnionArray[i].setBConst(rightUnionArray[i].getU64Const() != 0); 3760 break; 3761 case EbtBool: 3762 leftUnionArray[i] = rightUnionArray[i]; 3763 break; 3764 case EbtFloat: 3765 case EbtDouble: 3766 case EbtFloat16: 3767 leftUnionArray[i].setBConst(rightUnionArray[i].getDConst() != 0.0); 3768 break; 3769 default: 3770 return node; 3771 } 3772 break; 3773 case EbtInt64: 3774 switch (node->getType().getBasicType()) { 3775 case EbtInt: 3776 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getIConst())); 3777 break; 3778 case EbtUint: 3779 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getUConst())); 3780 break; 3781 case EbtInt64: 3782 leftUnionArray[i] = rightUnionArray[i]; 3783 break; 3784 case EbtUint64: 3785 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getU64Const())); 3786 break; 3787 case EbtBool: 3788 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getBConst())); 3789 break; 3790 case EbtFloat: 3791 case EbtDouble: 3792 case EbtFloat16: 3793 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getDConst())); 3794 break; 3795 default: 3796 return node; 3797 } 3798 break; 3799 case EbtUint64: 3800 switch (node->getType().getBasicType()) { 3801 case EbtInt: 3802 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getIConst())); 3803 break; 3804 case EbtUint: 3805 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getUConst())); 3806 break; 3807 case EbtInt64: 3808 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getI64Const())); 3809 break; 3810 case EbtUint64: 3811 leftUnionArray[i] = rightUnionArray[i]; 3812 break; 3813 case EbtBool: 3814 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getBConst())); 3815 break; 3816 case EbtFloat: 3817 case EbtDouble: 3818 case EbtFloat16: 3819 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getDConst())); 3820 break; 3821 default: 3822 return node; 3823 } 3824 break; 3825 default: 3826 return node; 3827 } 3828 } 3829 3830 const TType& t = node->getType(); 3831 3832 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()), 3833 node->getLoc()); 3834 } 3835 3836 void TIntermAggregate::setPragmaTable(const TPragmaTable& pTable) 3837 { 3838 assert(pragmaTable == nullptr); 3839 pragmaTable = new TPragmaTable; 3840 *pragmaTable = pTable; 3841 } 3842 3843 // If either node is a specialization constant, while the other is 3844 // a constant (or specialization constant), the result is still 3845 // a specialization constant. 3846 bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TIntermTyped& node2) 3847 { 3848 return (node1.getType().getQualifier().isSpecConstant() && node2.getType().getQualifier().isConstant()) || 3849 (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant()); 3850 } 3851 3852 struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser { 3853 void visitSymbol(TIntermSymbol* symbol) override { 3854 if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) { 3855 symbol->getWritableType().getSampler().combined = true; 3856 } 3857 } 3858 bool visitAggregate(TVisit, TIntermAggregate* ag) override { 3859 using namespace std; 3860 TIntermSequence& seq = ag->getSequence(); 3861 TQualifierList& qual = ag->getQualifierList(); 3862 3863 // qual and seq are indexed using the same indices, so we have to modify both in lock-step 3864 assert(seq.size() == qual.size() || qual.empty()); 3865 3866 size_t write = 0; 3867 for (size_t i = 0; i < seq.size(); ++i) { 3868 TIntermSymbol* symbol = seq[i]->getAsSymbolNode(); 3869 if (symbol && symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()) { 3870 // remove pure sampler variables 3871 continue; 3872 } 3873 3874 TIntermNode* result = seq[i]; 3875 3876 // replace constructors with sampler/textures 3877 TIntermAggregate *constructor = seq[i]->getAsAggregate(); 3878 if (constructor && constructor->getOp() == EOpConstructTextureSampler) { 3879 if (!constructor->getSequence().empty()) 3880 result = constructor->getSequence()[0]; 3881 } 3882 3883 // write new node & qualifier 3884 seq[write] = result; 3885 if (!qual.empty()) 3886 qual[write] = qual[i]; 3887 write++; 3888 } 3889 3890 seq.resize(write); 3891 if (!qual.empty()) 3892 qual.resize(write); 3893 3894 return true; 3895 } 3896 }; 3897 3898 void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root) 3899 { 3900 TextureUpgradeAndSamplerRemovalTransform transform; 3901 root->traverse(&transform); 3902 } 3903 3904 const char* TIntermediate::getResourceName(TResourceType res) 3905 { 3906 switch (res) { 3907 case EResSampler: return "shift-sampler-binding"; 3908 case EResTexture: return "shift-texture-binding"; 3909 case EResImage: return "shift-image-binding"; 3910 case EResUbo: return "shift-UBO-binding"; 3911 case EResSsbo: return "shift-ssbo-binding"; 3912 case EResUav: return "shift-uav-binding"; 3913 default: 3914 assert(0); // internal error: should only be called with valid resource types. 3915 return nullptr; 3916 } 3917 } 3918 3919 3920 } // end namespace glslang 3921