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