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