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() : iConst(0), type(EbtVoid) {}
71
TConstantUnion(int i)72 TConstantUnion::TConstantUnion(int i) : iConst(i), type(EbtInt) {}
73
TConstantUnion(unsigned int u)74 TConstantUnion::TConstantUnion(unsigned int u) : uConst(u), type(EbtUInt) {}
75
TConstantUnion(float f)76 TConstantUnion::TConstantUnion(float f) : fConst(f), type(EbtFloat) {}
77
TConstantUnion(bool b)78 TConstantUnion::TConstantUnion(bool b) : bConst(b), type(EbtBool) {}
79
getIConst() const80 int TConstantUnion::getIConst() const
81 {
82 ASSERT(type == EbtInt);
83 return iConst;
84 }
85
getUConst() const86 unsigned int TConstantUnion::getUConst() const
87 {
88 ASSERT(type == EbtUInt);
89 return uConst;
90 }
91
getFConst() const92 float TConstantUnion::getFConst() const
93 {
94 switch (type)
95 {
96 case EbtInt:
97 return static_cast<float>(iConst);
98 case EbtUInt:
99 return static_cast<float>(uConst);
100 default:
101 ASSERT(type == EbtFloat);
102 return fConst;
103 }
104 }
105
getBConst() const106 bool TConstantUnion::getBConst() const
107 {
108 ASSERT(type == EbtBool);
109 return bConst;
110 }
111
isZero() const112 bool TConstantUnion::isZero() const
113 {
114 switch (type)
115 {
116 case EbtInt:
117 return getIConst() == 0;
118 case EbtUInt:
119 return getUConst() == 0;
120 case EbtFloat:
121 return getFConst() == 0.0f;
122 case EbtBool:
123 return getBConst() == false;
124 default:
125 return false;
126 }
127 }
128
getYuvCscStandardEXTConst() const129 TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const
130 {
131 ASSERT(type == EbtYuvCscStandardEXT);
132 return yuvCscStandardEXTConst;
133 }
134
cast(TBasicType newType,const TConstantUnion & constant)135 bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
136 {
137 switch (newType)
138 {
139 case EbtFloat:
140 switch (constant.type)
141 {
142 case EbtInt:
143 setFConst(static_cast<float>(constant.getIConst()));
144 break;
145 case EbtUInt:
146 setFConst(static_cast<float>(constant.getUConst()));
147 break;
148 case EbtBool:
149 setFConst(static_cast<float>(constant.getBConst()));
150 break;
151 case EbtFloat:
152 setFConst(static_cast<float>(constant.getFConst()));
153 break;
154 default:
155 return false;
156 }
157 break;
158 case EbtInt:
159 switch (constant.type)
160 {
161 case EbtInt:
162 setIConst(static_cast<int>(constant.getIConst()));
163 break;
164 case EbtUInt:
165 setIConst(static_cast<int>(constant.getUConst()));
166 break;
167 case EbtBool:
168 setIConst(static_cast<int>(constant.getBConst()));
169 break;
170 case EbtFloat:
171 setIConst(static_cast<int>(constant.getFConst()));
172 break;
173 default:
174 return false;
175 }
176 break;
177 case EbtUInt:
178 switch (constant.type)
179 {
180 case EbtInt:
181 setUConst(static_cast<unsigned int>(constant.getIConst()));
182 break;
183 case EbtUInt:
184 setUConst(static_cast<unsigned int>(constant.getUConst()));
185 break;
186 case EbtBool:
187 setUConst(static_cast<unsigned int>(constant.getBConst()));
188 break;
189 case EbtFloat:
190 if (constant.getFConst() < 0.0f)
191 {
192 // Avoid undefined behavior in C++ by first casting to signed int.
193 setUConst(
194 static_cast<unsigned int>(static_cast<int>(constant.getFConst())));
195 }
196 else
197 {
198 setUConst(static_cast<unsigned int>(constant.getFConst()));
199 }
200 break;
201 default:
202 return false;
203 }
204 break;
205 case EbtBool:
206 switch (constant.type)
207 {
208 case EbtInt:
209 setBConst(constant.getIConst() != 0);
210 break;
211 case EbtUInt:
212 setBConst(constant.getUConst() != 0);
213 break;
214 case EbtBool:
215 setBConst(constant.getBConst());
216 break;
217 case EbtFloat:
218 setBConst(constant.getFConst() != 0.0f);
219 break;
220 default:
221 return false;
222 }
223 break;
224 case EbtStruct: // Struct fields don't get cast
225 switch (constant.type)
226 {
227 case EbtInt:
228 setIConst(constant.getIConst());
229 break;
230 case EbtUInt:
231 setUConst(constant.getUConst());
232 break;
233 case EbtBool:
234 setBConst(constant.getBConst());
235 break;
236 case EbtFloat:
237 setFConst(constant.getFConst());
238 break;
239 default:
240 return false;
241 }
242 break;
243 case EbtYuvCscStandardEXT:
244 switch (constant.type)
245 {
246 case EbtYuvCscStandardEXT:
247 setYuvCscStandardEXTConst(constant.getYuvCscStandardEXTConst());
248 break;
249 default:
250 return false;
251 }
252 break;
253 default:
254 return false;
255 }
256
257 return true;
258 }
259
operator ==(const int i) const260 bool TConstantUnion::operator==(const int i) const
261 {
262 switch (type)
263 {
264 case EbtFloat:
265 return static_cast<float>(i) == fConst;
266 default:
267 return i == iConst;
268 }
269 }
270
operator ==(const unsigned int u) const271 bool TConstantUnion::operator==(const unsigned int u) const
272 {
273 switch (type)
274 {
275 case EbtFloat:
276 return static_cast<float>(u) == fConst;
277 default:
278 return u == uConst;
279 }
280 }
281
operator ==(const float f) const282 bool TConstantUnion::operator==(const float f) const
283 {
284 switch (type)
285 {
286 case EbtInt:
287 return f == static_cast<float>(iConst);
288 case EbtUInt:
289 return f == static_cast<float>(uConst);
290 default:
291 return f == fConst;
292 }
293 }
294
operator ==(const bool b) const295 bool TConstantUnion::operator==(const bool b) const
296 {
297 return b == bConst;
298 }
299
operator ==(const TYuvCscStandardEXT s) const300 bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const
301 {
302 return s == yuvCscStandardEXTConst;
303 }
304
operator ==(const TConstantUnion & constant) const305 bool TConstantUnion::operator==(const TConstantUnion &constant) const
306 {
307 ImplicitTypeConversion conversion = GetConversion(constant.type, type);
308 if (conversion == ImplicitTypeConversion::Same)
309 {
310 switch (type)
311 {
312 case EbtInt:
313 return constant.iConst == iConst;
314 case EbtUInt:
315 return constant.uConst == uConst;
316 case EbtFloat:
317 return constant.fConst == fConst;
318 case EbtBool:
319 return constant.bConst == bConst;
320 case EbtYuvCscStandardEXT:
321 return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst;
322 default:
323 return false;
324 }
325 }
326 else if (conversion == ImplicitTypeConversion::Invalid)
327 {
328 return false;
329 }
330 else
331 {
332 return constant.getFConst() == getFConst();
333 }
334 }
335
operator !=(const int i) const336 bool TConstantUnion::operator!=(const int i) const
337 {
338 return !operator==(i);
339 }
340
operator !=(const unsigned int u) const341 bool TConstantUnion::operator!=(const unsigned int u) const
342 {
343 return !operator==(u);
344 }
345
operator !=(const float f) const346 bool TConstantUnion::operator!=(const float f) const
347 {
348 return !operator==(f);
349 }
350
operator !=(const bool b) const351 bool TConstantUnion::operator!=(const bool b) const
352 {
353 return !operator==(b);
354 }
355
operator !=(const TYuvCscStandardEXT s) const356 bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const
357 {
358 return !operator==(s);
359 }
360
operator !=(const TConstantUnion & constant) const361 bool TConstantUnion::operator!=(const TConstantUnion &constant) const
362 {
363 return !operator==(constant);
364 }
365
operator >(const TConstantUnion & constant) const366 bool TConstantUnion::operator>(const TConstantUnion &constant) const
367 {
368
369 ImplicitTypeConversion conversion = GetConversion(constant.type, type);
370 if (conversion == ImplicitTypeConversion::Same)
371 {
372 switch (type)
373 {
374 case EbtInt:
375 return iConst > constant.iConst;
376 case EbtUInt:
377 return uConst > constant.uConst;
378 case EbtFloat:
379 return fConst > constant.fConst;
380 default:
381 return false; // Invalid operation, handled at semantic analysis
382 }
383 }
384 else
385 {
386 ASSERT(conversion != ImplicitTypeConversion::Invalid);
387 return getFConst() > constant.getFConst();
388 }
389 }
390
operator <(const TConstantUnion & constant) const391 bool TConstantUnion::operator<(const TConstantUnion &constant) const
392 {
393 ImplicitTypeConversion conversion = GetConversion(constant.type, type);
394 if (conversion == ImplicitTypeConversion::Same)
395 {
396 switch (type)
397 {
398 case EbtInt:
399 return iConst < constant.iConst;
400 case EbtUInt:
401 return uConst < constant.uConst;
402 case EbtFloat:
403 return fConst < constant.fConst;
404 default:
405 return false; // Invalid operation, handled at semantic analysis
406 }
407 }
408 else
409 {
410 ASSERT(conversion != ImplicitTypeConversion::Invalid);
411 return getFConst() < constant.getFConst();
412 }
413 }
414
415 // static
add(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)416 TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
417 const TConstantUnion &rhs,
418 TDiagnostics *diag,
419 const TSourceLoc &line)
420 {
421 TConstantUnion returnValue;
422
423 ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type);
424 if (conversion == ImplicitTypeConversion::Same)
425 {
426 switch (lhs.type)
427 {
428 case EbtInt:
429 returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
430 break;
431 case EbtUInt:
432 returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
433 break;
434 case EbtFloat:
435 returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line));
436 break;
437 default:
438 UNREACHABLE();
439 }
440 }
441 else
442 {
443 ASSERT(conversion != ImplicitTypeConversion::Invalid);
444 returnValue.setFConst(CheckedSum(lhs.getFConst(), rhs.getFConst(), diag, line));
445 }
446
447 return returnValue;
448 }
449
450 // static
sub(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)451 TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
452 const TConstantUnion &rhs,
453 TDiagnostics *diag,
454 const TSourceLoc &line)
455 {
456 TConstantUnion returnValue;
457
458 ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type);
459 if (conversion == ImplicitTypeConversion::Same)
460 {
461 switch (lhs.type)
462 {
463 case EbtInt:
464 returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
465 break;
466 case EbtUInt:
467 returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
468 break;
469 case EbtFloat:
470 returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line));
471 break;
472 default:
473 UNREACHABLE();
474 }
475 }
476 else
477 {
478 ASSERT(conversion != ImplicitTypeConversion::Invalid);
479 returnValue.setFConst(CheckedDiff(lhs.getFConst(), rhs.getFConst(), diag, line));
480 }
481
482 return returnValue;
483 }
484
485 // static
mul(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)486 TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
487 const TConstantUnion &rhs,
488 TDiagnostics *diag,
489 const TSourceLoc &line)
490 {
491 TConstantUnion returnValue;
492
493 ImplicitTypeConversion conversion = GetConversion(lhs.type, rhs.type);
494 if (conversion == ImplicitTypeConversion::Same)
495 {
496 switch (lhs.type)
497 {
498 case EbtInt:
499 returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst));
500 break;
501 case EbtUInt:
502 // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely
503 // on that to implement wrapping multiplication.
504 returnValue.setUConst(lhs.uConst * rhs.uConst);
505 break;
506 case EbtFloat:
507 returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line));
508 break;
509 default:
510 UNREACHABLE();
511 }
512 }
513 else
514 {
515 ASSERT(conversion != ImplicitTypeConversion::Invalid);
516 returnValue.setFConst(CheckedMul(lhs.getFConst(), rhs.getFConst(), diag, line));
517 }
518
519 return returnValue;
520 }
521
operator %(const TConstantUnion & constant) const522 TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
523 {
524 TConstantUnion returnValue;
525 ASSERT(type == constant.type);
526 switch (type)
527 {
528 case EbtInt:
529 returnValue.setIConst(iConst % constant.iConst);
530 break;
531 case EbtUInt:
532 returnValue.setUConst(uConst % constant.uConst);
533 break;
534 default:
535 UNREACHABLE();
536 }
537
538 return returnValue;
539 }
540
541 // static
rshift(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)542 TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs,
543 const TConstantUnion &rhs,
544 TDiagnostics *diag,
545 const TSourceLoc &line)
546 {
547 TConstantUnion returnValue;
548 ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
549 ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
550 if (!IsValidShiftOffset(rhs))
551 {
552 diag->warning(line, "Undefined shift (operand out of range)", ">>");
553 switch (lhs.type)
554 {
555 case EbtInt:
556 returnValue.setIConst(0);
557 break;
558 case EbtUInt:
559 returnValue.setUConst(0u);
560 break;
561 default:
562 UNREACHABLE();
563 }
564 return returnValue;
565 }
566
567 switch (lhs.type)
568 {
569 case EbtInt:
570 {
571 unsigned int shiftOffset = 0;
572 switch (rhs.type)
573 {
574 case EbtInt:
575 shiftOffset = static_cast<unsigned int>(rhs.iConst);
576 break;
577 case EbtUInt:
578 shiftOffset = rhs.uConst;
579 break;
580 default:
581 UNREACHABLE();
582 }
583 if (shiftOffset > 0)
584 {
585 // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
586 // the sign bit." In C++ shifting negative integers is undefined, so we implement
587 // extending the sign bit manually.
588 int lhsSafe = lhs.iConst;
589 if (lhsSafe == std::numeric_limits<int>::min())
590 {
591 // The min integer needs special treatment because only bit it has set is the
592 // sign bit, which we clear later to implement safe right shift of negative
593 // numbers.
594 lhsSafe = -0x40000000;
595 --shiftOffset;
596 }
597 if (shiftOffset > 0)
598 {
599 bool extendSignBit = false;
600 if (lhsSafe < 0)
601 {
602 extendSignBit = true;
603 // Clear the sign bit so that bitshift right is defined in C++.
604 lhsSafe &= 0x7fffffff;
605 ASSERT(lhsSafe > 0);
606 }
607 returnValue.setIConst(lhsSafe >> shiftOffset);
608
609 // Manually fill in the extended sign bit if necessary.
610 if (extendSignBit)
611 {
612 int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
613 returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
614 }
615 }
616 else
617 {
618 returnValue.setIConst(lhsSafe);
619 }
620 }
621 else
622 {
623 returnValue.setIConst(lhs.iConst);
624 }
625 break;
626 }
627 case EbtUInt:
628 switch (rhs.type)
629 {
630 case EbtInt:
631 returnValue.setUConst(lhs.uConst >> rhs.iConst);
632 break;
633 case EbtUInt:
634 returnValue.setUConst(lhs.uConst >> rhs.uConst);
635 break;
636 default:
637 UNREACHABLE();
638 }
639 break;
640
641 default:
642 UNREACHABLE();
643 }
644 return returnValue;
645 }
646
647 // static
lshift(const TConstantUnion & lhs,const TConstantUnion & rhs,TDiagnostics * diag,const TSourceLoc & line)648 TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs,
649 const TConstantUnion &rhs,
650 TDiagnostics *diag,
651 const TSourceLoc &line)
652 {
653 TConstantUnion returnValue;
654 ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
655 ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
656 if (!IsValidShiftOffset(rhs))
657 {
658 diag->warning(line, "Undefined shift (operand out of range)", "<<");
659 switch (lhs.type)
660 {
661 case EbtInt:
662 returnValue.setIConst(0);
663 break;
664 case EbtUInt:
665 returnValue.setUConst(0u);
666 break;
667 default:
668 UNREACHABLE();
669 }
670 return returnValue;
671 }
672
673 switch (lhs.type)
674 {
675 case EbtInt:
676 switch (rhs.type)
677 {
678 // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that
679 // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed
680 // integer overflow or undefined shift of a negative integer.
681 case EbtInt:
682 returnValue.setIConst(
683 static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
684 break;
685 case EbtUInt:
686 returnValue.setIConst(
687 static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst));
688 break;
689 default:
690 UNREACHABLE();
691 }
692 break;
693
694 case EbtUInt:
695 switch (rhs.type)
696 {
697 case EbtInt:
698 returnValue.setUConst(lhs.uConst << rhs.iConst);
699 break;
700 case EbtUInt:
701 returnValue.setUConst(lhs.uConst << rhs.uConst);
702 break;
703 default:
704 UNREACHABLE();
705 }
706 break;
707
708 default:
709 UNREACHABLE();
710 }
711 return returnValue;
712 }
713
operator &(const TConstantUnion & constant) const714 TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
715 {
716 TConstantUnion returnValue;
717 ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
718 switch (type)
719 {
720 case EbtInt:
721 returnValue.setIConst(iConst & constant.iConst);
722 break;
723 case EbtUInt:
724 returnValue.setUConst(uConst & constant.uConst);
725 break;
726 default:
727 UNREACHABLE();
728 }
729
730 return returnValue;
731 }
732
operator |(const TConstantUnion & constant) const733 TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
734 {
735 TConstantUnion returnValue;
736 ASSERT(type == constant.type);
737 switch (type)
738 {
739 case EbtInt:
740 returnValue.setIConst(iConst | constant.iConst);
741 break;
742 case EbtUInt:
743 returnValue.setUConst(uConst | constant.uConst);
744 break;
745 default:
746 UNREACHABLE();
747 }
748
749 return returnValue;
750 }
751
operator ^(const TConstantUnion & constant) const752 TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
753 {
754 TConstantUnion returnValue;
755 ASSERT(type == constant.type);
756 switch (type)
757 {
758 case EbtInt:
759 returnValue.setIConst(iConst ^ constant.iConst);
760 break;
761 case EbtUInt:
762 returnValue.setUConst(uConst ^ constant.uConst);
763 break;
764 default:
765 UNREACHABLE();
766 }
767
768 return returnValue;
769 }
770
operator &&(const TConstantUnion & constant) const771 TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
772 {
773 TConstantUnion returnValue;
774 ASSERT(type == constant.type);
775 switch (type)
776 {
777 case EbtBool:
778 returnValue.setBConst(bConst && constant.bConst);
779 break;
780 default:
781 UNREACHABLE();
782 }
783
784 return returnValue;
785 }
786
operator ||(const TConstantUnion & constant) const787 TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
788 {
789 TConstantUnion returnValue;
790 ASSERT(type == constant.type);
791 switch (type)
792 {
793 case EbtBool:
794 returnValue.setBConst(bConst || constant.bConst);
795 break;
796 default:
797 UNREACHABLE();
798 }
799
800 return returnValue;
801 }
802
803 } // namespace sh
804