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