• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2013 LunarG, Inc.
4 // Copyright (C) 2017 ARM Limited.
5 // Copyright (C) 2018-2020 Google, Inc.
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 #include "localintermediate.h"
40 #include <cmath>
41 #include <cfloat>
42 #include <cstdlib>
43 #include <climits>
44 
45 namespace {
46 
47 using namespace glslang;
48 
49 const double pi = 3.1415926535897932384626433832795;
50 
51 } // end anonymous namespace
52 
53 
54 namespace glslang {
55 
56 //
57 // The fold functions see if an operation on a constant can be done in place,
58 // without generating run-time code.
59 //
60 // Returns the node to keep using, which may or may not be the node passed in.
61 //
62 // Note: As of version 1.2, all constant operations must be folded.  It is
63 // not opportunistic, but rather a semantic requirement.
64 //
65 
66 //
67 // Do folding between a pair of nodes.
68 // 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
69 //
70 // Returns a new node representing the result.
71 //
fold(TOperator op,const TIntermTyped * rightConstantNode) const72 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
73 {
74     // For most cases, the return type matches the argument type, so set that
75     // up and just code to exceptions below.
76     TType returnType;
77     returnType.shallowCopy(getType());
78 
79     //
80     // A pair of nodes is to be folded together
81     //
82 
83     const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
84     TConstUnionArray leftUnionArray = getConstArray();
85     TConstUnionArray rightUnionArray = rightNode->getConstArray();
86 
87     // Figure out the size of the result
88     int newComps;
89     int constComps;
90     switch(op) {
91     case EOpMatrixTimesMatrix:
92         newComps = rightNode->getMatrixCols() * getMatrixRows();
93         break;
94     case EOpMatrixTimesVector:
95         newComps = getMatrixRows();
96         break;
97     case EOpVectorTimesMatrix:
98         newComps = rightNode->getMatrixCols();
99         break;
100     default:
101         newComps = getType().computeNumComponents();
102         constComps = rightConstantNode->getType().computeNumComponents();
103         if (constComps == 1 && newComps > 1) {
104             // for a case like vec4 f = vec4(2,3,4,5) + 1.2;
105             TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]);
106             rightUnionArray = smearedArray;
107         } else if (constComps > 1 && newComps == 1) {
108             // for a case like vec4 f = 1.2 + vec4(2,3,4,5);
109             newComps = constComps;
110             rightUnionArray = rightNode->getConstArray();
111             TConstUnionArray smearedArray(newComps, getConstArray()[0]);
112             leftUnionArray = smearedArray;
113             returnType.shallowCopy(rightNode->getType());
114         }
115         break;
116     }
117 
118     TConstUnionArray newConstArray(newComps);
119     TType constBool(EbtBool, EvqConst);
120 
121     switch(op) {
122     case EOpAdd:
123         for (int i = 0; i < newComps; i++)
124             newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
125         break;
126     case EOpSub:
127         for (int i = 0; i < newComps; i++)
128             newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
129         break;
130 
131     case EOpMul:
132     case EOpVectorTimesScalar:
133     case EOpMatrixTimesScalar:
134         for (int i = 0; i < newComps; i++)
135             newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
136         break;
137     case EOpMatrixTimesMatrix:
138         for (int row = 0; row < getMatrixRows(); row++) {
139             for (int column = 0; column < rightNode->getMatrixCols(); column++) {
140                 double sum = 0.0f;
141                 for (int i = 0; i < rightNode->getMatrixRows(); i++)
142                     sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst();
143                 newConstArray[column * getMatrixRows() + row].setDConst(sum);
144             }
145         }
146         returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
147         break;
148     case EOpDiv:
149         for (int i = 0; i < newComps; i++) {
150             switch (getType().getBasicType()) {
151             case EbtDouble:
152             case EbtFloat:
153             case EbtFloat16:
154                 if (rightUnionArray[i].getDConst() != 0.0)
155                     newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
156                 else if (leftUnionArray[i].getDConst() > 0.0)
157                     newConstArray[i].setDConst((double)INFINITY);
158                 else if (leftUnionArray[i].getDConst() < 0.0)
159                     newConstArray[i].setDConst(-(double)INFINITY);
160                 else
161                     newConstArray[i].setDConst((double)NAN);
162                 break;
163 
164             case EbtInt:
165                 if (rightUnionArray[i] == 0)
166                     newConstArray[i].setIConst(0x7FFFFFFF);
167                 else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
168                     newConstArray[i].setIConst((int)-0x80000000ll);
169                 else
170                     newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
171                 break;
172 
173             case EbtUint:
174                 if (rightUnionArray[i] == 0u)
175                     newConstArray[i].setUConst(0xFFFFFFFFu);
176                 else
177                     newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
178                 break;
179 
180             case EbtInt8:
181                 if (rightUnionArray[i] == (signed char)0)
182                     newConstArray[i].setI8Const((signed char)0x7F);
183                 else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
184                     newConstArray[i].setI8Const((signed char)-0x80);
185                 else
186                     newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
187                 break;
188 
189             case EbtUint8:
190                 if (rightUnionArray[i] == (unsigned char)0u)
191                     newConstArray[i].setU8Const((unsigned char)0xFFu);
192                 else
193                     newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
194                 break;
195 
196            case EbtInt16:
197                 if (rightUnionArray[i] == (signed short)0)
198                     newConstArray[i].setI16Const((signed short)0x7FFF);
199                 else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
200                     newConstArray[i].setI16Const((signed short)-0x8000);
201                 else
202                     newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
203                 break;
204 
205             case EbtUint16:
206                 if (rightUnionArray[i] == (unsigned short)0u)
207                     newConstArray[i].setU16Const((unsigned short)0xFFFFu);
208                 else
209                     newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
210                 break;
211 
212             case EbtInt64:
213                 if (rightUnionArray[i] == 0ll)
214                     newConstArray[i].setI64Const(LLONG_MAX);
215                 else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN)
216                     newConstArray[i].setI64Const(LLONG_MIN);
217                 else
218                     newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
219                 break;
220 
221             case EbtUint64:
222                 if (rightUnionArray[i] == 0ull)
223                     newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
224                 else
225                     newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
226                 break;
227             default:
228                 return nullptr;
229             }
230         }
231         break;
232 
233     case EOpMatrixTimesVector:
234         for (int i = 0; i < getMatrixRows(); i++) {
235             double sum = 0.0f;
236             for (int j = 0; j < rightNode->getVectorSize(); j++) {
237                 sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
238             }
239             newConstArray[i].setDConst(sum);
240         }
241 
242         returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
243         break;
244 
245     case EOpVectorTimesMatrix:
246         for (int i = 0; i < rightNode->getMatrixCols(); i++) {
247             double sum = 0.0f;
248             for (int j = 0; j < getVectorSize(); j++)
249                 sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
250             newConstArray[i].setDConst(sum);
251         }
252 
253         returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
254         break;
255 
256     case EOpMod:
257         for (int i = 0; i < newComps; i++) {
258             if (rightUnionArray[i] == 0)
259                 newConstArray[i] = leftUnionArray[i];
260             else {
261                 switch (getType().getBasicType()) {
262                 case EbtInt:
263                     if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
264                         newConstArray[i].setIConst(0);
265                         break;
266                     } else goto modulo_default;
267                 case EbtInt64:
268                     if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
269                         newConstArray[i].setI64Const(0);
270                         break;
271                     } else goto modulo_default;
272                 case EbtInt16:
273                     if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
274                         newConstArray[i].setIConst(0);
275                         break;
276                     } else goto modulo_default;
277                 default:
278                 modulo_default:
279                     newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
280                 }
281             }
282         }
283         break;
284 
285     case EOpRightShift:
286         for (int i = 0; i < newComps; i++)
287             newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
288         break;
289 
290     case EOpLeftShift:
291         for (int i = 0; i < newComps; i++)
292             newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
293         break;
294 
295     case EOpAnd:
296         for (int i = 0; i < newComps; i++)
297             newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
298         break;
299     case EOpInclusiveOr:
300         for (int i = 0; i < newComps; i++)
301             newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
302         break;
303     case EOpExclusiveOr:
304         for (int i = 0; i < newComps; i++)
305             newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
306         break;
307 
308     case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
309         for (int i = 0; i < newComps; i++)
310             newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
311         break;
312 
313     case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
314         for (int i = 0; i < newComps; i++)
315             newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
316         break;
317 
318     case EOpLogicalXor:
319         for (int i = 0; i < newComps; i++) {
320             switch (getType().getBasicType()) {
321             case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
322             default: assert(false && "Default missing");
323             }
324         }
325         break;
326 
327     case EOpLessThan:
328         newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
329         returnType.shallowCopy(constBool);
330         break;
331     case EOpGreaterThan:
332         newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
333         returnType.shallowCopy(constBool);
334         break;
335     case EOpLessThanEqual:
336         newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
337         returnType.shallowCopy(constBool);
338         break;
339     case EOpGreaterThanEqual:
340         newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
341         returnType.shallowCopy(constBool);
342         break;
343     case EOpEqual:
344         newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
345         returnType.shallowCopy(constBool);
346         break;
347     case EOpNotEqual:
348         newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
349         returnType.shallowCopy(constBool);
350         break;
351 
352     default:
353         return nullptr;
354     }
355 
356     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
357     newNode->setLoc(getLoc());
358 
359     return newNode;
360 }
361 
362 //
363 // Do single unary node folding
364 //
365 // Returns a new node representing the result.
366 //
fold(TOperator op,const TType & returnType) const367 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
368 {
369     // First, size the result, which is mostly the same as the argument's size,
370     // but not always, and classify what is componentwise.
371     // Also, eliminate cases that can't be compile-time constant.
372     int resultSize;
373     bool componentWise = true;
374 
375     int objectSize = getType().computeNumComponents();
376     switch (op) {
377     case EOpDeterminant:
378     case EOpAny:
379     case EOpAll:
380     case EOpLength:
381         componentWise = false;
382         resultSize = 1;
383         break;
384 
385     case EOpEmitStreamVertex:
386     case EOpEndStreamPrimitive:
387         // These don't fold
388         return nullptr;
389 
390     case EOpPackSnorm2x16:
391     case EOpPackUnorm2x16:
392     case EOpPackHalf2x16:
393         componentWise = false;
394         resultSize = 1;
395         break;
396 
397     case EOpUnpackSnorm2x16:
398     case EOpUnpackUnorm2x16:
399     case EOpUnpackHalf2x16:
400         componentWise = false;
401         resultSize = 2;
402         break;
403 
404     case EOpPack16:
405     case EOpPack32:
406     case EOpPack64:
407     case EOpUnpack32:
408     case EOpUnpack16:
409     case EOpUnpack8:
410     case EOpNormalize:
411         componentWise = false;
412         resultSize = objectSize;
413         break;
414 
415     default:
416         resultSize = objectSize;
417         break;
418     }
419 
420     // Set up for processing
421     TConstUnionArray newConstArray(resultSize);
422     const TConstUnionArray& unionArray = getConstArray();
423 
424     // Process non-component-wise operations
425     switch (op) {
426     case EOpLength:
427     case EOpNormalize:
428     {
429         double sum = 0;
430         for (int i = 0; i < objectSize; i++)
431             sum += unionArray[i].getDConst() * unionArray[i].getDConst();
432         double length = sqrt(sum);
433         if (op == EOpLength)
434             newConstArray[0].setDConst(length);
435         else {
436             for (int i = 0; i < objectSize; i++)
437                 newConstArray[i].setDConst(unionArray[i].getDConst() / length);
438         }
439         break;
440     }
441 
442     case EOpAny:
443     {
444         bool result = false;
445         for (int i = 0; i < objectSize; i++) {
446             if (unionArray[i].getBConst())
447                 result = true;
448         }
449         newConstArray[0].setBConst(result);
450         break;
451     }
452     case EOpAll:
453     {
454         bool result = true;
455         for (int i = 0; i < objectSize; i++) {
456             if (! unionArray[i].getBConst())
457                 result = false;
458         }
459         newConstArray[0].setBConst(result);
460         break;
461     }
462 
463     case EOpPackSnorm2x16:
464     case EOpPackUnorm2x16:
465     case EOpPackHalf2x16:
466     case EOpPack16:
467     case EOpPack32:
468     case EOpPack64:
469     case EOpUnpack32:
470     case EOpUnpack16:
471     case EOpUnpack8:
472 
473     case EOpUnpackSnorm2x16:
474     case EOpUnpackUnorm2x16:
475     case EOpUnpackHalf2x16:
476 
477     case EOpDeterminant:
478     case EOpMatrixInverse:
479     case EOpTranspose:
480         return nullptr;
481 
482     default:
483         assert(componentWise);
484         break;
485     }
486 
487     // Turn off the componentwise loop
488     if (! componentWise)
489         objectSize = 0;
490 
491     // Process component-wise operations
492     for (int i = 0; i < objectSize; i++) {
493         switch (op) {
494         case EOpNegative:
495             switch (getType().getBasicType()) {
496             case EbtDouble:
497             case EbtFloat16:
498             case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
499             // Note: avoid UBSAN error regarding negating 0x80000000
500             case EbtInt:   newConstArray[i].setIConst(
501                                 static_cast<unsigned int>(unionArray[i].getIConst()) == 0x80000000
502                                     ? -0x7FFFFFFF - 1
503                                     : -unionArray[i].getIConst());
504                            break;
505             case EbtUint:  newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst())));  break;
506             case EbtInt8:  newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
507             case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const())));  break;
508             case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
509             case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const())));  break;
510             case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
511             case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const())));  break;
512             default:
513                 return nullptr;
514             }
515             break;
516         case EOpLogicalNot:
517         case EOpVectorLogicalNot:
518             switch (getType().getBasicType()) {
519             case EbtBool:  newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
520             default:
521                 return nullptr;
522             }
523             break;
524         case EOpBitwiseNot:
525             newConstArray[i] = ~unionArray[i];
526             break;
527         case EOpRadians:
528             newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
529             break;
530         case EOpDegrees:
531             newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
532             break;
533         case EOpSin:
534             newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
535             break;
536         case EOpCos:
537             newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
538             break;
539         case EOpTan:
540             newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
541             break;
542         case EOpAsin:
543             newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
544             break;
545         case EOpAcos:
546             newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
547             break;
548         case EOpAtan:
549             newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
550             break;
551 
552         case EOpDPdx:
553         case EOpDPdy:
554         case EOpFwidth:
555         case EOpDPdxFine:
556         case EOpDPdyFine:
557         case EOpFwidthFine:
558         case EOpDPdxCoarse:
559         case EOpDPdyCoarse:
560         case EOpFwidthCoarse:
561             // The derivatives are all mandated to create a constant 0.
562             newConstArray[i].setDConst(0.0);
563             break;
564 
565         case EOpExp:
566             newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
567             break;
568         case EOpLog:
569             newConstArray[i].setDConst(log(unionArray[i].getDConst()));
570             break;
571         case EOpExp2:
572             newConstArray[i].setDConst(exp2(unionArray[i].getDConst()));
573             break;
574         case EOpLog2:
575             newConstArray[i].setDConst(log2(unionArray[i].getDConst()));
576             break;
577         case EOpSqrt:
578             newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
579             break;
580         case EOpInverseSqrt:
581             newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
582             break;
583 
584         case EOpAbs:
585             if (unionArray[i].getType() == EbtDouble)
586                 newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
587             else if (unionArray[i].getType() == EbtInt)
588                 newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
589             else
590                 newConstArray[i] = unionArray[i];
591             break;
592         case EOpSign:
593             #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
594             if (unionArray[i].getType() == EbtDouble)
595                 newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
596             else
597                 newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
598             break;
599         case EOpFloor:
600             newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
601             break;
602         case EOpTrunc:
603             if (unionArray[i].getDConst() > 0)
604                 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
605             else
606                 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
607             break;
608         case EOpRound:
609             newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
610             break;
611         case EOpRoundEven:
612         {
613             double flr = floor(unionArray[i].getDConst());
614             bool even = flr / 2.0 == floor(flr / 2.0);
615             double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
616             newConstArray[i].setDConst(rounded);
617             break;
618         }
619         case EOpCeil:
620             newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
621             break;
622         case EOpFract:
623         {
624             double x = unionArray[i].getDConst();
625             newConstArray[i].setDConst(x - floor(x));
626             break;
627         }
628 
629         case EOpIsNan:
630         {
631             newConstArray[i].setBConst(std::isnan(unionArray[i].getDConst()));
632             break;
633         }
634         case EOpIsInf:
635         {
636             newConstArray[i].setBConst(std::isinf(unionArray[i].getDConst()));
637             break;
638         }
639 
640         case EOpConvIntToBool:
641             newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
642         case EOpConvUintToBool:
643             newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
644         case EOpConvBoolToInt:
645             newConstArray[i].setIConst(unionArray[i].getBConst()); break;
646         case EOpConvBoolToUint:
647             newConstArray[i].setUConst(unionArray[i].getBConst()); break;
648         case EOpConvIntToUint:
649             newConstArray[i].setUConst(unionArray[i].getIConst()); break;
650         case EOpConvUintToInt:
651             newConstArray[i].setIConst(unionArray[i].getUConst()); break;
652 
653         case EOpConvFloatToBool:
654         case EOpConvDoubleToBool:
655             newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
656 
657         case EOpConvBoolToFloat:
658         case EOpConvBoolToDouble:
659             newConstArray[i].setDConst(unionArray[i].getBConst()); break;
660 
661         case EOpConvIntToFloat:
662         case EOpConvIntToDouble:
663             newConstArray[i].setDConst(unionArray[i].getIConst()); break;
664 
665         case EOpConvUintToFloat:
666         case EOpConvUintToDouble:
667             newConstArray[i].setDConst(unionArray[i].getUConst()); break;
668 
669         case EOpConvDoubleToFloat:
670         case EOpConvFloatToDouble:
671             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
672 
673         case EOpConvFloatToUint:
674         case EOpConvDoubleToUint:
675             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
676 
677         case EOpConvFloatToInt:
678         case EOpConvDoubleToInt:
679             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
680 
681         case EOpConvInt8ToBool:
682             newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
683         case EOpConvUint8ToBool:
684             newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
685         case EOpConvInt16ToBool:
686             newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
687         case EOpConvUint16ToBool:
688             newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
689         case EOpConvInt64ToBool:
690             newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
691         case EOpConvUint64ToBool:
692             newConstArray[i].setBConst(unionArray[i].getU64Const() != 0); break;
693         case EOpConvFloat16ToBool:
694             newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
695 
696         case EOpConvBoolToInt8:
697             newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
698         case EOpConvBoolToUint8:
699             newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
700         case EOpConvBoolToInt16:
701             newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
702         case EOpConvBoolToUint16:
703             newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
704         case EOpConvBoolToInt64:
705             newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
706         case EOpConvBoolToUint64:
707             newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
708         case EOpConvBoolToFloat16:
709             newConstArray[i].setDConst(unionArray[i].getBConst()); break;
710 
711         case EOpConvInt8ToInt16:
712             newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
713         case EOpConvInt8ToInt:
714             newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
715         case EOpConvInt8ToInt64:
716             newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
717         case EOpConvInt8ToUint8:
718             newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
719         case EOpConvInt8ToUint16:
720             newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
721         case EOpConvInt8ToUint:
722             newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
723         case EOpConvInt8ToUint64:
724             newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
725         case EOpConvUint8ToInt8:
726             newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
727         case EOpConvUint8ToInt16:
728             newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
729         case EOpConvUint8ToInt:
730             newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
731         case EOpConvUint8ToInt64:
732             newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
733         case EOpConvUint8ToUint16:
734             newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
735         case EOpConvUint8ToUint:
736             newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
737         case EOpConvUint8ToUint64:
738             newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
739         case EOpConvInt8ToFloat16:
740             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
741         case EOpConvInt8ToFloat:
742             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
743         case EOpConvInt8ToDouble:
744             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
745         case EOpConvUint8ToFloat16:
746             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
747         case EOpConvUint8ToFloat:
748             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
749         case EOpConvUint8ToDouble:
750             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
751 
752         case EOpConvInt16ToInt8:
753             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
754         case EOpConvInt16ToInt:
755             newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
756         case EOpConvInt16ToInt64:
757             newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
758         case EOpConvInt16ToUint8:
759             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
760         case EOpConvInt16ToUint16:
761             newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
762         case EOpConvInt16ToUint:
763             newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
764         case EOpConvInt16ToUint64:
765             newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
766         case EOpConvUint16ToInt8:
767             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
768         case EOpConvUint16ToInt16:
769             newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
770         case EOpConvUint16ToInt:
771             newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
772         case EOpConvUint16ToInt64:
773             newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
774         case EOpConvUint16ToUint8:
775             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
776 
777         case EOpConvUint16ToUint:
778             newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
779         case EOpConvUint16ToUint64:
780             newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
781         case EOpConvInt16ToFloat16:
782             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
783         case EOpConvInt16ToFloat:
784             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
785         case EOpConvInt16ToDouble:
786             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
787         case EOpConvUint16ToFloat16:
788             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
789         case EOpConvUint16ToFloat:
790             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
791         case EOpConvUint16ToDouble:
792             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
793 
794         case EOpConvIntToInt8:
795             newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
796         case EOpConvIntToInt16:
797             newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
798         case EOpConvIntToInt64:
799             newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
800         case EOpConvIntToUint8:
801             newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
802         case EOpConvIntToUint16:
803             newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
804         case EOpConvIntToUint64:
805             newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
806 
807         case EOpConvUintToInt8:
808             newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
809         case EOpConvUintToInt16:
810             newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
811         case EOpConvUintToInt64:
812             newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
813         case EOpConvUintToUint8:
814             newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
815         case EOpConvUintToUint16:
816             newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
817         case EOpConvUintToUint64:
818             newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
819         case EOpConvIntToFloat16:
820             newConstArray[i].setDConst(unionArray[i].getIConst()); break;
821         case EOpConvUintToFloat16:
822             newConstArray[i].setDConst(unionArray[i].getUConst()); break;
823         case EOpConvInt64ToInt8:
824             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
825         case EOpConvInt64ToInt16:
826             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
827         case EOpConvInt64ToInt:
828             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
829         case EOpConvInt64ToUint8:
830             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
831         case EOpConvInt64ToUint16:
832             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
833         case EOpConvInt64ToUint:
834             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
835         case EOpConvInt64ToUint64:
836             newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
837         case EOpConvUint64ToInt8:
838             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
839         case EOpConvUint64ToInt16:
840             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
841         case EOpConvUint64ToInt:
842             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
843         case EOpConvUint64ToInt64:
844             newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
845         case EOpConvUint64ToUint8:
846             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
847         case EOpConvUint64ToUint16:
848             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
849         case EOpConvUint64ToUint:
850             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
851         case EOpConvInt64ToFloat16:
852             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
853         case EOpConvInt64ToFloat:
854             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
855         case EOpConvInt64ToDouble:
856             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
857         case EOpConvUint64ToFloat16:
858             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
859         case EOpConvUint64ToFloat:
860             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
861         case EOpConvUint64ToDouble:
862             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
863         case EOpConvFloat16ToInt8:
864             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
865         case EOpConvFloat16ToInt16:
866             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
867         case EOpConvFloat16ToInt:
868             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
869         case EOpConvFloat16ToInt64:
870             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
871         case EOpConvFloat16ToUint8:
872             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
873         case EOpConvFloat16ToUint16:
874             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
875         case EOpConvFloat16ToUint:
876             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
877         case EOpConvFloat16ToUint64:
878             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
879         case EOpConvFloat16ToFloat:
880             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
881         case EOpConvFloat16ToDouble:
882             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
883         case EOpConvFloatToInt8:
884             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
885         case EOpConvFloatToInt16:
886             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
887         case EOpConvFloatToInt64:
888             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
889         case EOpConvFloatToUint8:
890             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
891         case EOpConvFloatToUint16:
892             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
893         case EOpConvFloatToUint64:
894             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
895         case EOpConvFloatToFloat16:
896             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
897         case EOpConvDoubleToInt8:
898             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
899         case EOpConvDoubleToInt16:
900             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
901         case EOpConvDoubleToInt64:
902             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
903         case EOpConvDoubleToUint8:
904             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
905         case EOpConvDoubleToUint16:
906             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
907         case EOpConvDoubleToUint64:
908             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
909         case EOpConvDoubleToFloat16:
910             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
911         case EOpConvPtrToUint64:
912         case EOpConvUint64ToPtr:
913         case EOpConstructReference:
914             newConstArray[i].setU64Const(unionArray[i].getU64Const()); break;
915 
916         // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
917 
918         case EOpSinh:
919         case EOpCosh:
920         case EOpTanh:
921         case EOpAsinh:
922         case EOpAcosh:
923         case EOpAtanh:
924 
925         case EOpFloatBitsToInt:
926         case EOpFloatBitsToUint:
927         case EOpIntBitsToFloat:
928         case EOpUintBitsToFloat:
929         case EOpDoubleBitsToInt64:
930         case EOpDoubleBitsToUint64:
931         case EOpInt64BitsToDouble:
932         case EOpUint64BitsToDouble:
933         case EOpFloat16BitsToInt16:
934         case EOpFloat16BitsToUint16:
935         case EOpInt16BitsToFloat16:
936         case EOpUint16BitsToFloat16:
937         default:
938             return nullptr;
939         }
940     }
941 
942     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
943     newNode->getWritableType().getQualifier().storage = EvqConst;
944     newNode->setLoc(getLoc());
945 
946     return newNode;
947 }
948 
949 //
950 // Do constant folding for an aggregate node that has all its children
951 // as constants and an operator that requires constant folding.
952 //
fold(TIntermAggregate * aggrNode)953 TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
954 {
955     if (aggrNode == nullptr)
956         return aggrNode;
957 
958     if (! areAllChildConst(aggrNode))
959         return aggrNode;
960 
961     if (aggrNode->isConstructor())
962         return foldConstructor(aggrNode);
963 
964     TIntermSequence& children = aggrNode->getSequence();
965 
966     // First, see if this is an operation to constant fold, kick out if not,
967     // see what size the result is if so.
968 
969     bool componentwise = false;  // will also say componentwise if a scalar argument gets repeated to make per-component results
970     int objectSize;
971     switch (aggrNode->getOp()) {
972     case EOpAtan:
973     case EOpPow:
974     case EOpMin:
975     case EOpMax:
976     case EOpMix:
977     case EOpMod:
978     case EOpClamp:
979     case EOpLessThan:
980     case EOpGreaterThan:
981     case EOpLessThanEqual:
982     case EOpGreaterThanEqual:
983     case EOpVectorEqual:
984     case EOpVectorNotEqual:
985         componentwise = true;
986         objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
987         break;
988     case EOpCross:
989     case EOpReflect:
990     case EOpRefract:
991     case EOpFaceForward:
992         objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
993         break;
994     case EOpDistance:
995     case EOpDot:
996         objectSize = 1;
997         break;
998     case EOpOuterProduct:
999         objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
1000                      children[1]->getAsTyped()->getType().getVectorSize();
1001         break;
1002     case EOpStep:
1003         componentwise = true;
1004         objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1005                               children[1]->getAsTyped()->getType().getVectorSize());
1006         break;
1007     case EOpSmoothStep:
1008         componentwise = true;
1009         objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1010                               children[2]->getAsTyped()->getType().getVectorSize());
1011         break;
1012     default:
1013         return aggrNode;
1014     }
1015     TConstUnionArray newConstArray(objectSize);
1016 
1017     TVector<TConstUnionArray> childConstUnions;
1018     for (unsigned int arg = 0; arg < children.size(); ++arg)
1019         childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
1020 
1021     if (componentwise) {
1022         for (int comp = 0; comp < objectSize; comp++) {
1023 
1024             // some arguments are scalars instead of matching vectors; simulate a smear
1025             int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
1026             int arg1comp = 0;
1027             if (children.size() > 1)
1028                 arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
1029             int arg2comp = 0;
1030             if (children.size() > 2)
1031                 arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
1032 
1033             switch (aggrNode->getOp()) {
1034             case EOpAtan:
1035                 newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1036                 break;
1037             case EOpPow:
1038                 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1039                 break;
1040             case EOpMod:
1041             {
1042                 double arg0 = childConstUnions[0][arg0comp].getDConst();
1043                 double arg1 = childConstUnions[1][arg1comp].getDConst();
1044                 double result = arg0 - arg1 * floor(arg0 / arg1);
1045                 newConstArray[comp].setDConst(result);
1046                 break;
1047             }
1048             case EOpMin:
1049                 switch(children[0]->getAsTyped()->getBasicType()) {
1050                 case EbtFloat16:
1051                 case EbtFloat:
1052                 case EbtDouble:
1053                     newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1054                     break;
1055                 case EbtInt:
1056                     newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1057                     break;
1058                 case EbtUint:
1059                     newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1060                     break;
1061                 case EbtInt8:
1062                     newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1063                     break;
1064                 case EbtUint8:
1065                     newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1066                     break;
1067                 case EbtInt16:
1068                     newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1069                     break;
1070                 case EbtUint16:
1071                     newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1072                     break;
1073                 case EbtInt64:
1074                     newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1075                     break;
1076                 case EbtUint64:
1077                     newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1078                     break;
1079                 default: assert(false && "Default missing");
1080                 }
1081                 break;
1082             case EOpMax:
1083                 switch(children[0]->getAsTyped()->getBasicType()) {
1084                 case EbtFloat16:
1085                 case EbtFloat:
1086                 case EbtDouble:
1087                     newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1088                     break;
1089                 case EbtInt:
1090                     newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1091                     break;
1092                 case EbtUint:
1093                     newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1094                     break;
1095                 case EbtInt8:
1096                     newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1097                     break;
1098                 case EbtUint8:
1099                     newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1100                     break;
1101                 case EbtInt16:
1102                     newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1103                     break;
1104                 case EbtUint16:
1105                     newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1106                     break;
1107                 case EbtInt64:
1108                     newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1109                     break;
1110                 case EbtUint64:
1111                     newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1112                     break;
1113                 default: assert(false && "Default missing");
1114                 }
1115                 break;
1116             case EOpClamp:
1117                 switch(children[0]->getAsTyped()->getBasicType()) {
1118                 case EbtFloat16:
1119                 case EbtFloat:
1120                 case EbtDouble:
1121                     newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
1122                                                                                                                childConstUnions[2][arg2comp].getDConst()));
1123                     break;
1124                 case EbtUint:
1125                     newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
1126                                                                                                                    childConstUnions[2][arg2comp].getUConst()));
1127                     break;
1128                 case EbtInt8:
1129                     newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
1130                                                                                                                    childConstUnions[2][arg2comp].getI8Const()));
1131                     break;
1132                 case EbtUint8:
1133                      newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
1134                                                                                                                    childConstUnions[2][arg2comp].getU8Const()));
1135                     break;
1136                 case EbtInt16:
1137                     newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
1138                                                                                                                    childConstUnions[2][arg2comp].getI16Const()));
1139                     break;
1140                 case EbtUint16:
1141                     newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
1142                                                                                                                    childConstUnions[2][arg2comp].getU16Const()));
1143                     break;
1144                 case EbtInt:
1145                     newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
1146                                                                                                                    childConstUnions[2][arg2comp].getIConst()));
1147                     break;
1148                 case EbtInt64:
1149                     newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
1150                                                                                                                        childConstUnions[2][arg2comp].getI64Const()));
1151                     break;
1152                 case EbtUint64:
1153                     newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
1154                                                                                                                        childConstUnions[2][arg2comp].getU64Const()));
1155                     break;
1156                 default: assert(false && "Default missing");
1157                 }
1158                 break;
1159             case EOpLessThan:
1160                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
1161                 break;
1162             case EOpGreaterThan:
1163                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
1164                 break;
1165             case EOpLessThanEqual:
1166                 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
1167                 break;
1168             case EOpGreaterThanEqual:
1169                 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
1170                 break;
1171             case EOpVectorEqual:
1172                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
1173                 break;
1174             case EOpVectorNotEqual:
1175                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
1176                 break;
1177             case EOpMix:
1178                 if (!children[0]->getAsTyped()->isFloatingDomain())
1179                     return aggrNode;
1180                 if (children[2]->getAsTyped()->getBasicType() == EbtBool) {
1181                     newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst()
1182                         ? childConstUnions[1][arg1comp].getDConst()
1183                         : childConstUnions[0][arg0comp].getDConst());
1184                 } else {
1185                     newConstArray[comp].setDConst(
1186                         childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
1187                         childConstUnions[1][arg1comp].getDConst() *        childConstUnions[2][arg2comp].getDConst());
1188                 }
1189                 break;
1190             case EOpStep:
1191                 newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
1192                 break;
1193             case EOpSmoothStep:
1194             {
1195                 double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
1196                            (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
1197                 if (t < 0.0)
1198                     t = 0.0;
1199                 if (t > 1.0)
1200                     t = 1.0;
1201                 newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
1202                 break;
1203             }
1204             default:
1205                 return aggrNode;
1206             }
1207         }
1208     } else {
1209         // Non-componentwise...
1210 
1211         int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1212         double dot;
1213 
1214         switch (aggrNode->getOp()) {
1215         case EOpDistance:
1216         {
1217             double sum = 0.0;
1218             for (int comp = 0; comp < numComps; ++comp) {
1219                 double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
1220                 sum += diff * diff;
1221             }
1222             newConstArray[0].setDConst(sqrt(sum));
1223             break;
1224         }
1225         case EOpDot:
1226             newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
1227             break;
1228         case EOpCross:
1229             newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
1230             newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
1231             newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
1232             break;
1233         case EOpFaceForward:
1234             // If dot(Nref, I) < 0 return N, otherwise return -N:  Arguments are (N, I, Nref).
1235             dot = childConstUnions[1].dot(childConstUnions[2]);
1236             for (int comp = 0; comp < numComps; ++comp) {
1237                 if (dot < 0.0)
1238                     newConstArray[comp] = childConstUnions[0][comp];
1239                 else
1240                     newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
1241             }
1242             break;
1243         case EOpReflect:
1244             // I - 2 * dot(N, I) * N:  Arguments are (I, N).
1245             dot = childConstUnions[0].dot(childConstUnions[1]);
1246             dot *= 2.0;
1247             for (int comp = 0; comp < numComps; ++comp)
1248                 newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
1249             break;
1250         case EOpRefract:
1251         {
1252             // Arguments are (I, N, eta).
1253             // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
1254             // if (k < 0.0)
1255             //     return dvec(0.0)
1256             // else
1257             //     return eta * I - (eta * dot(N, I) + sqrt(k)) * N
1258             dot = childConstUnions[0].dot(childConstUnions[1]);
1259             double eta = childConstUnions[2][0].getDConst();
1260             double k = 1.0 - eta * eta * (1.0 - dot * dot);
1261             if (k < 0.0) {
1262                 for (int comp = 0; comp < numComps; ++comp)
1263                     newConstArray[comp].setDConst(0.0);
1264             } else {
1265                 for (int comp = 0; comp < numComps; ++comp)
1266                     newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
1267             }
1268             break;
1269         }
1270         case EOpOuterProduct:
1271         {
1272             int numRows = numComps;
1273             int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
1274             for (int row = 0; row < numRows; ++row)
1275                 for (int col = 0; col < numCols; ++col)
1276                     newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
1277             break;
1278         }
1279         default:
1280             return aggrNode;
1281         }
1282     }
1283 
1284     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
1285     newNode->getWritableType().getQualifier().storage = EvqConst;
1286     newNode->setLoc(aggrNode->getLoc());
1287 
1288     return newNode;
1289 }
1290 
areAllChildConst(TIntermAggregate * aggrNode)1291 bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
1292 {
1293     bool allConstant = true;
1294 
1295     // check if all the child nodes are constants so that they can be inserted into
1296     // the parent node
1297     if (aggrNode) {
1298         TIntermSequence& childSequenceVector = aggrNode->getSequence();
1299         for (TIntermSequence::iterator p  = childSequenceVector.begin();
1300                                        p != childSequenceVector.end(); p++) {
1301             if (!(*p)->getAsTyped()->getAsConstantUnion())
1302                 return false;
1303         }
1304     }
1305 
1306     return allConstant;
1307 }
1308 
foldConstructor(TIntermAggregate * aggrNode)1309 TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
1310 {
1311     bool error = false;
1312 
1313     TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
1314     if (aggrNode->getSequence().size() == 1)
1315         error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
1316     else
1317         error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
1318 
1319     if (error)
1320         return aggrNode;
1321 
1322     return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
1323 }
1324 
1325 //
1326 // Constant folding of a bracket (array-style) dereference or struct-like dot
1327 // dereference.  Can handle anything except a multi-character swizzle, though
1328 // all swizzles may go to foldSwizzle().
1329 //
foldDereference(TIntermTyped * node,int index,const TSourceLoc & loc)1330 TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
1331 {
1332     TType dereferencedType(node->getType(), index);
1333     dereferencedType.getQualifier().storage = EvqConst;
1334     TIntermTyped* result = nullptr;
1335     int size = dereferencedType.computeNumComponents();
1336 
1337     // arrays, vectors, matrices, all use simple multiplicative math
1338     // while structures need to add up heterogeneous members
1339     int start;
1340     if (node->getType().isCoopMat())
1341         start = 0;
1342     else if (node->isArray() || ! node->isStruct())
1343         start = size * index;
1344     else {
1345         // it is a structure
1346         assert(node->isStruct());
1347         start = 0;
1348         for (int i = 0; i < index; ++i)
1349             start += (*node->getType().getStruct())[i].type->computeNumComponents();
1350     }
1351 
1352     result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
1353 
1354     if (result == nullptr)
1355         result = node;
1356     else
1357         result->setType(dereferencedType);
1358 
1359     return result;
1360 }
1361 
1362 //
1363 // Make a constant vector node or constant scalar node, representing a given
1364 // constant vector and constant swizzle into it.
1365 //
foldSwizzle(TIntermTyped * node,TSwizzleSelectors<TVectorSelector> & selectors,const TSourceLoc & loc)1366 TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
1367 {
1368     const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
1369     TConstUnionArray constArray(selectors.size());
1370 
1371     for (int i = 0; i < selectors.size(); i++)
1372         constArray[i] = unionArray[selectors[i]];
1373 
1374     TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
1375 
1376     if (result == nullptr)
1377         result = node;
1378     else
1379         result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
1380 
1381     return result;
1382 }
1383 
1384 } // end namespace glslang
1385