Home | History | Annotate | Download | only in MachineIndependent
      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