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