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