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 
isNan(double x)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 
isInf(double x)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 //
fold(TOperator op,const TIntermTyped * rightConstantNode) const101 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 //
fold(TOperator op,const TType & returnType) const400 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             case EbtInt:   newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
533             case EbtUint:  newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst())));  break;
534 #ifndef GLSLANG_WEB
535             case EbtInt8:  newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
536             case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const())));  break;
537             case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
538             case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const())));  break;
539             case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
540             case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const())));  break;
541 #endif
542             default:
543                 return nullptr;
544             }
545             break;
546         case EOpLogicalNot:
547         case EOpVectorLogicalNot:
548             switch (getType().getBasicType()) {
549             case EbtBool:  newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
550             default:
551                 return nullptr;
552             }
553             break;
554         case EOpBitwiseNot:
555             newConstArray[i] = ~unionArray[i];
556             break;
557         case EOpRadians:
558             newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
559             break;
560         case EOpDegrees:
561             newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
562             break;
563         case EOpSin:
564             newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
565             break;
566         case EOpCos:
567             newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
568             break;
569         case EOpTan:
570             newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
571             break;
572         case EOpAsin:
573             newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
574             break;
575         case EOpAcos:
576             newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
577             break;
578         case EOpAtan:
579             newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
580             break;
581 
582         case EOpDPdx:
583         case EOpDPdy:
584         case EOpFwidth:
585         case EOpDPdxFine:
586         case EOpDPdyFine:
587         case EOpFwidthFine:
588         case EOpDPdxCoarse:
589         case EOpDPdyCoarse:
590         case EOpFwidthCoarse:
591             // The derivatives are all mandated to create a constant 0.
592             newConstArray[i].setDConst(0.0);
593             break;
594 
595         case EOpExp:
596             newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
597             break;
598         case EOpLog:
599             newConstArray[i].setDConst(log(unionArray[i].getDConst()));
600             break;
601         case EOpExp2:
602             {
603                 const double inv_log2_e = 0.69314718055994530941723212145818;
604                 newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
605                 break;
606             }
607         case EOpLog2:
608             {
609                 const double log2_e = 1.4426950408889634073599246810019;
610                 newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
611                 break;
612             }
613         case EOpSqrt:
614             newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
615             break;
616         case EOpInverseSqrt:
617             newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
618             break;
619 
620         case EOpAbs:
621             if (unionArray[i].getType() == EbtDouble)
622                 newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
623             else if (unionArray[i].getType() == EbtInt)
624                 newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
625             else
626                 newConstArray[i] = unionArray[i];
627             break;
628         case EOpSign:
629             #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
630             if (unionArray[i].getType() == EbtDouble)
631                 newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
632             else
633                 newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
634             break;
635         case EOpFloor:
636             newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
637             break;
638         case EOpTrunc:
639             if (unionArray[i].getDConst() > 0)
640                 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
641             else
642                 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
643             break;
644         case EOpRound:
645             newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
646             break;
647         case EOpRoundEven:
648         {
649             double flr = floor(unionArray[i].getDConst());
650             bool even = flr / 2.0 == floor(flr / 2.0);
651             double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
652             newConstArray[i].setDConst(rounded);
653             break;
654         }
655         case EOpCeil:
656             newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
657             break;
658         case EOpFract:
659         {
660             double x = unionArray[i].getDConst();
661             newConstArray[i].setDConst(x - floor(x));
662             break;
663         }
664 
665         case EOpIsNan:
666         {
667             newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
668             break;
669         }
670         case EOpIsInf:
671         {
672             newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
673             break;
674         }
675 
676         case EOpConvIntToBool:
677             newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
678         case EOpConvUintToBool:
679             newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
680         case EOpConvBoolToInt:
681             newConstArray[i].setIConst(unionArray[i].getBConst()); break;
682         case EOpConvBoolToUint:
683             newConstArray[i].setUConst(unionArray[i].getBConst()); break;
684         case EOpConvIntToUint:
685             newConstArray[i].setUConst(unionArray[i].getIConst()); break;
686         case EOpConvUintToInt:
687             newConstArray[i].setIConst(unionArray[i].getUConst()); break;
688 
689         case EOpConvFloatToBool:
690         case EOpConvDoubleToBool:
691             newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
692 
693         case EOpConvBoolToFloat:
694         case EOpConvBoolToDouble:
695             newConstArray[i].setDConst(unionArray[i].getBConst()); break;
696 
697         case EOpConvIntToFloat:
698         case EOpConvIntToDouble:
699             newConstArray[i].setDConst(unionArray[i].getIConst()); break;
700 
701         case EOpConvUintToFloat:
702         case EOpConvUintToDouble:
703             newConstArray[i].setDConst(unionArray[i].getUConst()); break;
704 
705         case EOpConvDoubleToFloat:
706         case EOpConvFloatToDouble:
707             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
708 
709         case EOpConvFloatToUint:
710         case EOpConvDoubleToUint:
711             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
712 
713         case EOpConvFloatToInt:
714         case EOpConvDoubleToInt:
715             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
716 
717 #ifndef GLSLANG_WEB
718         case EOpConvInt8ToBool:
719             newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
720         case EOpConvUint8ToBool:
721             newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
722         case EOpConvInt16ToBool:
723             newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
724         case EOpConvUint16ToBool:
725             newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
726         case EOpConvInt64ToBool:
727             newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
728         case EOpConvUint64ToBool:
729             newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
730         case EOpConvFloat16ToBool:
731             newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
732 
733         case EOpConvBoolToInt8:
734             newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
735         case EOpConvBoolToUint8:
736             newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
737         case EOpConvBoolToInt16:
738             newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
739         case EOpConvBoolToUint16:
740             newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
741         case EOpConvBoolToInt64:
742             newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
743         case EOpConvBoolToUint64:
744             newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
745         case EOpConvBoolToFloat16:
746             newConstArray[i].setDConst(unionArray[i].getBConst()); break;
747 
748         case EOpConvInt8ToInt16:
749             newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
750         case EOpConvInt8ToInt:
751             newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
752         case EOpConvInt8ToInt64:
753             newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
754         case EOpConvInt8ToUint8:
755             newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
756         case EOpConvInt8ToUint16:
757             newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
758         case EOpConvInt8ToUint:
759             newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
760         case EOpConvInt8ToUint64:
761             newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
762         case EOpConvUint8ToInt8:
763             newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
764         case EOpConvUint8ToInt16:
765             newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
766         case EOpConvUint8ToInt:
767             newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
768         case EOpConvUint8ToInt64:
769             newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
770         case EOpConvUint8ToUint16:
771             newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
772         case EOpConvUint8ToUint:
773             newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
774         case EOpConvUint8ToUint64:
775             newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
776         case EOpConvInt8ToFloat16:
777             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
778         case EOpConvInt8ToFloat:
779             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
780         case EOpConvInt8ToDouble:
781             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
782         case EOpConvUint8ToFloat16:
783             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
784         case EOpConvUint8ToFloat:
785             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
786         case EOpConvUint8ToDouble:
787             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
788 
789         case EOpConvInt16ToInt8:
790             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
791         case EOpConvInt16ToInt:
792             newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
793         case EOpConvInt16ToInt64:
794             newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
795         case EOpConvInt16ToUint8:
796             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
797         case EOpConvInt16ToUint16:
798             newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
799         case EOpConvInt16ToUint:
800             newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
801         case EOpConvInt16ToUint64:
802             newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
803         case EOpConvUint16ToInt8:
804             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
805         case EOpConvUint16ToInt16:
806             newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
807         case EOpConvUint16ToInt:
808             newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
809         case EOpConvUint16ToInt64:
810             newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
811         case EOpConvUint16ToUint8:
812             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
813 
814         case EOpConvUint16ToUint:
815             newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
816         case EOpConvUint16ToUint64:
817             newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
818         case EOpConvInt16ToFloat16:
819             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
820         case EOpConvInt16ToFloat:
821             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
822         case EOpConvInt16ToDouble:
823             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
824         case EOpConvUint16ToFloat16:
825             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
826         case EOpConvUint16ToFloat:
827             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
828         case EOpConvUint16ToDouble:
829             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
830 
831         case EOpConvIntToInt8:
832             newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
833         case EOpConvIntToInt16:
834             newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
835         case EOpConvIntToInt64:
836             newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
837         case EOpConvIntToUint8:
838             newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
839         case EOpConvIntToUint16:
840             newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
841         case EOpConvIntToUint64:
842             newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
843 
844         case EOpConvUintToInt8:
845             newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
846         case EOpConvUintToInt16:
847             newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
848         case EOpConvUintToInt64:
849             newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
850         case EOpConvUintToUint8:
851             newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
852         case EOpConvUintToUint16:
853             newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
854         case EOpConvUintToUint64:
855             newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
856         case EOpConvIntToFloat16:
857             newConstArray[i].setDConst(unionArray[i].getIConst()); break;
858         case EOpConvUintToFloat16:
859             newConstArray[i].setDConst(unionArray[i].getUConst()); break;
860         case EOpConvInt64ToInt8:
861             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
862         case EOpConvInt64ToInt16:
863             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
864         case EOpConvInt64ToInt:
865             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
866         case EOpConvInt64ToUint8:
867             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
868         case EOpConvInt64ToUint16:
869             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
870         case EOpConvInt64ToUint:
871             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
872         case EOpConvInt64ToUint64:
873             newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
874         case EOpConvUint64ToInt8:
875             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
876         case EOpConvUint64ToInt16:
877             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
878         case EOpConvUint64ToInt:
879             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
880         case EOpConvUint64ToInt64:
881             newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
882         case EOpConvUint64ToUint8:
883             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
884         case EOpConvUint64ToUint16:
885             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
886         case EOpConvUint64ToUint:
887             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
888         case EOpConvInt64ToFloat16:
889             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
890         case EOpConvInt64ToFloat:
891             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
892         case EOpConvInt64ToDouble:
893             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
894         case EOpConvUint64ToFloat16:
895             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
896         case EOpConvUint64ToFloat:
897             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
898         case EOpConvUint64ToDouble:
899             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
900         case EOpConvFloat16ToInt8:
901             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
902         case EOpConvFloat16ToInt16:
903             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
904         case EOpConvFloat16ToInt:
905             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
906         case EOpConvFloat16ToInt64:
907             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
908         case EOpConvFloat16ToUint8:
909             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
910         case EOpConvFloat16ToUint16:
911             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
912         case EOpConvFloat16ToUint:
913             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
914         case EOpConvFloat16ToUint64:
915             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
916         case EOpConvFloat16ToFloat:
917             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
918         case EOpConvFloat16ToDouble:
919             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
920         case EOpConvFloatToInt8:
921             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
922         case EOpConvFloatToInt16:
923             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
924         case EOpConvFloatToInt64:
925             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
926         case EOpConvFloatToUint8:
927             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
928         case EOpConvFloatToUint16:
929             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
930         case EOpConvFloatToUint64:
931             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
932         case EOpConvFloatToFloat16:
933             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
934         case EOpConvDoubleToInt8:
935             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
936         case EOpConvDoubleToInt16:
937             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
938         case EOpConvDoubleToInt64:
939             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
940         case EOpConvDoubleToUint8:
941             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
942         case EOpConvDoubleToUint16:
943             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
944         case EOpConvDoubleToUint64:
945             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
946         case EOpConvDoubleToFloat16:
947             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
948         case EOpConvPtrToUint64:
949         case EOpConvUint64ToPtr:
950         case EOpConstructReference:
951             newConstArray[i].setU64Const(unionArray[i].getU64Const()); break;
952 #endif
953 
954         // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
955 
956         case EOpSinh:
957         case EOpCosh:
958         case EOpTanh:
959         case EOpAsinh:
960         case EOpAcosh:
961         case EOpAtanh:
962 
963         case EOpFloatBitsToInt:
964         case EOpFloatBitsToUint:
965         case EOpIntBitsToFloat:
966         case EOpUintBitsToFloat:
967         case EOpDoubleBitsToInt64:
968         case EOpDoubleBitsToUint64:
969         case EOpInt64BitsToDouble:
970         case EOpUint64BitsToDouble:
971         case EOpFloat16BitsToInt16:
972         case EOpFloat16BitsToUint16:
973         case EOpInt16BitsToFloat16:
974         case EOpUint16BitsToFloat16:
975         default:
976             return nullptr;
977         }
978     }
979 
980     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
981     newNode->getWritableType().getQualifier().storage = EvqConst;
982     newNode->setLoc(getLoc());
983 
984     return newNode;
985 }
986 
987 //
988 // Do constant folding for an aggregate node that has all its children
989 // as constants and an operator that requires constant folding.
990 //
fold(TIntermAggregate * aggrNode)991 TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
992 {
993     if (aggrNode == nullptr)
994         return aggrNode;
995 
996     if (! areAllChildConst(aggrNode))
997         return aggrNode;
998 
999     if (aggrNode->isConstructor())
1000         return foldConstructor(aggrNode);
1001 
1002     TIntermSequence& children = aggrNode->getSequence();
1003 
1004     // First, see if this is an operation to constant fold, kick out if not,
1005     // see what size the result is if so.
1006 
1007     bool componentwise = false;  // will also say componentwise if a scalar argument gets repeated to make per-component results
1008     int objectSize;
1009     switch (aggrNode->getOp()) {
1010     case EOpAtan:
1011     case EOpPow:
1012     case EOpMin:
1013     case EOpMax:
1014     case EOpMix:
1015     case EOpMod:
1016     case EOpClamp:
1017     case EOpLessThan:
1018     case EOpGreaterThan:
1019     case EOpLessThanEqual:
1020     case EOpGreaterThanEqual:
1021     case EOpVectorEqual:
1022     case EOpVectorNotEqual:
1023         componentwise = true;
1024         objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1025         break;
1026     case EOpCross:
1027     case EOpReflect:
1028     case EOpRefract:
1029     case EOpFaceForward:
1030         objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1031         break;
1032     case EOpDistance:
1033     case EOpDot:
1034         objectSize = 1;
1035         break;
1036     case EOpOuterProduct:
1037         objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
1038                      children[1]->getAsTyped()->getType().getVectorSize();
1039         break;
1040     case EOpStep:
1041         componentwise = true;
1042         objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1043                               children[1]->getAsTyped()->getType().getVectorSize());
1044         break;
1045     case EOpSmoothStep:
1046         componentwise = true;
1047         objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1048                               children[2]->getAsTyped()->getType().getVectorSize());
1049         break;
1050     default:
1051         return aggrNode;
1052     }
1053     TConstUnionArray newConstArray(objectSize);
1054 
1055     TVector<TConstUnionArray> childConstUnions;
1056     for (unsigned int arg = 0; arg < children.size(); ++arg)
1057         childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
1058 
1059     if (componentwise) {
1060         for (int comp = 0; comp < objectSize; comp++) {
1061 
1062             // some arguments are scalars instead of matching vectors; simulate a smear
1063             int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
1064             int arg1comp = 0;
1065             if (children.size() > 1)
1066                 arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
1067             int arg2comp = 0;
1068             if (children.size() > 2)
1069                 arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
1070 
1071             switch (aggrNode->getOp()) {
1072             case EOpAtan:
1073                 newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1074                 break;
1075             case EOpPow:
1076                 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1077                 break;
1078             case EOpMod:
1079             {
1080                 double arg0 = childConstUnions[0][arg0comp].getDConst();
1081                 double arg1 = childConstUnions[1][arg1comp].getDConst();
1082                 double result = arg0 - arg1 * floor(arg0 / arg1);
1083                 newConstArray[comp].setDConst(result);
1084                 break;
1085             }
1086             case EOpMin:
1087                 switch(children[0]->getAsTyped()->getBasicType()) {
1088                 case EbtFloat16:
1089                 case EbtFloat:
1090                 case EbtDouble:
1091                     newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1092                     break;
1093                 case EbtInt:
1094                     newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1095                     break;
1096                 case EbtUint:
1097                     newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1098                     break;
1099 #ifndef GLSLANG_WEB
1100                 case EbtInt8:
1101                     newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1102                     break;
1103                 case EbtUint8:
1104                     newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1105                     break;
1106                 case EbtInt16:
1107                     newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1108                     break;
1109                 case EbtUint16:
1110                     newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1111                     break;
1112                 case EbtInt64:
1113                     newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1114                     break;
1115                 case EbtUint64:
1116                     newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1117                     break;
1118 #endif
1119                 default: assert(false && "Default missing");
1120                 }
1121                 break;
1122             case EOpMax:
1123                 switch(children[0]->getAsTyped()->getBasicType()) {
1124                 case EbtFloat16:
1125                 case EbtFloat:
1126                 case EbtDouble:
1127                     newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1128                     break;
1129                 case EbtInt:
1130                     newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1131                     break;
1132                 case EbtUint:
1133                     newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1134                     break;
1135 #ifndef GLSLANG_WEB
1136                 case EbtInt8:
1137                     newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1138                     break;
1139                 case EbtUint8:
1140                     newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1141                     break;
1142                 case EbtInt16:
1143                     newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1144                     break;
1145                 case EbtUint16:
1146                     newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1147                     break;
1148                 case EbtInt64:
1149                     newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1150                     break;
1151                 case EbtUint64:
1152                     newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1153                     break;
1154 #endif
1155                 default: assert(false && "Default missing");
1156                 }
1157                 break;
1158             case EOpClamp:
1159                 switch(children[0]->getAsTyped()->getBasicType()) {
1160                 case EbtFloat16:
1161                 case EbtFloat:
1162                 case EbtDouble:
1163                     newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
1164                                                                                                                childConstUnions[2][arg2comp].getDConst()));
1165                     break;
1166                 case EbtUint:
1167                     newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
1168                                                                                                                    childConstUnions[2][arg2comp].getUConst()));
1169                     break;
1170 #ifndef GLSLANG_WEB
1171                 case EbtInt8:
1172                     newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
1173                                                                                                                    childConstUnions[2][arg2comp].getI8Const()));
1174                     break;
1175                 case EbtUint8:
1176                      newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
1177                                                                                                                    childConstUnions[2][arg2comp].getU8Const()));
1178                     break;
1179                 case EbtInt16:
1180                     newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
1181                                                                                                                    childConstUnions[2][arg2comp].getI16Const()));
1182                     break;
1183                 case EbtUint16:
1184                     newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
1185                                                                                                                    childConstUnions[2][arg2comp].getU16Const()));
1186                     break;
1187                 case EbtInt:
1188                     newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
1189                                                                                                                    childConstUnions[2][arg2comp].getIConst()));
1190                     break;
1191                 case EbtInt64:
1192                     newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
1193                                                                                                                        childConstUnions[2][arg2comp].getI64Const()));
1194                     break;
1195                 case EbtUint64:
1196                     newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
1197                                                                                                                        childConstUnions[2][arg2comp].getU64Const()));
1198                     break;
1199 #endif
1200                 default: assert(false && "Default missing");
1201                 }
1202                 break;
1203             case EOpLessThan:
1204                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
1205                 break;
1206             case EOpGreaterThan:
1207                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
1208                 break;
1209             case EOpLessThanEqual:
1210                 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
1211                 break;
1212             case EOpGreaterThanEqual:
1213                 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
1214                 break;
1215             case EOpVectorEqual:
1216                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
1217                 break;
1218             case EOpVectorNotEqual:
1219                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
1220                 break;
1221             case EOpMix:
1222                 if (!children[0]->getAsTyped()->isFloatingDomain())
1223                     return aggrNode;
1224                 if (children[2]->getAsTyped()->getBasicType() == EbtBool) {
1225                     newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst()
1226                         ? childConstUnions[1][arg1comp].getDConst()
1227                         : childConstUnions[0][arg0comp].getDConst());
1228                 } else {
1229                     newConstArray[comp].setDConst(
1230                         childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
1231                         childConstUnions[1][arg1comp].getDConst() *        childConstUnions[2][arg2comp].getDConst());
1232                 }
1233                 break;
1234             case EOpStep:
1235                 newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
1236                 break;
1237             case EOpSmoothStep:
1238             {
1239                 double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
1240                            (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
1241                 if (t < 0.0)
1242                     t = 0.0;
1243                 if (t > 1.0)
1244                     t = 1.0;
1245                 newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
1246                 break;
1247             }
1248             default:
1249                 return aggrNode;
1250             }
1251         }
1252     } else {
1253         // Non-componentwise...
1254 
1255         int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1256         double dot;
1257 
1258         switch (aggrNode->getOp()) {
1259         case EOpDistance:
1260         {
1261             double sum = 0.0;
1262             for (int comp = 0; comp < numComps; ++comp) {
1263                 double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
1264                 sum += diff * diff;
1265             }
1266             newConstArray[0].setDConst(sqrt(sum));
1267             break;
1268         }
1269         case EOpDot:
1270             newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
1271             break;
1272         case EOpCross:
1273             newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
1274             newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
1275             newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
1276             break;
1277         case EOpFaceForward:
1278             // If dot(Nref, I) < 0 return N, otherwise return -N:  Arguments are (N, I, Nref).
1279             dot = childConstUnions[1].dot(childConstUnions[2]);
1280             for (int comp = 0; comp < numComps; ++comp) {
1281                 if (dot < 0.0)
1282                     newConstArray[comp] = childConstUnions[0][comp];
1283                 else
1284                     newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
1285             }
1286             break;
1287         case EOpReflect:
1288             // I - 2 * dot(N, I) * N:  Arguments are (I, N).
1289             dot = childConstUnions[0].dot(childConstUnions[1]);
1290             dot *= 2.0;
1291             for (int comp = 0; comp < numComps; ++comp)
1292                 newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
1293             break;
1294         case EOpRefract:
1295         {
1296             // Arguments are (I, N, eta).
1297             // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
1298             // if (k < 0.0)
1299             //     return dvec(0.0)
1300             // else
1301             //     return eta * I - (eta * dot(N, I) + sqrt(k)) * N
1302             dot = childConstUnions[0].dot(childConstUnions[1]);
1303             double eta = childConstUnions[2][0].getDConst();
1304             double k = 1.0 - eta * eta * (1.0 - dot * dot);
1305             if (k < 0.0) {
1306                 for (int comp = 0; comp < numComps; ++comp)
1307                     newConstArray[comp].setDConst(0.0);
1308             } else {
1309                 for (int comp = 0; comp < numComps; ++comp)
1310                     newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
1311             }
1312             break;
1313         }
1314         case EOpOuterProduct:
1315         {
1316             int numRows = numComps;
1317             int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
1318             for (int row = 0; row < numRows; ++row)
1319                 for (int col = 0; col < numCols; ++col)
1320                     newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
1321             break;
1322         }
1323         default:
1324             return aggrNode;
1325         }
1326     }
1327 
1328     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
1329     newNode->getWritableType().getQualifier().storage = EvqConst;
1330     newNode->setLoc(aggrNode->getLoc());
1331 
1332     return newNode;
1333 }
1334 
areAllChildConst(TIntermAggregate * aggrNode)1335 bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
1336 {
1337     bool allConstant = true;
1338 
1339     // check if all the child nodes are constants so that they can be inserted into
1340     // the parent node
1341     if (aggrNode) {
1342         TIntermSequence& childSequenceVector = aggrNode->getSequence();
1343         for (TIntermSequence::iterator p  = childSequenceVector.begin();
1344                                        p != childSequenceVector.end(); p++) {
1345             if (!(*p)->getAsTyped()->getAsConstantUnion())
1346                 return false;
1347         }
1348     }
1349 
1350     return allConstant;
1351 }
1352 
foldConstructor(TIntermAggregate * aggrNode)1353 TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
1354 {
1355     bool error = false;
1356 
1357     TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
1358     if (aggrNode->getSequence().size() == 1)
1359         error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
1360     else
1361         error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
1362 
1363     if (error)
1364         return aggrNode;
1365 
1366     return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
1367 }
1368 
1369 //
1370 // Constant folding of a bracket (array-style) dereference or struct-like dot
1371 // dereference.  Can handle anything except a multi-character swizzle, though
1372 // all swizzles may go to foldSwizzle().
1373 //
foldDereference(TIntermTyped * node,int index,const TSourceLoc & loc)1374 TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
1375 {
1376     TType dereferencedType(node->getType(), index);
1377     dereferencedType.getQualifier().storage = EvqConst;
1378     TIntermTyped* result = 0;
1379     int size = dereferencedType.computeNumComponents();
1380 
1381     // arrays, vectors, matrices, all use simple multiplicative math
1382     // while structures need to add up heterogeneous members
1383     int start;
1384     if (node->getType().isCoopMat())
1385         start = 0;
1386     else if (node->isArray() || ! node->isStruct())
1387         start = size * index;
1388     else {
1389         // it is a structure
1390         assert(node->isStruct());
1391         start = 0;
1392         for (int i = 0; i < index; ++i)
1393             start += (*node->getType().getStruct())[i].type->computeNumComponents();
1394     }
1395 
1396     result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
1397 
1398     if (result == 0)
1399         result = node;
1400     else
1401         result->setType(dereferencedType);
1402 
1403     return result;
1404 }
1405 
1406 //
1407 // Make a constant vector node or constant scalar node, representing a given
1408 // constant vector and constant swizzle into it.
1409 //
foldSwizzle(TIntermTyped * node,TSwizzleSelectors<TVectorSelector> & selectors,const TSourceLoc & loc)1410 TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
1411 {
1412     const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
1413     TConstUnionArray constArray(selectors.size());
1414 
1415     for (int i = 0; i < selectors.size(); i++)
1416         constArray[i] = unionArray[selectors[i]];
1417 
1418     TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
1419 
1420     if (result == 0)
1421         result = node;
1422     else
1423         result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
1424 
1425     return result;
1426 }
1427 
1428 } // end namespace glslang
1429