tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ConstantUnion.cpp (23419B)


      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 
     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 
     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 
     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 
     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 
     70 TConstantUnion::TConstantUnion() : iConst(0), type(EbtVoid) {}
     71 
     72 TConstantUnion::TConstantUnion(int i) : iConst(i), type(EbtInt) {}
     73 
     74 TConstantUnion::TConstantUnion(unsigned int u) : uConst(u), type(EbtUInt) {}
     75 
     76 TConstantUnion::TConstantUnion(float f) : fConst(f), type(EbtFloat) {}
     77 
     78 TConstantUnion::TConstantUnion(bool b) : bConst(b), type(EbtBool) {}
     79 
     80 int TConstantUnion::getIConst() const
     81 {
     82    ASSERT(type == EbtInt);
     83    return iConst;
     84 }
     85 
     86 unsigned int TConstantUnion::getUConst() const
     87 {
     88    ASSERT(type == EbtUInt);
     89    return uConst;
     90 }
     91 
     92 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 
    106 bool TConstantUnion::getBConst() const
    107 {
    108    ASSERT(type == EbtBool);
    109    return bConst;
    110 }
    111 
    112 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 
    129 TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const
    130 {
    131    ASSERT(type == EbtYuvCscStandardEXT);
    132    return yuvCscStandardEXTConst;
    133 }
    134 
    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 
    260 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 
    271 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 
    282 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 
    295 bool TConstantUnion::operator==(const bool b) const
    296 {
    297    return b == bConst;
    298 }
    299 
    300 bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const
    301 {
    302    return s == yuvCscStandardEXTConst;
    303 }
    304 
    305 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 
    336 bool TConstantUnion::operator!=(const int i) const
    337 {
    338    return !operator==(i);
    339 }
    340 
    341 bool TConstantUnion::operator!=(const unsigned int u) const
    342 {
    343    return !operator==(u);
    344 }
    345 
    346 bool TConstantUnion::operator!=(const float f) const
    347 {
    348    return !operator==(f);
    349 }
    350 
    351 bool TConstantUnion::operator!=(const bool b) const
    352 {
    353    return !operator==(b);
    354 }
    355 
    356 bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const
    357 {
    358    return !operator==(s);
    359 }
    360 
    361 bool TConstantUnion::operator!=(const TConstantUnion &constant) const
    362 {
    363    return !operator==(constant);
    364 }
    365 
    366 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 
    391 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
    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
    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
    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 
    522 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
    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
    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 
    714 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 
    733 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 
    752 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 
    771 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 
    787 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