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