summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/s2wasm.h9
-rw-r--r--src/support/bits.cpp2
-rw-r--r--src/wasm-interpreter.h9
-rw-r--r--src/wasm-s-parser.h70
-rw-r--r--src/wasm.h68
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);