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