diff options
Diffstat (limited to 'src/wasm.h')
-rw-r--r-- | src/wasm.h | 68 |
1 files changed, 53 insertions, 15 deletions
diff --git a/src/wasm.h b/src/wasm.h index d61c8e564..e3c8ea7d9 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -409,8 +409,8 @@ public: Literal add(const Literal& other) const { switch (type) { - case WasmType::i32: return Literal(i32 + other.i32); - case WasmType::i64: return Literal(i64 + other.i64); + case WasmType::i32: return Literal(uint32_t(i32) + uint32_t(other.i32)); + case WasmType::i64: return Literal(uint64_t(i64) + uint64_t(other.i64)); case WasmType::f32: return Literal(getf32() + other.getf32()); case WasmType::f64: return Literal(getf64() + other.getf64()); default: WASM_UNREACHABLE(); @@ -418,8 +418,8 @@ public: } Literal sub(const Literal& other) const { switch (type) { - case WasmType::i32: return Literal(i32 - other.i32); - case WasmType::i64: return Literal(i64 - other.i64); + case WasmType::i32: return Literal(uint32_t(i32) - uint32_t(other.i32)); + case WasmType::i64: return Literal(uint64_t(i64) - uint64_t(other.i64)); case WasmType::f32: return Literal(getf32() - other.getf32()); case WasmType::f64: return Literal(getf64() - other.getf64()); default: WASM_UNREACHABLE(); @@ -427,8 +427,8 @@ public: } Literal mul(const Literal& other) const { switch (type) { - case WasmType::i32: return Literal(i32 * other.i32); - case WasmType::i64: return Literal(i64 * other.i64); + case WasmType::i32: return Literal(uint32_t(i32) * uint32_t(other.i32)); + case WasmType::i64: return Literal(uint64_t(i64) * uint64_t(other.i64)); case WasmType::f32: return Literal(getf32() * other.getf32()); case WasmType::f64: return Literal(getf64() * other.getf64()); default: WASM_UNREACHABLE(); @@ -436,8 +436,46 @@ public: } Literal div(const Literal& other) const { switch (type) { - case WasmType::f32: return Literal(getf32() / other.getf32()); - case WasmType::f64: return Literal(getf64() / other.getf64()); + case WasmType::f32: { + float lhs = getf32(), rhs = other.getf32(); + float sign = std::signbit(lhs) == std::signbit(rhs) ? 0.f : -0.f; + switch (std::fpclassify(rhs)) { + case FP_ZERO: + switch (std::fpclassify(lhs)) { + case FP_NAN: return *this; + case FP_ZERO: return Literal(std::copysign(std::numeric_limits<float>::quiet_NaN(), sign)); + case FP_NORMAL: // fallthrough + case FP_SUBNORMAL: // fallthrough + case FP_INFINITE: return Literal(std::copysign(std::numeric_limits<float>::infinity(), sign)); + default: WASM_UNREACHABLE(); + } + case FP_NAN: // fallthrough + case FP_INFINITE: // fallthrough + case FP_NORMAL: // fallthrough + case FP_SUBNORMAL: return Literal(lhs / rhs); + default: WASM_UNREACHABLE(); + } + } + case WasmType::f64: { + double lhs = getf64(), rhs = other.getf64(); + double sign = std::signbit(lhs) == std::signbit(rhs) ? 0. : -0.; + switch (std::fpclassify(rhs)) { + case FP_ZERO: + switch (std::fpclassify(lhs)) { + case FP_NAN: return *this; + case FP_ZERO: return Literal(std::copysign(std::numeric_limits<double>::quiet_NaN(), sign)); + case FP_NORMAL: // fallthrough + case FP_SUBNORMAL: // fallthrough + case FP_INFINITE: return Literal(std::copysign(std::numeric_limits<double>::infinity(), sign)); + default: WASM_UNREACHABLE(); + } + case FP_NAN: // fallthrough + case FP_INFINITE: // fallthrough + case FP_NORMAL: // fallthrough + case FP_SUBNORMAL: return Literal(lhs / rhs); + default: WASM_UNREACHABLE(); + } + } default: WASM_UNREACHABLE(); } } @@ -492,22 +530,22 @@ public: } Literal shl(const Literal& other) const { switch (type) { - case WasmType::i32: return Literal(i32 << other.i32); - case WasmType::i64: return Literal(i64 << other.i64); + case WasmType::i32: return Literal(uint32_t(i32) << (other.i32 & 0x1f)); + case WasmType::i64: return Literal(uint64_t(i64) << (other.i64 & 0x3f)); default: WASM_UNREACHABLE(); } } Literal shrS(const Literal& other) const { switch (type) { - case WasmType::i32: return Literal(i32 >> other.i32); - case WasmType::i64: return Literal(i64 >> other.i64); + case WasmType::i32: return Literal(i32 >> (other.i32 & 0x1f)); + case WasmType::i64: return Literal(i64 >> (other.i64 & 0x3f)); default: WASM_UNREACHABLE(); } } Literal shrU(const Literal& other) const { switch (type) { - case WasmType::i32: return Literal(uint32_t(i32) >> uint32_t(other.i32)); - case WasmType::i64: return Literal(uint64_t(i64) >> uint64_t(other.i64)); + case WasmType::i32: return Literal(uint32_t(i32) >> uint32_t(other.i32 & 0x1f)); + case WasmType::i64: return Literal(uint64_t(i64) >> uint64_t(other.i64 & 0x3f)); default: WASM_UNREACHABLE(); } } @@ -1188,7 +1226,7 @@ public: Segment() {} Segment(size_t offset, const char *init, size_t size) : offset(offset) { data.resize(size); - memcpy(&data[0], init, size); + std::copy_n(init, size, data.begin()); } Segment(size_t offset, std::vector<char>& init) : offset(offset) { data.swap(init); |