From dc7b490d57736def99a40920ad4e6e8ef1cfa3a4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 19 Feb 2016 15:33:57 -0800 Subject: add unaligned memory accesses to wasm.js --- src/wasm-js.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 3 deletions(-) (limited to 'src/wasm-js.cpp') diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp index 82a74d2ab..49838c905 100644 --- a/src/wasm-js.cpp +++ b/src/wasm-js.cpp @@ -26,6 +26,7 @@ #include "asm2wasm.h" #include "wasm-interpreter.h" #include "wasm-s-parser.h" +#include "wasm-printing.h" using namespace cashew; using namespace wasm; @@ -124,7 +125,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input, char *mappedG // instantiates the loaded wasm (which might be from asm2wasm, or // s-expressions, or something else) with a JS external interface. extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { - if (wasmJSDebug) std::cerr << "instantiating module: \n" << *module << '\n'; + if (wasmJSDebug) std::cerr << "instantiating module: \n" << module << '\n'; if (wasmJSDebug) std::cerr << "generating exports...\n"; @@ -200,7 +201,41 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { } Literal load(Load* load, size_t addr) override { - assert(load->align >= load->bytes); + if (load->align < load->bytes) { + double ret = EM_ASM_DOUBLE({ + var addr = $0; + var bytes = $1; + var isFloat = $2; + var isSigned = $3; + var save0 = HEAP32[0]; + var save1 = HEAP32[1]; + for (var i = 0; i < bytes; i++) { + HEAPU8[i] = HEAPU8[addr + i]; + } + var ret; + if (!isFloat) { + if (bytes === 1) ret = isSigned ? HEAP8[0] : HEAPU8[0]; + else if (bytes === 2) ret = isSigned ? HEAP16[0] : HEAPU16[0]; + else if (bytes === 4) ret = isSigned ? HEAP32[0] : HEAPU32[0]; + else abort(); + } else { + if (bytes === 4) ret = HEAPF32[0]; + else if (bytes === 8) ret = HEAPF64[0]; + else abort(); + } + HEAP32[0] = save0; HEAP32[1] = save1; + return ret; + }, addr, load->bytes, isWasmTypeFloat(load->type), load->signed_); + if (!isWasmTypeFloat(load->type)) { + return Literal((int32_t)ret); + } else if (load->bytes == 4) { + return Literal((float)ret); + } else if (load->bytes == 8) { + return Literal((double)ret); + } + abort(); + } + // nicely aligned if (!isWasmTypeFloat(load->type)) { if (load->bytes == 1) { if (load->signed_) { @@ -233,7 +268,33 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { } void store(Store* store, size_t addr, Literal value) override { - assert(store->align >= store->bytes); + if (store->align < store->bytes) { + double ret = EM_ASM_DOUBLE({ + var addr = $0; + var bytes = $1; + var isFloat = $2; + var value = $3; + var save0 = HEAP32[0]; + var save1 = HEAP32[1]; + if (!isFloat) { + if (bytes === 1) HEAPU8[0] = value; + else if (bytes === 2) HEAPU16[0] = value; + else if (bytes === 4) HEAPU32[0] = value; + else abort(); + } else { + if (bytes === 4) HEAPF32[0] = value; + else if (bytes === 8) HEAPF64[0] = value; + else abort(); + } + for (var i = 0; i < bytes; i++) { + HEAPU8[addr + i] = HEAPU8[i]; + } + HEAP32[0] = save0; HEAP32[1] = save1; + return ret; + }, addr, store->bytes, isWasmTypeFloat(store->type), isWasmTypeFloat(store->type) ? value.getFloat() : (double)value.getInteger()); + return; + } + // nicely aligned if (!isWasmTypeFloat(store->type)) { if (store->bytes == 1) { EM_ASM_INT({ Module['info'].parent['HEAP8'][$0] = $1 }, addr, value.geti32()); -- cgit v1.2.3 From 5ec0fdb423075356756c3f791a938b23f0495084 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 19 Feb 2016 15:47:57 -0800 Subject: support 64-bit stores in wasm.js --- src/wasm-js.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/wasm-js.cpp') diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp index 49838c905..cbaf15fbb 100644 --- a/src/wasm-js.cpp +++ b/src/wasm-js.cpp @@ -302,6 +302,11 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { EM_ASM_INT({ Module['info'].parent['HEAP16'][$0 >> 1] = $1 }, addr, value.geti32()); } else if (store->bytes == 4) { EM_ASM_INT({ Module['info'].parent['HEAP32'][$0 >> 2] = $1 }, addr, value.geti32()); + } else if (store->bytes == 8) { + uint64_t v = value.geti64(); + EM_ASM_INT({ Module['info'].parent['HEAP32'][$0 >> 2] = $1 }, addr, uint32_t(v)); + v >>= 32; + EM_ASM_INT({ Module['info'].parent['HEAP32'][$0 + 4 >> 2] = $1 }, addr, uint32_t(v)); } else { abort(); } -- cgit v1.2.3 From 33fc36930b2b73ff98eba6037138eaa8d3a20404 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 19 Feb 2016 16:08:09 -0800 Subject: make wasm.js tolerate wrong alignments, as per the wasm spec --- src/wasm-js.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/wasm-js.cpp') diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp index cbaf15fbb..723946891 100644 --- a/src/wasm-js.cpp +++ b/src/wasm-js.cpp @@ -201,7 +201,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { } Literal load(Load* load, size_t addr) override { - if (load->align < load->bytes) { + if (load->align < load->bytes || (addr & (load->bytes-1))) { double ret = EM_ASM_DOUBLE({ var addr = $0; var bytes = $1; @@ -268,8 +268,8 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { } void store(Store* store, size_t addr, Literal value) override { - if (store->align < store->bytes) { - double ret = EM_ASM_DOUBLE({ + if (store->align < store->bytes || (addr & (store->bytes-1))) { + EM_ASM_DOUBLE({ var addr = $0; var bytes = $1; var isFloat = $2; @@ -290,7 +290,6 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { HEAPU8[addr + i] = HEAPU8[i]; } HEAP32[0] = save0; HEAP32[1] = save1; - return ret; }, addr, store->bytes, isWasmTypeFloat(store->type), isWasmTypeFloat(store->type) ? value.getFloat() : (double)value.getInteger()); return; } -- cgit v1.2.3 From 21bea4589aaf5d0de92cd6917ec284444ad6557a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 19 Feb 2016 16:15:33 -0800 Subject: handle aligned and unaligned int64 store in wasm.js --- src/wasm-js.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'src/wasm-js.cpp') diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp index 723946891..9d56b3c93 100644 --- a/src/wasm-js.cpp +++ b/src/wasm-js.cpp @@ -267,8 +267,19 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { } } - void store(Store* store, size_t addr, Literal value) override { - if (store->align < store->bytes || (addr & (store->bytes-1))) { + void store(Store* store_, size_t addr, Literal value) override { + // support int64 stores + if (value.type == WasmType::i64) { + Store fake = *store_; + fake.bytes = 4; + uint64_t v = value.geti64(); + store(&fake, addr, Literal(uint32_t(v))); + v >>= 32; + store(&fake, addr + 4, Literal(uint32_t(v))); + return; + } + // normal non-int64 value + if (store_->align < store_->bytes || (addr & (store_->bytes-1))) { EM_ASM_DOUBLE({ var addr = $0; var bytes = $1; @@ -290,29 +301,24 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { HEAPU8[addr + i] = HEAPU8[i]; } HEAP32[0] = save0; HEAP32[1] = save1; - }, addr, store->bytes, isWasmTypeFloat(store->type), isWasmTypeFloat(store->type) ? value.getFloat() : (double)value.getInteger()); + }, addr, store_->bytes, isWasmTypeFloat(store_->type), isWasmTypeFloat(store_->type) ? value.getFloat() : (double)value.getInteger()); return; } // nicely aligned - if (!isWasmTypeFloat(store->type)) { - if (store->bytes == 1) { + if (!isWasmTypeFloat(store_->type)) { + if (store_->bytes == 1) { EM_ASM_INT({ Module['info'].parent['HEAP8'][$0] = $1 }, addr, value.geti32()); - } else if (store->bytes == 2) { + } else if (store_->bytes == 2) { EM_ASM_INT({ Module['info'].parent['HEAP16'][$0 >> 1] = $1 }, addr, value.geti32()); - } else if (store->bytes == 4) { + } else if (store_->bytes == 4) { EM_ASM_INT({ Module['info'].parent['HEAP32'][$0 >> 2] = $1 }, addr, value.geti32()); - } else if (store->bytes == 8) { - uint64_t v = value.geti64(); - EM_ASM_INT({ Module['info'].parent['HEAP32'][$0 >> 2] = $1 }, addr, uint32_t(v)); - v >>= 32; - EM_ASM_INT({ Module['info'].parent['HEAP32'][$0 + 4 >> 2] = $1 }, addr, uint32_t(v)); } else { abort(); } } else { - if (store->bytes == 4) { + if (store_->bytes == 4) { EM_ASM_DOUBLE({ Module['info'].parent['HEAPF32'][$0 >> 2] = $1 }, addr, value.getf32()); - } else if (store->bytes == 8) { + } else if (store_->bytes == 8) { EM_ASM_DOUBLE({ Module['info'].parent['HEAPF64'][$0 >> 3] = $1 }, addr, value.getf64()); } else { abort(); -- cgit v1.2.3 From af854dd0e98c0b3185ead411ffb9164cb9cb8796 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 19 Feb 2016 16:42:47 -0800 Subject: fix unaligned wasm.js load/store --- src/wasm-js.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/wasm-js.cpp') diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp index 9d56b3c93..9c9096ad8 100644 --- a/src/wasm-js.cpp +++ b/src/wasm-js.cpp @@ -210,7 +210,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { var save0 = HEAP32[0]; var save1 = HEAP32[1]; for (var i = 0; i < bytes; i++) { - HEAPU8[i] = HEAPU8[addr + i]; + HEAPU8[i] = Module["info"].parent["HEAPU8"][addr + i]; } var ret; if (!isFloat) { @@ -272,6 +272,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { if (value.type == WasmType::i64) { Store fake = *store_; fake.bytes = 4; + fake.type = i32; uint64_t v = value.geti64(); store(&fake, addr, Literal(uint32_t(v))); v >>= 32; @@ -298,7 +299,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { else abort(); } for (var i = 0; i < bytes; i++) { - HEAPU8[addr + i] = HEAPU8[i]; + Module["info"].parent["HEAPU8"][addr + i] = HEAPU8[i]; } HEAP32[0] = save0; HEAP32[1] = save1; }, addr, store_->bytes, isWasmTypeFloat(store_->type), isWasmTypeFloat(store_->type) ? value.getFloat() : (double)value.getInteger()); -- cgit v1.2.3