1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef _CONSTANT_UNION_INCLUDED_ 16 #define _CONSTANT_UNION_INCLUDED_ 17 18 #ifndef __ANDROID__ 19 #include <assert.h> 20 #else 21 #include "../../Common/DebugAndroid.hpp" 22 #endif 23 24 class ConstantUnion { 25 public: 26 POOL_ALLOCATOR_NEW_DELETE(); ConstantUnion()27 ConstantUnion() 28 { 29 iConst = 0; 30 type = EbtVoid; 31 } 32 cast(TBasicType newType,const ConstantUnion & constant)33 bool cast(TBasicType newType, const ConstantUnion &constant) 34 { 35 switch (newType) 36 { 37 case EbtFloat: 38 switch (constant.type) 39 { 40 case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break; 41 case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break; 42 case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break; 43 case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break; 44 default: return false; 45 } 46 break; 47 case EbtInt: 48 switch (constant.type) 49 { 50 case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break; 51 case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break; 52 case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break; 53 case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break; 54 default: return false; 55 } 56 break; 57 case EbtUInt: 58 switch (constant.type) 59 { 60 case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break; 61 case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break; 62 case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break; 63 case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break; 64 default: return false; 65 } 66 break; 67 case EbtBool: 68 switch (constant.type) 69 { 70 case EbtInt: setBConst(constant.getIConst() != 0); break; 71 case EbtUInt: setBConst(constant.getUConst() != 0); break; 72 case EbtBool: setBConst(constant.getBConst()); break; 73 case EbtFloat: setBConst(constant.getFConst() != 0.0f); break; 74 default: return false; 75 } 76 break; 77 case EbtStruct: // Struct fields don't get cast 78 switch (constant.type) 79 { 80 case EbtInt: setIConst(constant.getIConst()); break; 81 case EbtUInt: setUConst(constant.getUConst()); break; 82 case EbtBool: setBConst(constant.getBConst()); break; 83 case EbtFloat: setFConst(constant.getFConst()); break; 84 default: return false; 85 } 86 break; 87 default: 88 return false; 89 } 90 91 return true; 92 } 93 setIConst(int i)94 void setIConst(int i) {iConst = i; type = EbtInt; } setUConst(unsigned int u)95 void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } setFConst(float f)96 void setFConst(float f) {fConst = f; type = EbtFloat; } setBConst(bool b)97 void setBConst(bool b) {bConst = b; type = EbtBool; } 98 getIConst()99 int getIConst() const { return iConst; } getUConst()100 unsigned int getUConst() const { return uConst; } getFConst()101 float getFConst() const { return fConst; } getBConst()102 bool getBConst() const { return bConst; } 103 getAsFloat()104 float getAsFloat() const 105 { 106 const int FFFFFFFFh = 0xFFFFFFFF; 107 108 switch(type) 109 { 110 case EbtInt: return reinterpret_cast<const float&>(iConst); 111 case EbtUInt: return reinterpret_cast<const float&>(uConst); 112 case EbtFloat: return fConst; 113 case EbtBool: return (bConst == true) ? reinterpret_cast<const float&>(FFFFFFFFh) : 0; 114 default: return 0; 115 } 116 } 117 118 bool operator==(const int i) const 119 { 120 return i == iConst; 121 } 122 123 bool operator==(const unsigned int u) const 124 { 125 return u == uConst; 126 } 127 128 bool operator==(const float f) const 129 { 130 return f == fConst; 131 } 132 133 bool operator==(const bool b) const 134 { 135 return b == bConst; 136 } 137 138 bool operator==(const ConstantUnion& constant) const 139 { 140 if (constant.type != type) 141 return false; 142 143 switch (type) { 144 case EbtInt: 145 return constant.iConst == iConst; 146 case EbtUInt: 147 return constant.uConst == uConst; 148 case EbtFloat: 149 return constant.fConst == fConst; 150 case EbtBool: 151 return constant.bConst == bConst; 152 default: 153 return false; 154 } 155 } 156 157 bool operator!=(const int i) const 158 { 159 return !operator==(i); 160 } 161 162 bool operator!=(const unsigned int u) const 163 { 164 return !operator==(u); 165 } 166 167 bool operator!=(const float f) const 168 { 169 return !operator==(f); 170 } 171 172 bool operator!=(const bool b) const 173 { 174 return !operator==(b); 175 } 176 177 bool operator!=(const ConstantUnion& constant) const 178 { 179 return !operator==(constant); 180 } 181 182 bool operator>(const ConstantUnion& constant) const 183 { 184 assert(type == constant.type); 185 switch (type) { 186 case EbtInt: 187 return iConst > constant.iConst; 188 case EbtUInt: 189 return uConst > constant.uConst; 190 case EbtFloat: 191 return fConst > constant.fConst; 192 default: 193 return false; // Invalid operation, handled at semantic analysis 194 } 195 } 196 197 bool operator<(const ConstantUnion& constant) const 198 { 199 assert(type == constant.type); 200 switch (type) { 201 case EbtInt: 202 return iConst < constant.iConst; 203 case EbtUInt: 204 return uConst < constant.uConst; 205 case EbtFloat: 206 return fConst < constant.fConst; 207 default: 208 return false; // Invalid operation, handled at semantic analysis 209 } 210 } 211 212 bool operator<=(const ConstantUnion& constant) const 213 { 214 assert(type == constant.type); 215 switch (type) { 216 case EbtInt: 217 return iConst <= constant.iConst; 218 case EbtUInt: 219 return uConst <= constant.uConst; 220 case EbtFloat: 221 return fConst <= constant.fConst; 222 default: 223 return false; // Invalid operation, handled at semantic analysis 224 } 225 } 226 227 bool operator>=(const ConstantUnion& constant) const 228 { 229 assert(type == constant.type); 230 switch (type) { 231 case EbtInt: 232 return iConst >= constant.iConst; 233 case EbtUInt: 234 return uConst >= constant.uConst; 235 case EbtFloat: 236 return fConst >= constant.fConst; 237 default: 238 return false; // Invalid operation, handled at semantic analysis 239 } 240 } 241 242 ConstantUnion operator+(const ConstantUnion& constant) const 243 { 244 ConstantUnion returnValue; 245 assert(type == constant.type); 246 switch (type) { 247 case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; 248 case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break; 249 case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; 250 default: assert(false && "Default missing"); 251 } 252 253 return returnValue; 254 } 255 256 ConstantUnion operator-(const ConstantUnion& constant) const 257 { 258 ConstantUnion returnValue; 259 assert(type == constant.type); 260 switch (type) { 261 case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; 262 case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break; 263 case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; 264 default: assert(false && "Default missing"); 265 } 266 267 return returnValue; 268 } 269 270 ConstantUnion operator*(const ConstantUnion& constant) const 271 { 272 ConstantUnion returnValue; 273 assert(type == constant.type); 274 switch (type) { 275 case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; 276 case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break; 277 case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; 278 default: assert(false && "Default missing"); 279 } 280 281 return returnValue; 282 } 283 284 ConstantUnion operator%(const ConstantUnion& constant) const 285 { 286 ConstantUnion returnValue; 287 assert(type == constant.type); 288 switch (type) { 289 case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; 290 case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break; 291 default: assert(false && "Default missing"); 292 } 293 294 return returnValue; 295 } 296 297 ConstantUnion operator>>(const ConstantUnion& constant) const 298 { 299 ConstantUnion returnValue; 300 assert(type == constant.type); 301 switch (type) { 302 case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; 303 case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break; 304 default: assert(false && "Default missing"); 305 } 306 307 return returnValue; 308 } 309 310 ConstantUnion operator<<(const ConstantUnion& constant) const 311 { 312 ConstantUnion returnValue; 313 // The signedness of the second parameter might be different, but we 314 // don't care, since the result is undefined if the second parameter is 315 // negative, and aliasing should not be a problem with unions. 316 assert(constant.type == EbtInt || constant.type == EbtUInt); 317 switch (type) { 318 case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; 319 case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; 320 default: assert(false && "Default missing"); 321 } 322 323 return returnValue; 324 } 325 326 ConstantUnion operator&(const ConstantUnion& constant) const 327 { 328 ConstantUnion returnValue; 329 assert(constant.type == EbtInt || constant.type == EbtUInt); 330 switch (type) { 331 case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; 332 case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; 333 default: assert(false && "Default missing"); 334 } 335 336 return returnValue; 337 } 338 339 ConstantUnion operator|(const ConstantUnion& constant) const 340 { 341 ConstantUnion returnValue; 342 assert(type == constant.type); 343 switch (type) { 344 case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; 345 case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break; 346 default: assert(false && "Default missing"); 347 } 348 349 return returnValue; 350 } 351 352 ConstantUnion operator^(const ConstantUnion& constant) const 353 { 354 ConstantUnion returnValue; 355 assert(type == constant.type); 356 switch (type) { 357 case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; 358 case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break; 359 default: assert(false && "Default missing"); 360 } 361 362 return returnValue; 363 } 364 365 ConstantUnion operator&&(const ConstantUnion& constant) const 366 { 367 ConstantUnion returnValue; 368 assert(type == constant.type); 369 switch (type) { 370 case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; 371 default: assert(false && "Default missing"); 372 } 373 374 return returnValue; 375 } 376 377 ConstantUnion operator||(const ConstantUnion& constant) const 378 { 379 ConstantUnion returnValue; 380 assert(type == constant.type); 381 switch (type) { 382 case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; 383 default: assert(false && "Default missing"); 384 } 385 386 return returnValue; 387 } 388 getType()389 TBasicType getType() const { return type; } 390 private: 391 392 union { 393 int iConst; // used for ivec, scalar ints 394 unsigned int uConst; // used for uvec, scalar uints 395 bool bConst; // used for bvec, scalar bools 396 float fConst; // used for vec, mat, scalar floats 397 } ; 398 399 TBasicType type; 400 }; 401 402 #endif // _CONSTANT_UNION_INCLUDED_ 403