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