• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ConstantUnion: Constant folding helper class.
7 
8 #include "compiler/translator/ConstantUnion.h"
9 
10 #include "common/mathutil.h"
11 #include "compiler/translator/Diagnostics.h"
12 #include "compiler/translator/util.h"
13 
14 namespace sh
15 {
16 
17 namespace
18 {
19 
CheckedSum(float lhs,float rhs,TDiagnostics * diag,const TSourceLoc & line)20 float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
21 {
22     float result = lhs + rhs;
23     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
24     {
25         diag->warning(line, "Constant folded undefined addition generated NaN", "+");
26     }
27     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
28     {
29         diag->warning(line, "Constant folded addition overflowed to infinity", "+");
30     }
31     return result;
32 }
33 
CheckedDiff(float lhs,float rhs,TDiagnostics * diag,const TSourceLoc & line)34 float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
35 {
36     float result = lhs - rhs;
37     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
38     {
39         diag->warning(line, "Constant folded undefined subtraction generated NaN", "-");
40     }
41     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
42     {
43         diag->warning(line, "Constant folded subtraction overflowed to infinity", "-");
44     }
45     return result;
46 }
47 
CheckedMul(float lhs,float rhs,TDiagnostics * diag,const TSourceLoc & line)48 float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
49 {
50     float result = lhs * rhs;
51     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
52     {
53         diag->warning(line, "Constant folded undefined multiplication generated NaN", "*");
54     }
55     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
56     {
57         diag->warning(line, "Constant folded multiplication overflowed to infinity", "*");
58     }
59     return result;
60 }
61 
IsValidShiftOffset(const TConstantUnion & rhs)62 bool IsValidShiftOffset(const TConstantUnion &rhs)
63 {
64     return (rhs.getType() == EbtInt && (rhs.getIConst() >= 0 && rhs.getIConst() <= 31)) ||
65            (rhs.getType() == EbtUInt && rhs.getUConst() <= 31u);
66 }
67 
68 }  // anonymous namespace
69 
TConstantUnion()70 TConstantUnion::TConstantUnion()
71 {
72     iConst = 0;
73     type   = EbtVoid;
74 }
75 
getIConst() const76 int TConstantUnion::getIConst() const
77 {
78     ASSERT(type == EbtInt);
79     return iConst;
80 }
81 
getUConst() const82 unsigned int TConstantUnion::getUConst() const
83 {
84     ASSERT(type == EbtUInt);
85     return uConst;
86 }
87 
getFConst() const88 float TConstantUnion::getFConst() const
89 {
90     switch (type)
91     {
92         case EbtInt:
93             return static_cast<float>(iConst);
94         case EbtUInt:
95             return static_cast<float>(uConst);
96         default:
97             ASSERT(type == EbtFloat);
98             return fConst;
99     }
100 }
101 
getBConst() const102 bool TConstantUnion::getBConst() const
103 {
104     ASSERT(type == EbtBool);
105     return bConst;
106 }
107 
isZero() const108 bool TConstantUnion::isZero() const
109 {
110     switch (type)
111     {
112         case EbtInt:
113             return getIConst() == 0;
114         case EbtUInt:
115             return getUConst() == 0;
116         case EbtFloat:
117             return getFConst() == 0.0f;
118         case EbtBool:
119             return getBConst() == false;
120         default:
121             return false;
122     }
123 }
124 
getYuvCscStandardEXTConst() const125 TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const
126 {
127     ASSERT(type == EbtYuvCscStandardEXT);
128     return yuvCscStandardEXTConst;
129 }
130 
cast(TBasicType newType,const TConstantUnion & constant)131 bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
132 {
133     switch (newType)
134     {
135         case EbtFloat:
136             switch (constant.type)
137             {
138                 case EbtInt:
139                     setFConst(static_cast<float>(constant.getIConst()));
140                     break;
141                 case EbtUInt:
142                     setFConst(static_cast<float>(constant.getUConst()));
143                     break;
144                 case EbtBool:
145                     setFConst(static_cast<float>(constant.getBConst()));
146                     break;
147                 case EbtFloat:
148                     setFConst(static_cast<float>(constant.getFConst()));
149                     break;
150                 default:
151                     return false;
152             }
153             break;
154         case EbtInt:
155             switch (constant.type)
156             {
157                 case EbtInt:
158                     setIConst(static_cast<int>(constant.getIConst()));
159                     break;
160                 case EbtUInt:
161                     setIConst(static_cast<int>(constant.getUConst()));
162                     break;
163                 case EbtBool:
164                     setIConst(static_cast<int>(constant.getBConst()));
165                     break;
166                 case EbtFloat:
167                     setIConst(static_cast<int>(constant.getFConst()));
168                     break;
169                 default:
170                     return false;
171             }
172             break;
173         case EbtUInt:
174             switch (constant.type)
175             {
176                 case EbtInt:
177                     setUConst(static_cast<unsigned int>(constant.getIConst()));
178                     break;
179                 case EbtUInt:
180                     setUConst(static_cast<unsigned int>(constant.getUConst()));
181                     break;
182                 case EbtBool:
183                     setUConst(static_cast<unsigned int>(constant.getBConst()));
184                     break;
185                 case EbtFloat:
186                     if (constant.getFConst() < 0.0f)
187                     {
188                         // Avoid undefined behavior in C++ by first casting to signed int.
189                         setUConst(
190                             static_cast<unsigned int>(static_cast<int>(constant.getFConst())));
191                     }
192                     else
193                     {
194                         setUConst(static_cast<unsigned int>(constant.getFConst()));
195                     }
196                     break;
197                 default:
198                     return false;
199             }
200             break;
201         case EbtBool:
202             switch (constant.type)
203             {
204                 case EbtInt:
205                     setBConst(constant.getIConst() != 0);
206                     break;
207                 case EbtUInt:
208                     setBConst(constant.getUConst() != 0);
209                     break;
210                 case EbtBool:
211                     setBConst(constant.getBConst());
212                     break;
213                 case EbtFloat:
214                     setBConst(constant.getFConst() != 0.0f);
215                     break;
216                 default:
217                     return false;
218             }
219             break;
220         case EbtStruct:  // Struct fields don't get cast
221             switch (constant.type)
222             {
223                 case EbtInt:
224                     setIConst(constant.getIConst());
225                     break;
226                 case EbtUInt:
227                     setUConst(constant.getUConst());
228                     break;
229                 case EbtBool:
230                     setBConst(constant.getBConst());
231                     break;
232                 case EbtFloat:
233                     setFConst(constant.getFConst());
234                     break;
235                 default:
236                     return false;
237             }
238             break;
239         default:
240             return false;
241     }
242 
243     return true;
244 }
245 
operator ==(const int i) const246 bool TConstantUnion::operator==(const int i) const
247 {
248     switch (type)
249     {
250         case EbtFloat:
251             return static_cast<float>(i) == fConst;
252         default:
253             return i == iConst;
254     }
255 }
256 
operator ==(const unsigned int u) const257 bool TConstantUnion::operator==(const unsigned int u) const
258 {
259     switch (type)
260     {
261         case EbtFloat:
262             return static_cast<float>(u) == fConst;
263         default:
264             return u == uConst;
265     }
266 }
267 
operator ==(const float f) const268 bool TConstantUnion::operator==(const float f) const
269 {
270     switch (type)
271     {
272         case EbtInt:
273             return f == static_cast<float>(iConst);
274         case EbtUInt:
275             return f == static_cast<float>(uConst);
276         default:
277             return f == fConst;
278     }
279 }
280 
operator ==(const bool b) const281 bool TConstantUnion::operator==(const bool b) const
282 {
283     return b == bConst;
284 }
285 
operator ==(const TYuvCscStandardEXT s) const286 bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const
287 {
288     return s == yuvCscStandardEXTConst;
289 }
290 
operator ==(const TConstantUnion & constant) const291 bool TConstantUnion::operator==(const TConstantUnion &constant) const
292 {
293     ImplicitTypeConversion conversion = GetConversion(constant.type, type);
294     if (conversion == ImplicitTypeConversion::Same)
295     {
296         switch (type)
297         {
298             case EbtInt:
299                 return constant.iConst == iConst;
300             case EbtUInt:
301                 return constant.uConst == uConst;
302             case EbtFloat:
303                 return constant.fConst == fConst;
304             case EbtBool:
305                 return constant.bConst == bConst;
306             case EbtYuvCscStandardEXT:
307                 return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst;
308             default:
309                 return false;
310         }
311     }
312     else if (conversion == ImplicitTypeConversion::Invalid)
313     {
314         return false;
315     }
316     else
317     {
318         return constant.getFConst() == getFConst();
319     }
320 }
321 
operator !=(const int i) const322 bool TConstantUnion::operator!=(const int i) const
323 {
324     return !operator==(i);
325 }
326 
operator !=(const unsigned int u) const327 bool TConstantUnion::operator!=(const unsigned int u) const
328 {
329     return !operator==(u);
330 }
331 
operator !=(const float f) const332 bool TConstantUnion::operator!=(const float f) const
333 {
334     return !operator==(f);
335 }
336 
operator !=(const bool b) const337 bool TConstantUnion::operator!=(const bool b) const
338 {
339     return !operator==(b);
340 }
341 
operator !=(const TYuvCscStandardEXT s) const342 bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const
343 {
344     return !operator==(s);
345 }
346 
operator !=(const TConstantUnion & constant) const347 bool TConstantUnion::operator!=(const TConstantUnion &constant) const
348 {
349     return !operator==(constant);
350 }
351 
operator >(const TConstantUnion & constant) const352 bool TConstantUnion::operator>(const TConstantUnion &constant) const
353 {
354 
355     ImplicitTypeConversion conversion = GetConversion(constant.type, type);
356     if (conversion == ImplicitTypeConversion::Same)
357     {
358         switch (type)
359         {
360             case EbtInt:
361                 return iConst > constant.iConst;
362             case EbtUInt:
363                 return uConst > constant.uConst;
364             case EbtFloat:
365                 return fConst > constant.fConst;
366             default:
367                 return false;  // Invalid operation, handled at semantic analysis
368         }
369     }
370     else
371     {
372         ASSERT(conversion != ImplicitTypeConversion::Invalid);
373         return getFConst() > constant.getFConst();
374     }
375 }
376 
operator <(const TConstantUnion & constant) const377 bool TConstantUnion::operator<(const TConstantUnion &constant) const
378 {
379     ImplicitTypeConversion conversion = GetConversion(constant.type, type);
380     if (conversion == ImplicitTypeConversion::Same)
381     {
382         switch (type)
383         {
384             case EbtInt:
385                 return iConst < constant.iConst;
386             case EbtUInt:
387                 return uConst < constant.uConst;
388             case EbtFloat:
389                 return fConst < constant.fConst;
390             default:
391                 return false;  // Invalid operation, handled at semantic analysis
392         }
393     }
394     else
395     {
396         ASSERT(conversion != ImplicitTypeConversion::Invalid);
397         return getFConst() < constant.getFConst();
398     }
399 }
400 
401 // static
add(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)402 TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
403                                    const TConstantUnion &rhs,
404                                    TDiagnostics *diag,
405                                    const TSourceLoc &line)
406 {
407     TConstantUnion returnValue;
408 
409     ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type);
410     if (conversion == ImplicitTypeConversion::Same)
411     {
412         switch (lhs.type)
413         {
414             case EbtInt:
415                 returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
416                 break;
417             case EbtUInt:
418                 returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
419                 break;
420             case EbtFloat:
421                 returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line));
422                 break;
423             default:
424                 UNREACHABLE();
425         }
426     }
427     else
428     {
429         ASSERT(conversion != ImplicitTypeConversion::Invalid);
430         returnValue.setFConst(CheckedSum(lhs.getFConst(), rhs.getFConst(), diag, line));
431     }
432 
433     return returnValue;
434 }
435 
436 // static
sub(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)437 TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
438                                    const TConstantUnion &rhs,
439                                    TDiagnostics *diag,
440                                    const TSourceLoc &line)
441 {
442     TConstantUnion returnValue;
443 
444     ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type);
445     if (conversion == ImplicitTypeConversion::Same)
446     {
447         switch (lhs.type)
448         {
449             case EbtInt:
450                 returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
451                 break;
452             case EbtUInt:
453                 returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
454                 break;
455             case EbtFloat:
456                 returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line));
457                 break;
458             default:
459                 UNREACHABLE();
460         }
461     }
462     else
463     {
464         ASSERT(conversion != ImplicitTypeConversion::Invalid);
465         returnValue.setFConst(CheckedDiff(lhs.getFConst(), rhs.getFConst(), diag, line));
466     }
467 
468     return returnValue;
469 }
470 
471 // static
mul(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)472 TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
473                                    const TConstantUnion &rhs,
474                                    TDiagnostics *diag,
475                                    const TSourceLoc &line)
476 {
477     TConstantUnion returnValue;
478 
479     ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type);
480     if (conversion == ImplicitTypeConversion::Same)
481     {
482         switch (lhs.type)
483         {
484             case EbtInt:
485                 returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst));
486                 break;
487             case EbtUInt:
488                 // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely
489                 // on that to implement wrapping multiplication.
490                 returnValue.setUConst(lhs.uConst * rhs.uConst);
491                 break;
492             case EbtFloat:
493                 returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line));
494                 break;
495             default:
496                 UNREACHABLE();
497         }
498     }
499     else
500     {
501         ASSERT(conversion != ImplicitTypeConversion::Invalid);
502         returnValue.setFConst(CheckedMul(lhs.getFConst(), rhs.getFConst(), diag, line));
503     }
504 
505     return returnValue;
506 }
507 
operator %(const TConstantUnion & constant) const508 TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
509 {
510     TConstantUnion returnValue;
511     ASSERT(type == constant.type);
512     switch (type)
513     {
514         case EbtInt:
515             returnValue.setIConst(iConst % constant.iConst);
516             break;
517         case EbtUInt:
518             returnValue.setUConst(uConst % constant.uConst);
519             break;
520         default:
521             UNREACHABLE();
522     }
523 
524     return returnValue;
525 }
526 
527 // static
rshift(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)528 TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs,
529                                       const TConstantUnion &rhs,
530                                       TDiagnostics *diag,
531                                       const TSourceLoc &line)
532 {
533     TConstantUnion returnValue;
534     ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
535     ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
536     if (!IsValidShiftOffset(rhs))
537     {
538         diag->warning(line, "Undefined shift (operand out of range)", ">>");
539         switch (lhs.type)
540         {
541             case EbtInt:
542                 returnValue.setIConst(0);
543                 break;
544             case EbtUInt:
545                 returnValue.setUConst(0u);
546                 break;
547             default:
548                 UNREACHABLE();
549         }
550         return returnValue;
551     }
552 
553     switch (lhs.type)
554     {
555         case EbtInt:
556         {
557             unsigned int shiftOffset = 0;
558             switch (rhs.type)
559             {
560                 case EbtInt:
561                     shiftOffset = static_cast<unsigned int>(rhs.iConst);
562                     break;
563                 case EbtUInt:
564                     shiftOffset = rhs.uConst;
565                     break;
566                 default:
567                     UNREACHABLE();
568             }
569             if (shiftOffset > 0)
570             {
571                 // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
572                 // the sign bit." In C++ shifting negative integers is undefined, so we implement
573                 // extending the sign bit manually.
574                 int lhsSafe = lhs.iConst;
575                 if (lhsSafe == std::numeric_limits<int>::min())
576                 {
577                     // The min integer needs special treatment because only bit it has set is the
578                     // sign bit, which we clear later to implement safe right shift of negative
579                     // numbers.
580                     lhsSafe = -0x40000000;
581                     --shiftOffset;
582                 }
583                 if (shiftOffset > 0)
584                 {
585                     bool extendSignBit = false;
586                     if (lhsSafe < 0)
587                     {
588                         extendSignBit = true;
589                         // Clear the sign bit so that bitshift right is defined in C++.
590                         lhsSafe &= 0x7fffffff;
591                         ASSERT(lhsSafe > 0);
592                     }
593                     returnValue.setIConst(lhsSafe >> shiftOffset);
594 
595                     // Manually fill in the extended sign bit if necessary.
596                     if (extendSignBit)
597                     {
598                         int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
599                         returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
600                     }
601                 }
602                 else
603                 {
604                     returnValue.setIConst(lhsSafe);
605                 }
606             }
607             else
608             {
609                 returnValue.setIConst(lhs.iConst);
610             }
611             break;
612         }
613         case EbtUInt:
614             switch (rhs.type)
615             {
616                 case EbtInt:
617                     returnValue.setUConst(lhs.uConst >> rhs.iConst);
618                     break;
619                 case EbtUInt:
620                     returnValue.setUConst(lhs.uConst >> rhs.uConst);
621                     break;
622                 default:
623                     UNREACHABLE();
624             }
625             break;
626 
627         default:
628             UNREACHABLE();
629     }
630     return returnValue;
631 }
632 
633 // static
lshift(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)634 TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs,
635                                       const TConstantUnion &rhs,
636                                       TDiagnostics *diag,
637                                       const TSourceLoc &line)
638 {
639     TConstantUnion returnValue;
640     ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
641     ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
642     if (!IsValidShiftOffset(rhs))
643     {
644         diag->warning(line, "Undefined shift (operand out of range)", "<<");
645         switch (lhs.type)
646         {
647             case EbtInt:
648                 returnValue.setIConst(0);
649                 break;
650             case EbtUInt:
651                 returnValue.setUConst(0u);
652                 break;
653             default:
654                 UNREACHABLE();
655         }
656         return returnValue;
657     }
658 
659     switch (lhs.type)
660     {
661         case EbtInt:
662             switch (rhs.type)
663             {
664                 // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that
665                 // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed
666                 // integer overflow or undefined shift of a negative integer.
667                 case EbtInt:
668                     returnValue.setIConst(
669                         static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
670                     break;
671                 case EbtUInt:
672                     returnValue.setIConst(
673                         static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst));
674                     break;
675                 default:
676                     UNREACHABLE();
677             }
678             break;
679 
680         case EbtUInt:
681             switch (rhs.type)
682             {
683                 case EbtInt:
684                     returnValue.setUConst(lhs.uConst << rhs.iConst);
685                     break;
686                 case EbtUInt:
687                     returnValue.setUConst(lhs.uConst << rhs.uConst);
688                     break;
689                 default:
690                     UNREACHABLE();
691             }
692             break;
693 
694         default:
695             UNREACHABLE();
696     }
697     return returnValue;
698 }
699 
operator &(const TConstantUnion & constant) const700 TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
701 {
702     TConstantUnion returnValue;
703     ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
704     switch (type)
705     {
706         case EbtInt:
707             returnValue.setIConst(iConst & constant.iConst);
708             break;
709         case EbtUInt:
710             returnValue.setUConst(uConst & constant.uConst);
711             break;
712         default:
713             UNREACHABLE();
714     }
715 
716     return returnValue;
717 }
718 
operator |(const TConstantUnion & constant) const719 TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
720 {
721     TConstantUnion returnValue;
722     ASSERT(type == constant.type);
723     switch (type)
724     {
725         case EbtInt:
726             returnValue.setIConst(iConst | constant.iConst);
727             break;
728         case EbtUInt:
729             returnValue.setUConst(uConst | constant.uConst);
730             break;
731         default:
732             UNREACHABLE();
733     }
734 
735     return returnValue;
736 }
737 
operator ^(const TConstantUnion & constant) const738 TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
739 {
740     TConstantUnion returnValue;
741     ASSERT(type == constant.type);
742     switch (type)
743     {
744         case EbtInt:
745             returnValue.setIConst(iConst ^ constant.iConst);
746             break;
747         case EbtUInt:
748             returnValue.setUConst(uConst ^ constant.uConst);
749             break;
750         default:
751             UNREACHABLE();
752     }
753 
754     return returnValue;
755 }
756 
operator &&(const TConstantUnion & constant) const757 TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
758 {
759     TConstantUnion returnValue;
760     ASSERT(type == constant.type);
761     switch (type)
762     {
763         case EbtBool:
764             returnValue.setBConst(bConst && constant.bConst);
765             break;
766         default:
767             UNREACHABLE();
768     }
769 
770     return returnValue;
771 }
772 
operator ||(const TConstantUnion & constant) const773 TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
774 {
775     TConstantUnion returnValue;
776     ASSERT(type == constant.type);
777     switch (type)
778     {
779         case EbtBool:
780             returnValue.setBConst(bConst || constant.bConst);
781             break;
782         default:
783             UNREACHABLE();
784     }
785 
786     return returnValue;
787 }
788 
789 }  // namespace sh
790