1 /* 2 * Copyright 2017 WebAssembly Community Group participants 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef wasm_literal_h 18 #define wasm_literal_h 19 20 #include <array> 21 #include <iostream> 22 23 #include "compiler-support.h" 24 #include "support/hash.h" 25 #include "support/name.h" 26 #include "support/small_vector.h" 27 #include "support/utilities.h" 28 #include "wasm-type.h" 29 30 namespace wasm { 31 32 class Literals; 33 struct ExceptionPackage; 34 35 class Literal { 36 // store only integers, whose bits are deterministic. floats 37 // can have their signalling bit set, for example. 38 union { 39 int32_t i32; 40 int64_t i64; 41 uint8_t v128[16]; 42 // funcref function name. `isNull()` indicates a `null` value. 43 Name func; 44 // exnref package. `nullptr` indicates a `null` value. 45 std::unique_ptr<ExceptionPackage> exn; 46 // TODO: Literals of type `externref` can only be `null` currently but we 47 // will need to represent extern values eventually, to 48 // 1) run the spec tests and fuzzer with reference types enabled and 49 // 2) avoid bailing out when seeing a reference typed value in precompute 50 }; 51 52 public: 53 // Type of the literal. Immutable because the literal's payload depends on it. 54 const Type type; 55 Literal()56 Literal() : v128(), type(Type::none) {} 57 explicit Literal(Type type); Literal(Type::BasicID typeId)58 explicit Literal(Type::BasicID typeId) : Literal(Type(typeId)) {} Literal(int32_t init)59 explicit Literal(int32_t init) : i32(init), type(Type::i32) {} Literal(uint32_t init)60 explicit Literal(uint32_t init) : i32(init), type(Type::i32) {} Literal(int64_t init)61 explicit Literal(int64_t init) : i64(init), type(Type::i64) {} Literal(uint64_t init)62 explicit Literal(uint64_t init) : i64(init), type(Type::i64) {} Literal(float init)63 explicit Literal(float init) 64 : i32(bit_cast<int32_t>(init)), type(Type::f32) {} Literal(double init)65 explicit Literal(double init) 66 : i64(bit_cast<int64_t>(init)), type(Type::f64) {} 67 // v128 literal from bytes 68 explicit Literal(const uint8_t init[16]); 69 // v128 literal from lane value literals 70 explicit Literal(const std::array<Literal, 16>&); 71 explicit Literal(const std::array<Literal, 8>&); 72 explicit Literal(const std::array<Literal, 4>&); 73 explicit Literal(const std::array<Literal, 2>&); Literal(Name func)74 explicit Literal(Name func) : func(func), type(Type::funcref) {} Literal(std::unique_ptr<ExceptionPackage> && exn)75 explicit Literal(std::unique_ptr<ExceptionPackage>&& exn) 76 : exn(std::move(exn)), type(Type::exnref) {} 77 Literal(const Literal& other); 78 Literal& operator=(const Literal& other); ~Literal()79 ~Literal() { 80 if (type.isException()) { 81 exn.~unique_ptr(); 82 } 83 } 84 isConcrete()85 bool isConcrete() const { return type != Type::none; } isNone()86 bool isNone() const { return type == Type::none; } isNull()87 bool isNull() const { 88 if (type.isNullable()) { 89 if (type.isFunction()) { 90 return func.isNull(); 91 } 92 if (type.isException()) { 93 return !exn; 94 } 95 return true; 96 } 97 return false; 98 } isZero()99 bool isZero() const { 100 switch (type.getBasic()) { 101 case Type::i32: 102 return i32 == 0; 103 case Type::i64: 104 return i64 == 0LL; 105 case Type::f32: 106 return bit_cast<float>(i32) == 0.0f; 107 case Type::f64: 108 return bit_cast<double>(i64) == 0.0; 109 case Type::v128: { 110 uint8_t zeros[16] = {0}; 111 return memcmp(&v128, zeros, 16) == 0; 112 } 113 default: 114 WASM_UNREACHABLE("unexpected type"); 115 } 116 } isSignedMin()117 bool isSignedMin() const { 118 switch (type.getBasic()) { 119 case Type::i32: 120 return i32 == std::numeric_limits<int32_t>::min(); 121 case Type::i64: 122 return i64 == std::numeric_limits<int64_t>::min(); 123 default: 124 WASM_UNREACHABLE("unexpected type"); 125 } 126 } isSignedMax()127 bool isSignedMax() const { 128 switch (type.getBasic()) { 129 case Type::i32: 130 return i32 == std::numeric_limits<int32_t>::max(); 131 case Type::i64: 132 return i64 == std::numeric_limits<int64_t>::max(); 133 default: 134 WASM_UNREACHABLE("unexpected type"); 135 } 136 } isUnsignedMax()137 bool isUnsignedMax() const { 138 switch (type.getBasic()) { 139 case Type::i32: 140 return uint32_t(i32) == std::numeric_limits<uint32_t>::max(); 141 case Type::i64: 142 return uint64_t(i64) == std::numeric_limits<uint64_t>::max(); 143 default: 144 WASM_UNREACHABLE("unexpected type"); 145 } 146 } 147 148 static Literals makeZeros(Type type); 149 static Literals makeOnes(Type type); 150 static Literals makeNegOnes(Type type); 151 static Literal makeZero(Type type); 152 static Literal makeOne(Type type); 153 static Literal makeNegOne(Type type); makeFromInt32(int32_t x,Type type)154 static Literal makeFromInt32(int32_t x, Type type) { 155 switch (type.getBasic()) { 156 case Type::i32: 157 return Literal(int32_t(x)); 158 case Type::i64: 159 return Literal(int64_t(x)); 160 case Type::f32: 161 return Literal(float(x)); 162 case Type::f64: 163 return Literal(double(x)); 164 case Type::v128: 165 return Literal(std::array<Literal, 4>{{Literal(x), 166 Literal(int32_t(0)), 167 Literal(int32_t(0)), 168 Literal(int32_t(0))}}); 169 default: 170 WASM_UNREACHABLE("unexpected type"); 171 } 172 } makeFromInt64(int64_t x,Type type)173 static Literal makeFromInt64(int64_t x, Type type) { 174 switch (type.getBasic()) { 175 case Type::i32: 176 return Literal(int32_t(x)); 177 case Type::i64: 178 return Literal(int64_t(x)); 179 case Type::f32: 180 return Literal(float(x)); 181 case Type::f64: 182 return Literal(double(x)); 183 case Type::v128: 184 return Literal( 185 std::array<Literal, 2>{{Literal(x), Literal(int64_t(0))}}); 186 default: 187 WASM_UNREACHABLE("unexpected type"); 188 } 189 } makeSignedMin(Type type)190 static Literal makeSignedMin(Type type) { 191 switch (type.getBasic()) { 192 case Type::i32: 193 return Literal(std::numeric_limits<int32_t>::min()); 194 case Type::i64: 195 return Literal(std::numeric_limits<int64_t>::min()); 196 default: 197 WASM_UNREACHABLE("unexpected type"); 198 } 199 } makeSignedMax(Type type)200 static Literal makeSignedMax(Type type) { 201 switch (type.getBasic()) { 202 case Type::i32: 203 return Literal(std::numeric_limits<int32_t>::max()); 204 case Type::i64: 205 return Literal(std::numeric_limits<int64_t>::max()); 206 default: 207 WASM_UNREACHABLE("unexpected type"); 208 } 209 } makeUnsignedMax(Type type)210 static Literal makeUnsignedMax(Type type) { 211 switch (type.getBasic()) { 212 case Type::i32: 213 return Literal(std::numeric_limits<uint32_t>::max()); 214 case Type::i64: 215 return Literal(std::numeric_limits<uint64_t>::max()); 216 default: 217 WASM_UNREACHABLE("unexpected type"); 218 } 219 } makeNull(Type type)220 static Literal makeNull(Type type) { 221 assert(type.isNullable()); 222 return Literal(type); 223 } makeFunc(Name func)224 static Literal makeFunc(Name func) { return Literal(func.c_str()); } makeExn(std::unique_ptr<ExceptionPackage> && exn)225 static Literal makeExn(std::unique_ptr<ExceptionPackage>&& exn) { 226 return Literal(std::move(exn)); 227 } makeI31(int32_t value)228 static Literal makeI31(int32_t value) { 229 auto lit = Literal(Type::i31ref); 230 lit.i32 = value & 0x7fffffff; 231 return lit; 232 } 233 234 Literal castToF32(); 235 Literal castToF64(); 236 Literal castToI32(); 237 Literal castToI64(); 238 geti32()239 int32_t geti32() const { 240 assert(type == Type::i32); 241 return i32; 242 } 243 int32_t geti31(bool signed_ = true) const { 244 assert(type == Type::i31ref); 245 return signed_ ? (i32 << 1) >> 1 : i32; 246 } geti64()247 int64_t geti64() const { 248 assert(type == Type::i64); 249 return i64; 250 } getf32()251 float getf32() const { 252 assert(type == Type::f32); 253 return bit_cast<float>(i32); 254 } getf64()255 double getf64() const { 256 assert(type == Type::f64); 257 return bit_cast<double>(i64); 258 } 259 std::array<uint8_t, 16> getv128() const; getFunc()260 Name getFunc() const { 261 assert(type.isFunction() && !func.isNull()); 262 return func; 263 } 264 ExceptionPackage getExceptionPackage() const; 265 266 // careful! geti32Ptr()267 int32_t* geti32Ptr() { 268 assert(type == Type::i32); 269 return &i32; 270 } getv128Ptr()271 uint8_t* getv128Ptr() { 272 assert(type == Type::v128); 273 return v128; 274 } getv128Ptr()275 const uint8_t* getv128Ptr() const { 276 assert(type == Type::v128); 277 return v128; 278 } 279 reinterpreti32()280 int32_t reinterpreti32() const { 281 assert(type == Type::f32); 282 return i32; 283 } reinterpreti64()284 int64_t reinterpreti64() const { 285 assert(type == Type::f64); 286 return i64; 287 } reinterpretf32()288 float reinterpretf32() const { 289 assert(type == Type::i32); 290 return bit_cast<float>(i32); 291 } reinterpretf64()292 double reinterpretf64() const { 293 assert(type == Type::i64); 294 return bit_cast<double>(i64); 295 } 296 297 int64_t getInteger() const; 298 uint64_t getUnsigned() const; 299 double getFloat() const; 300 // Obtains the bits of a basic value typed literal. 301 void getBits(uint8_t (&buf)[16]) const; 302 // Equality checks for the type and the bits, so a nan float would 303 // be compared bitwise (which means that a Literal containing a nan 304 // would be equal to itself, if the bits are equal). 305 bool operator==(const Literal& other) const; 306 bool operator!=(const Literal& other) const; 307 308 bool isNaN(); 309 310 static uint32_t NaNPayload(float f); 311 static uint64_t NaNPayload(double f); 312 static float setQuietNaN(float f); 313 static double setQuietNaN(double f); 314 315 static void printFloat(std::ostream& o, float f); 316 static void printDouble(std::ostream& o, double d); 317 static void printVec128(std::ostream& o, const std::array<uint8_t, 16>& v); 318 319 Literal countLeadingZeroes() const; 320 Literal countTrailingZeroes() const; 321 Literal popCount() const; 322 323 Literal extendToSI64() const; 324 Literal extendToUI64() const; 325 Literal extendToF64() const; 326 Literal extendS8() const; 327 Literal extendS16() const; 328 Literal extendS32() const; 329 Literal wrapToI32() const; 330 331 Literal convertSIToF32() const; 332 Literal convertUIToF32() const; 333 Literal convertSIToF64() const; 334 Literal convertUIToF64() const; 335 336 Literal truncSatToSI32() const; 337 Literal truncSatToSI64() const; 338 Literal truncSatToUI32() const; 339 Literal truncSatToUI64() const; 340 341 Literal eqz() const; 342 Literal neg() const; 343 Literal abs() const; 344 Literal ceil() const; 345 Literal floor() const; 346 Literal trunc() const; 347 Literal nearbyint() const; 348 Literal sqrt() const; 349 Literal demote() const; 350 351 Literal add(const Literal& other) const; 352 Literal sub(const Literal& other) const; 353 Literal mul(const Literal& other) const; 354 Literal div(const Literal& other) const; 355 Literal divS(const Literal& other) const; 356 Literal divU(const Literal& other) const; 357 Literal remS(const Literal& other) const; 358 Literal remU(const Literal& other) const; 359 Literal and_(const Literal& other) const; 360 Literal or_(const Literal& other) const; 361 Literal xor_(const Literal& other) const; 362 Literal shl(const Literal& other) const; 363 Literal shrS(const Literal& other) const; 364 Literal shrU(const Literal& other) const; 365 Literal rotL(const Literal& other) const; 366 Literal rotR(const Literal& other) const; 367 368 // Note that these functions perform equality checks based 369 // on the type of the literal, so that (unlike the == operator) 370 // a float nan would not be identical to itself. 371 Literal eq(const Literal& other) const; 372 Literal ne(const Literal& other) const; 373 Literal ltS(const Literal& other) const; 374 Literal ltU(const Literal& other) const; 375 Literal lt(const Literal& other) const; 376 Literal leS(const Literal& other) const; 377 Literal leU(const Literal& other) const; 378 Literal le(const Literal& other) const; 379 380 Literal gtS(const Literal& other) const; 381 Literal gtU(const Literal& other) const; 382 Literal gt(const Literal& other) const; 383 Literal geS(const Literal& other) const; 384 Literal geU(const Literal& other) const; 385 Literal ge(const Literal& other) const; 386 387 Literal min(const Literal& other) const; 388 Literal max(const Literal& other) const; 389 Literal pmin(const Literal& other) const; 390 Literal pmax(const Literal& other) const; 391 Literal copysign(const Literal& other) const; 392 393 std::array<Literal, 16> getLanesSI8x16() const; 394 std::array<Literal, 16> getLanesUI8x16() const; 395 std::array<Literal, 8> getLanesSI16x8() const; 396 std::array<Literal, 8> getLanesUI16x8() const; 397 std::array<Literal, 4> getLanesI32x4() const; 398 std::array<Literal, 2> getLanesI64x2() const; 399 std::array<Literal, 4> getLanesF32x4() const; 400 std::array<Literal, 2> getLanesF64x2() const; 401 402 Literal shuffleV8x16(const Literal& other, 403 const std::array<uint8_t, 16>& mask) const; 404 Literal splatI8x16() const; 405 Literal extractLaneSI8x16(uint8_t index) const; 406 Literal extractLaneUI8x16(uint8_t index) const; 407 Literal replaceLaneI8x16(const Literal& other, uint8_t index) const; 408 Literal splatI16x8() const; 409 Literal extractLaneSI16x8(uint8_t index) const; 410 Literal extractLaneUI16x8(uint8_t index) const; 411 Literal replaceLaneI16x8(const Literal& other, uint8_t index) const; 412 Literal splatI32x4() const; 413 Literal extractLaneI32x4(uint8_t index) const; 414 Literal replaceLaneI32x4(const Literal& other, uint8_t index) const; 415 Literal splatI64x2() const; 416 Literal extractLaneI64x2(uint8_t index) const; 417 Literal replaceLaneI64x2(const Literal& other, uint8_t index) const; 418 Literal splatF32x4() const; 419 Literal extractLaneF32x4(uint8_t index) const; 420 Literal replaceLaneF32x4(const Literal& other, uint8_t index) const; 421 Literal splatF64x2() const; 422 Literal extractLaneF64x2(uint8_t index) const; 423 Literal replaceLaneF64x2(const Literal& other, uint8_t index) const; 424 Literal eqI8x16(const Literal& other) const; 425 Literal neI8x16(const Literal& other) const; 426 Literal ltSI8x16(const Literal& other) const; 427 Literal ltUI8x16(const Literal& other) const; 428 Literal gtSI8x16(const Literal& other) const; 429 Literal gtUI8x16(const Literal& other) const; 430 Literal leSI8x16(const Literal& other) const; 431 Literal leUI8x16(const Literal& other) const; 432 Literal geSI8x16(const Literal& other) const; 433 Literal geUI8x16(const Literal& other) const; 434 Literal eqI16x8(const Literal& other) const; 435 Literal neI16x8(const Literal& other) const; 436 Literal ltSI16x8(const Literal& other) const; 437 Literal ltUI16x8(const Literal& other) const; 438 Literal gtSI16x8(const Literal& other) const; 439 Literal gtUI16x8(const Literal& other) const; 440 Literal leSI16x8(const Literal& other) const; 441 Literal leUI16x8(const Literal& other) const; 442 Literal geSI16x8(const Literal& other) const; 443 Literal geUI16x8(const Literal& other) const; 444 Literal eqI32x4(const Literal& other) const; 445 Literal neI32x4(const Literal& other) const; 446 Literal ltSI32x4(const Literal& other) const; 447 Literal ltUI32x4(const Literal& other) const; 448 Literal gtSI32x4(const Literal& other) const; 449 Literal gtUI32x4(const Literal& other) const; 450 Literal leSI32x4(const Literal& other) const; 451 Literal leUI32x4(const Literal& other) const; 452 Literal geSI32x4(const Literal& other) const; 453 Literal geUI32x4(const Literal& other) const; 454 Literal eqF32x4(const Literal& other) const; 455 Literal neF32x4(const Literal& other) const; 456 Literal ltF32x4(const Literal& other) const; 457 Literal gtF32x4(const Literal& other) const; 458 Literal leF32x4(const Literal& other) const; 459 Literal geF32x4(const Literal& other) const; 460 Literal eqF64x2(const Literal& other) const; 461 Literal neF64x2(const Literal& other) const; 462 Literal ltF64x2(const Literal& other) const; 463 Literal gtF64x2(const Literal& other) const; 464 Literal leF64x2(const Literal& other) const; 465 Literal geF64x2(const Literal& other) const; 466 Literal notV128() const; 467 Literal andV128(const Literal& other) const; 468 Literal orV128(const Literal& other) const; 469 Literal xorV128(const Literal& other) const; 470 Literal bitselectV128(const Literal& left, const Literal& right) const; 471 Literal absI8x16() const; 472 Literal negI8x16() const; 473 Literal anyTrueI8x16() const; 474 Literal allTrueI8x16() const; 475 Literal bitmaskI8x16() const; 476 Literal shlI8x16(const Literal& other) const; 477 Literal shrSI8x16(const Literal& other) const; 478 Literal shrUI8x16(const Literal& other) const; 479 Literal addI8x16(const Literal& other) const; 480 Literal addSaturateSI8x16(const Literal& other) const; 481 Literal addSaturateUI8x16(const Literal& other) const; 482 Literal subI8x16(const Literal& other) const; 483 Literal subSaturateSI8x16(const Literal& other) const; 484 Literal subSaturateUI8x16(const Literal& other) const; 485 Literal mulI8x16(const Literal& other) const; 486 Literal minSI8x16(const Literal& other) const; 487 Literal minUI8x16(const Literal& other) const; 488 Literal maxSI8x16(const Literal& other) const; 489 Literal maxUI8x16(const Literal& other) const; 490 Literal avgrUI8x16(const Literal& other) const; 491 Literal absI16x8() const; 492 Literal negI16x8() const; 493 Literal anyTrueI16x8() const; 494 Literal allTrueI16x8() const; 495 Literal bitmaskI16x8() const; 496 Literal shlI16x8(const Literal& other) const; 497 Literal shrSI16x8(const Literal& other) const; 498 Literal shrUI16x8(const Literal& other) const; 499 Literal addI16x8(const Literal& other) const; 500 Literal addSaturateSI16x8(const Literal& other) const; 501 Literal addSaturateUI16x8(const Literal& other) const; 502 Literal subI16x8(const Literal& other) const; 503 Literal subSaturateSI16x8(const Literal& other) const; 504 Literal subSaturateUI16x8(const Literal& other) const; 505 Literal mulI16x8(const Literal& other) const; 506 Literal minSI16x8(const Literal& other) const; 507 Literal minUI16x8(const Literal& other) const; 508 Literal maxSI16x8(const Literal& other) const; 509 Literal maxUI16x8(const Literal& other) const; 510 Literal avgrUI16x8(const Literal& other) const; 511 Literal absI32x4() const; 512 Literal negI32x4() const; 513 Literal anyTrueI32x4() const; 514 Literal allTrueI32x4() const; 515 Literal bitmaskI32x4() const; 516 Literal shlI32x4(const Literal& other) const; 517 Literal shrSI32x4(const Literal& other) const; 518 Literal shrUI32x4(const Literal& other) const; 519 Literal addI32x4(const Literal& other) const; 520 Literal subI32x4(const Literal& other) const; 521 Literal mulI32x4(const Literal& other) const; 522 Literal minSI32x4(const Literal& other) const; 523 Literal minUI32x4(const Literal& other) const; 524 Literal maxSI32x4(const Literal& other) const; 525 Literal maxUI32x4(const Literal& other) const; 526 Literal dotSI16x8toI32x4(const Literal& other) const; 527 Literal negI64x2() const; 528 Literal anyTrueI64x2() const; 529 Literal allTrueI64x2() const; 530 Literal shlI64x2(const Literal& other) const; 531 Literal shrSI64x2(const Literal& other) const; 532 Literal shrUI64x2(const Literal& other) const; 533 Literal addI64x2(const Literal& other) const; 534 Literal subI64x2(const Literal& other) const; 535 Literal mulI64x2(const Literal& other) const; 536 Literal absF32x4() const; 537 Literal negF32x4() const; 538 Literal sqrtF32x4() const; 539 Literal addF32x4(const Literal& other) const; 540 Literal subF32x4(const Literal& other) const; 541 Literal mulF32x4(const Literal& other) const; 542 Literal divF32x4(const Literal& other) const; 543 Literal minF32x4(const Literal& other) const; 544 Literal maxF32x4(const Literal& other) const; 545 Literal pminF32x4(const Literal& other) const; 546 Literal pmaxF32x4(const Literal& other) const; 547 Literal ceilF32x4() const; 548 Literal floorF32x4() const; 549 Literal truncF32x4() const; 550 Literal nearestF32x4() const; 551 Literal absF64x2() const; 552 Literal negF64x2() const; 553 Literal sqrtF64x2() const; 554 Literal addF64x2(const Literal& other) const; 555 Literal subF64x2(const Literal& other) const; 556 Literal mulF64x2(const Literal& other) const; 557 Literal divF64x2(const Literal& other) const; 558 Literal minF64x2(const Literal& other) const; 559 Literal maxF64x2(const Literal& other) const; 560 Literal pminF64x2(const Literal& other) const; 561 Literal pmaxF64x2(const Literal& other) const; 562 Literal ceilF64x2() const; 563 Literal floorF64x2() const; 564 Literal truncF64x2() const; 565 Literal nearestF64x2() const; 566 Literal truncSatToSI32x4() const; 567 Literal truncSatToUI32x4() const; 568 Literal truncSatToSI64x2() const; 569 Literal truncSatToUI64x2() const; 570 Literal convertSToF32x4() const; 571 Literal convertUToF32x4() const; 572 Literal convertSToF64x2() const; 573 Literal convertUToF64x2() const; 574 Literal narrowSToVecI8x16(const Literal& other) const; 575 Literal narrowUToVecI8x16(const Literal& other) const; 576 Literal narrowSToVecI16x8(const Literal& other) const; 577 Literal narrowUToVecI16x8(const Literal& other) const; 578 Literal widenLowSToVecI16x8() const; 579 Literal widenHighSToVecI16x8() const; 580 Literal widenLowUToVecI16x8() const; 581 Literal widenHighUToVecI16x8() const; 582 Literal widenLowSToVecI32x4() const; 583 Literal widenHighSToVecI32x4() const; 584 Literal widenLowUToVecI32x4() const; 585 Literal widenHighUToVecI32x4() const; 586 Literal swizzleVec8x16(const Literal& other) const; 587 588 private: 589 Literal addSatSI8(const Literal& other) const; 590 Literal addSatUI8(const Literal& other) const; 591 Literal addSatSI16(const Literal& other) const; 592 Literal addSatUI16(const Literal& other) const; 593 Literal subSatSI8(const Literal& other) const; 594 Literal subSatUI8(const Literal& other) const; 595 Literal subSatSI16(const Literal& other) const; 596 Literal subSatUI16(const Literal& other) const; 597 Literal minInt(const Literal& other) const; 598 Literal maxInt(const Literal& other) const; 599 Literal minUInt(const Literal& other) const; 600 Literal maxUInt(const Literal& other) const; 601 Literal avgrUInt(const Literal& other) const; 602 }; 603 604 class Literals : public SmallVector<Literal, 1> { 605 public: 606 Literals() = default; Literals(std::initializer_list<Literal> init)607 Literals(std::initializer_list<Literal> init) 608 : SmallVector<Literal, 1>(init) { 609 #ifndef NDEBUG 610 for (auto& lit : init) { 611 assert(lit.isConcrete()); 612 } 613 #endif 614 }; getType()615 Type getType() { 616 std::vector<Type> types; 617 for (auto& val : *this) { 618 types.push_back(val.type); 619 } 620 return Type(types); 621 } isNone()622 bool isNone() { return size() == 0; } isConcrete()623 bool isConcrete() { return size() != 0; } 624 }; 625 626 // A struct for a thrown exception, which includes a tag (event) and thrown 627 // values 628 struct ExceptionPackage { 629 Name event; 630 Literals values; 631 bool operator==(const ExceptionPackage& other) const { 632 return event == other.event && values == other.values; 633 } 634 bool operator!=(const ExceptionPackage& other) const { 635 return !(*this == other); 636 } 637 }; 638 639 std::ostream& operator<<(std::ostream& o, wasm::Literal literal); 640 std::ostream& operator<<(std::ostream& o, wasm::Literals literals); 641 std::ostream& operator<<(std::ostream& o, const ExceptionPackage& exn); 642 643 } // namespace wasm 644 645 namespace std { 646 template<> struct hash<wasm::Literal> { 647 size_t operator()(const wasm::Literal& a) const { 648 auto digest = wasm::hash(a.type.getID()); 649 auto hashRef = [&]() { 650 assert(a.type.isRef()); 651 if (a.isNull()) { 652 return digest; 653 } 654 if (a.type.isFunction()) { 655 wasm::rehash(digest, a.getFunc()); 656 return digest; 657 } 658 if (a.type.isException()) { 659 auto exn = a.getExceptionPackage(); 660 wasm::rehash(digest, exn.event); 661 wasm::rehash(digest, exn.values); 662 return digest; 663 } 664 // other non-null reference type literals cannot represent concrete 665 // values, i.e. there is no concrete externref, anyref or eqref other than 666 // null. 667 WASM_UNREACHABLE("unexpected type"); 668 }; 669 if (a.type.isBasic()) { 670 switch (a.type.getBasic()) { 671 case wasm::Type::i32: 672 wasm::rehash(digest, a.geti32()); 673 return digest; 674 case wasm::Type::f32: 675 wasm::rehash(digest, a.reinterpreti32()); 676 return digest; 677 case wasm::Type::i64: 678 wasm::rehash(digest, a.geti64()); 679 return digest; 680 case wasm::Type::f64: 681 wasm::rehash(digest, a.reinterpreti64()); 682 return digest; 683 case wasm::Type::v128: 684 uint64_t chunks[2]; 685 memcpy(&chunks, a.getv128Ptr(), 16); 686 wasm::rehash(digest, chunks[0]); 687 wasm::rehash(digest, chunks[1]); 688 return digest; 689 case wasm::Type::funcref: 690 case wasm::Type::externref: 691 case wasm::Type::exnref: 692 case wasm::Type::anyref: 693 case wasm::Type::eqref: 694 return hashRef(); 695 case wasm::Type::i31ref: 696 wasm::rehash(digest, a.geti31(true)); 697 return digest; 698 case wasm::Type::none: 699 case wasm::Type::unreachable: 700 break; 701 } 702 } else if (a.type.isRef()) { 703 return hashRef(); 704 } else if (a.type.isRtt()) { 705 WASM_UNREACHABLE("TODO: rtt literals"); 706 } 707 WASM_UNREACHABLE("unexpected type"); 708 } 709 }; 710 template<> struct hash<wasm::Literals> { 711 size_t operator()(const wasm::Literals& a) const { 712 auto digest = wasm::hash(a.size()); 713 for (const auto& lit : a) { 714 wasm::rehash(digest, lit); 715 } 716 return digest; 717 } 718 }; 719 template<> struct less<wasm::Literal> { 720 bool operator()(const wasm::Literal& a, const wasm::Literal& b) const { 721 if (a.type < b.type) { 722 return true; 723 } 724 if (b.type < a.type) { 725 return false; 726 } 727 TODO_SINGLE_COMPOUND(a.type); 728 switch (a.type.getBasic()) { 729 case wasm::Type::i32: 730 return a.geti32() < b.geti32(); 731 case wasm::Type::f32: 732 return a.reinterpreti32() < b.reinterpreti32(); 733 case wasm::Type::i64: 734 return a.geti64() < b.geti64(); 735 case wasm::Type::f64: 736 return a.reinterpreti64() < b.reinterpreti64(); 737 case wasm::Type::v128: 738 return memcmp(a.getv128Ptr(), b.getv128Ptr(), 16) < 0; 739 case wasm::Type::funcref: 740 case wasm::Type::externref: 741 case wasm::Type::exnref: 742 case wasm::Type::anyref: 743 case wasm::Type::eqref: 744 case wasm::Type::i31ref: 745 case wasm::Type::none: 746 case wasm::Type::unreachable: 747 return false; 748 } 749 WASM_UNREACHABLE("unexpected type"); 750 } 751 }; 752 } // namespace std 753 754 #endif // wasm_literal_h 755