// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef _CONSTANT_UNION_INCLUDED_ #define _CONSTANT_UNION_INCLUDED_ #ifndef __ANDROID__ #include <assert.h> #else #include "../../Common/DebugAndroid.hpp" #endif class ConstantUnion { public: POOL_ALLOCATOR_NEW_DELETE(); ConstantUnion() { iConst = 0; type = EbtVoid; } bool cast(TBasicType newType, const ConstantUnion &constant) { switch (newType) { case EbtFloat: switch (constant.type) { case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break; case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break; case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break; case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break; default: return false; } break; case EbtInt: switch (constant.type) { case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break; case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break; case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break; case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break; default: return false; } break; case EbtUInt: switch (constant.type) { case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break; case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break; case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break; case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break; default: return false; } break; case EbtBool: switch (constant.type) { case EbtInt: setBConst(constant.getIConst() != 0); break; case EbtUInt: setBConst(constant.getUConst() != 0); break; case EbtBool: setBConst(constant.getBConst()); break; case EbtFloat: setBConst(constant.getFConst() != 0.0f); break; default: return false; } break; case EbtStruct: // Struct fields don't get cast switch (constant.type) { case EbtInt: setIConst(constant.getIConst()); break; case EbtUInt: setUConst(constant.getUConst()); break; case EbtBool: setBConst(constant.getBConst()); break; case EbtFloat: setFConst(constant.getFConst()); break; default: return false; } break; default: return false; } return true; } void setIConst(int i) {iConst = i; type = EbtInt; } void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } void setFConst(float f) {fConst = f; type = EbtFloat; } void setBConst(bool b) {bConst = b; type = EbtBool; } int getIConst() const { return iConst; } unsigned int getUConst() const { return uConst; } float getFConst() const { return fConst; } bool getBConst() const { return bConst; } float getAsFloat() const { const int FFFFFFFFh = 0xFFFFFFFF; switch(type) { case EbtInt: return reinterpret_cast<const float&>(iConst); case EbtUInt: return reinterpret_cast<const float&>(uConst); case EbtFloat: return fConst; case EbtBool: return (bConst == true) ? reinterpret_cast<const float&>(FFFFFFFFh) : 0; default: return 0; } } bool operator==(const int i) const { return i == iConst; } bool operator==(const unsigned int u) const { return u == uConst; } bool operator==(const float f) const { return f == fConst; } bool operator==(const bool b) const { return b == bConst; } bool operator==(const ConstantUnion& constant) const { if (constant.type != type) return false; switch (type) { case EbtInt: return constant.iConst == iConst; case EbtUInt: return constant.uConst == uConst; case EbtFloat: return constant.fConst == fConst; case EbtBool: return constant.bConst == bConst; default: return false; } } bool operator!=(const int i) const { return !operator==(i); } bool operator!=(const unsigned int u) const { return !operator==(u); } bool operator!=(const float f) const { return !operator==(f); } bool operator!=(const bool b) const { return !operator==(b); } bool operator!=(const ConstantUnion& constant) const { return !operator==(constant); } bool operator>(const ConstantUnion& constant) const { assert(type == constant.type); switch (type) { case EbtInt: return iConst > constant.iConst; case EbtUInt: return uConst > constant.uConst; case EbtFloat: return fConst > constant.fConst; default: return false; // Invalid operation, handled at semantic analysis } } bool operator<(const ConstantUnion& constant) const { assert(type == constant.type); switch (type) { case EbtInt: return iConst < constant.iConst; case EbtUInt: return uConst < constant.uConst; case EbtFloat: return fConst < constant.fConst; default: return false; // Invalid operation, handled at semantic analysis } } bool operator<=(const ConstantUnion& constant) const { assert(type == constant.type); switch (type) { case EbtInt: return iConst <= constant.iConst; case EbtUInt: return uConst <= constant.uConst; case EbtFloat: return fConst <= constant.fConst; default: return false; // Invalid operation, handled at semantic analysis } } bool operator>=(const ConstantUnion& constant) const { assert(type == constant.type); switch (type) { case EbtInt: return iConst >= constant.iConst; case EbtUInt: return uConst >= constant.uConst; case EbtFloat: return fConst >= constant.fConst; default: return false; // Invalid operation, handled at semantic analysis } } ConstantUnion operator+(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break; case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator-(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break; case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator*(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break; case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator%(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator>>(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator<<(const ConstantUnion& constant) const { ConstantUnion returnValue; // The signedness of the second parameter might be different, but we // don't care, since the result is undefined if the second parameter is // negative, and aliasing should not be a problem with unions. assert(constant.type == EbtInt || constant.type == EbtUInt); switch (type) { case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator&(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(constant.type == EbtInt || constant.type == EbtUInt); switch (type) { case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator|(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator^(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator&&(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; default: assert(false && "Default missing"); } return returnValue; } ConstantUnion operator||(const ConstantUnion& constant) const { ConstantUnion returnValue; assert(type == constant.type); switch (type) { case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; default: assert(false && "Default missing"); } return returnValue; } TBasicType getType() const { return type; } private: union { int iConst; // used for ivec, scalar ints unsigned int uConst; // used for uvec, scalar uints bool bConst; // used for bvec, scalar bools float fConst; // used for vec, mat, scalar floats } ; TBasicType type; }; #endif // _CONSTANT_UNION_INCLUDED_