diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/s2wasm.h | 9 | ||||
-rw-r--r-- | src/support/bits.cpp | 2 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 9 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 70 | ||||
-rw-r--r-- | src/wasm.h | 68 |
5 files changed, 105 insertions, 53 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h index 3efd667d5..56d96dde2 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -207,7 +207,8 @@ class S2WasmBuilder { // returns whether this is a relocation bool getConst(uint32_t* target) { if (isdigit(*s) || *s == '-') { - *target = getInt(); + int32_t val = getInt(); + memcpy(target, &val, sizeof(val)); return false; } else { // a global constant, we need to fix it up later @@ -1073,7 +1074,8 @@ class S2WasmBuilder { } else if (match(".int16")) { size_t size = raw.size(); raw.resize(size + 2); - (*(int16_t*)(&raw[size])) = getInt(); + int16_t val = getInt(); + memcpy(&raw[size], &val, sizeof(val)); zero = false; } else if (match(".int32")) { size_t size = raw.size(); @@ -1085,7 +1087,8 @@ class S2WasmBuilder { } else if (match(".int64")) { size_t size = raw.size(); raw.resize(size + 8); - (*(int64_t*)(&raw[size])) = getInt64(); + int64_t val = getInt64(); + memcpy(&raw[size], &val, sizeof(val)); zero = false; } else { break; diff --git a/src/support/bits.cpp b/src/support/bits.cpp index 3d03b100c..aa72201f4 100644 --- a/src/support/bits.cpp +++ b/src/support/bits.cpp @@ -68,7 +68,7 @@ int CountTrailingZeroes<uint32_t>(uint32_t v) { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; - return v ? (int)tbl[((uint32_t)((v & -(int32_t)v) * 0x077CB531U)) >> 27] : 32; + return v ? (int)tbl[((uint32_t)((v & -v) * 0x077CB531U)) >> 27] : 32; } template<> diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index d0e64c91e..5e3011282 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -455,7 +455,14 @@ private: case TruncSFloat64: return truncSFloat(curr, value); case TruncUFloat64: return truncUFloat(curr, value); case ReinterpretFloat: return value.castToI64(); - case DemoteFloat64: return value.truncateToF32(); + case DemoteFloat64: { + double val = value.getFloat(); + if (std::isnan(val)) return Literal(float(val)); + if (std::isinf(val)) return Literal(float(val)); + if (val < -std::numeric_limits<float>::max()) return Literal(-std::numeric_limits<float>::infinity()); + if (val > std::numeric_limits<float>::max()) return Literal(std::numeric_limits<float>::infinity()); + return value.truncateToF32(); + } default: abort(); } } diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 05715f739..af50a684c 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -1067,42 +1067,46 @@ private: Element& curr = *s[i]; assert(curr[0]->str() == SEGMENT); const char *input = curr[2]->c_str(); - std::vector<char> data; - data.resize(strlen(input)); - char *write = (char*)&data[0]; - while (1) { - if (input[0] == 0) break; - if (input[0] == '\\') { - if (input[1] == '"') { - *write++ = '"'; - input += 2; - continue; - } else if (input[1] == '\'') { - *write++ = '\''; - input += 2; - continue; - } else if (input[1] == '\\') { - *write++ = '\\'; - input += 2; - continue; - } else if (input[1] == 'n') { - *write++ = '\n'; - input += 2; - continue; - } else if (input[1] == 't') { - *write++ = '\t'; - input += 2; - continue; - } else { - *write++ = (char)(unhex(input[1])*16 + unhex(input[2])); - input += 3; - continue; + if (auto size = strlen(input)) { + std::vector<char> data; + data.resize(size); + char *write = data.data(); + while (1) { + if (input[0] == 0) break; + if (input[0] == '\\') { + if (input[1] == '"') { + *write++ = '"'; + input += 2; + continue; + } else if (input[1] == '\'') { + *write++ = '\''; + input += 2; + continue; + } else if (input[1] == '\\') { + *write++ = '\\'; + input += 2; + continue; + } else if (input[1] == 'n') { + *write++ = '\n'; + input += 2; + continue; + } else if (input[1] == 't') { + *write++ = '\t'; + input += 2; + continue; + } else { + *write++ = (char)(unhex(input[1])*16 + unhex(input[2])); + input += 3; + continue; + } } + *write++ = input[0]; + input++; } - *write++ = input[0]; - input++; + wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), data.data(), write - data.data()); + } else { + wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), "", 0); } - wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), (const char*)&data[0], write - (const char*)&data[0]); i++; } } 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); |