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