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 return false; 157 } 158 159 bool operator!=(const int i) const 160 { 161 return !operator==(i); 162 } 163 164 bool operator!=(const unsigned int u) const 165 { 166 return !operator==(u); 167 } 168 169 bool operator!=(const float f) const 170 { 171 return !operator==(f); 172 } 173 174 bool operator!=(const bool b) const 175 { 176 return !operator==(b); 177 } 178 179 bool operator!=(const ConstantUnion& constant) const 180 { 181 return !operator==(constant); 182 } 183 184 bool operator>(const ConstantUnion& constant) const 185 { 186 assert(type == constant.type); 187 switch (type) { 188 case EbtInt: 189 return iConst > constant.iConst; 190 case EbtUInt: 191 return uConst > constant.uConst; 192 case EbtFloat: 193 return fConst > constant.fConst; 194 default: 195 return false; // Invalid operation, handled at semantic analysis 196 } 197 198 return false; 199 } 200 201 bool operator<(const ConstantUnion& constant) const 202 { 203 assert(type == constant.type); 204 switch (type) { 205 case EbtInt: 206 return iConst < constant.iConst; 207 case EbtUInt: 208 return uConst < constant.uConst; 209 case EbtFloat: 210 return fConst < constant.fConst; 211 default: 212 return false; // Invalid operation, handled at semantic analysis 213 } 214 215 return false; 216 } 217 218 bool operator<=(const ConstantUnion& constant) const 219 { 220 assert(type == constant.type); 221 switch (type) { 222 case EbtInt: 223 return iConst <= constant.iConst; 224 case EbtUInt: 225 return uConst <= constant.uConst; 226 case EbtFloat: 227 return fConst <= constant.fConst; 228 default: 229 return false; // Invalid operation, handled at semantic analysis 230 } 231 232 return false; 233 } 234 235 bool operator>=(const ConstantUnion& constant) const 236 { 237 assert(type == constant.type); 238 switch (type) { 239 case EbtInt: 240 return iConst >= constant.iConst; 241 case EbtUInt: 242 return uConst >= constant.uConst; 243 case EbtFloat: 244 return fConst >= constant.fConst; 245 default: 246 return false; // Invalid operation, handled at semantic analysis 247 } 248 249 return false; 250 } 251 252 ConstantUnion operator+(const ConstantUnion& constant) const 253 { 254 ConstantUnion returnValue; 255 assert(type == constant.type); 256 switch (type) { 257 case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; 258 case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break; 259 case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; 260 default: assert(false && "Default missing"); 261 } 262 263 return returnValue; 264 } 265 266 ConstantUnion operator-(const ConstantUnion& constant) const 267 { 268 ConstantUnion returnValue; 269 assert(type == constant.type); 270 switch (type) { 271 case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; 272 case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break; 273 case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; 274 default: assert(false && "Default missing"); 275 } 276 277 return returnValue; 278 } 279 280 ConstantUnion operator*(const ConstantUnion& constant) const 281 { 282 ConstantUnion returnValue; 283 assert(type == constant.type); 284 switch (type) { 285 case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; 286 case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break; 287 case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; 288 default: assert(false && "Default missing"); 289 } 290 291 return returnValue; 292 } 293 294 ConstantUnion operator%(const ConstantUnion& constant) const 295 { 296 ConstantUnion returnValue; 297 assert(type == constant.type); 298 switch (type) { 299 case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; 300 case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break; 301 default: assert(false && "Default missing"); 302 } 303 304 return returnValue; 305 } 306 307 ConstantUnion operator>>(const ConstantUnion& constant) const 308 { 309 ConstantUnion returnValue; 310 assert(type == constant.type); 311 switch (type) { 312 case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; 313 case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break; 314 default: assert(false && "Default missing"); 315 } 316 317 return returnValue; 318 } 319 320 ConstantUnion operator<<(const ConstantUnion& constant) const 321 { 322 ConstantUnion returnValue; 323 // The signedness of the second parameter might be different, but we 324 // don't care, since the result is undefined if the second parameter is 325 // negative, and aliasing should not be a problem with unions. 326 assert(constant.type == EbtInt || constant.type == EbtUInt); 327 switch (type) { 328 case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; 329 case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; 330 default: assert(false && "Default missing"); 331 } 332 333 return returnValue; 334 } 335 336 ConstantUnion operator&(const ConstantUnion& constant) const 337 { 338 ConstantUnion returnValue; 339 assert(constant.type == EbtInt || constant.type == EbtUInt); 340 switch (type) { 341 case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; 342 case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; 343 default: assert(false && "Default missing"); 344 } 345 346 return returnValue; 347 } 348 349 ConstantUnion operator|(const ConstantUnion& constant) const 350 { 351 ConstantUnion returnValue; 352 assert(type == constant.type); 353 switch (type) { 354 case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; 355 case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break; 356 default: assert(false && "Default missing"); 357 } 358 359 return returnValue; 360 } 361 362 ConstantUnion operator^(const ConstantUnion& constant) const 363 { 364 ConstantUnion returnValue; 365 assert(type == constant.type); 366 switch (type) { 367 case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; 368 case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break; 369 default: assert(false && "Default missing"); 370 } 371 372 return returnValue; 373 } 374 375 ConstantUnion operator&&(const ConstantUnion& constant) const 376 { 377 ConstantUnion returnValue; 378 assert(type == constant.type); 379 switch (type) { 380 case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; 381 default: assert(false && "Default missing"); 382 } 383 384 return returnValue; 385 } 386 387 ConstantUnion operator||(const ConstantUnion& constant) const 388 { 389 ConstantUnion returnValue; 390 assert(type == constant.type); 391 switch (type) { 392 case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; 393 default: assert(false && "Default missing"); 394 } 395 396 return returnValue; 397 } 398 getType()399 TBasicType getType() const { return type; } 400 private: 401 402 union { 403 int iConst; // used for ivec, scalar ints 404 unsigned int uConst; // used for uvec, scalar uints 405 bool bConst; // used for bvec, scalar bools 406 float fConst; // used for vec, mat, scalar floats 407 } ; 408 409 TBasicType type; 410 }; 411 412 #endif // _CONSTANT_UNION_INCLUDED_ 413