instantiate_wasm is a function that instantiates a TB's Wasm binary,
importing the functions as specified by its arguments. Following the header
definition in wasm/tcg-target.c.inc, QEMU's memory is imported into the
module as "env.memory", and helper functions are imported as "helper.<idx>".
The instantiated Wasm module is imported to QEMU using Emscripten's
"addFunction" feature[1] which returns a function pointer. This allows QEMU
to call this module directly from C code via that pointer.
Since the subarray() method doesn't accept a BigInt value which is used for
the 64bit pointer value, it is converted to a Number (i53) using
bigintToI53Checked method of Emscripten. Although this conversion (64bit to
53bit) drops higher bits, the maximum memory size of the engine
implementations is currently limited to 16GiB[2] so we can assume that the
pointers are within the Number's range.
Note that since FireFox 138, WebAssembly.Module no longer accepts a
SharedArrayBuffer as input [3] as reported by Nicolas Vandeginste in my
fork[4]. This commit ensures that WebAssembly.Module() is passed a
Uint8Array created from the binary data on a SharedArrayBuffer.
[1] https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#calling-javascript-functions-as-function-pointers-from-c
[2] https://webassembly.github.io/memory64/js-api/#limits
[3] https://bugzilla.mozilla.org/show_bug.cgi?id=1965217
[4] https://github.com/ktock/qemu-wasm/pull/25
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
---
tcg/wasm.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/tcg/wasm.c b/tcg/wasm.c
index 1cc2e45e77..15db1f9a8a 100644
--- a/tcg/wasm.c
+++ b/tcg/wasm.c
@@ -23,6 +23,43 @@
#include "tcg/tcg-ldst.h"
#include "tcg/helper-info.h"
#include <ffi.h>
+#include <emscripten.h>
+
+#define EM_JS_PRE(ret, name, args, body...) EM_JS(ret, name, args, body)
+
+#define DEC_PTR(p) bigintToI53Checked(p)
+#define ENC_PTR(p) BigInt(p)
+#if defined(WASM64_MEMORY64_2)
+#define ENC_WASM_TABLE_IDX(i) Number(i)
+#else
+#define ENC_WASM_TABLE_IDX(i) i
+#endif
+
+EM_JS_PRE(void*, instantiate_wasm, (void *wasm_begin,
+ int wasm_size,
+ void *import_vec_begin,
+ int import_vec_size),
+{
+ const memory_v = new DataView(HEAP8.buffer);
+ const wasm = HEAP8.subarray(DEC_PTR(wasm_begin),
+ DEC_PTR(wasm_begin) + wasm_size);
+ var helper = {};
+ const entsize = TCG_TARGET_REG_BITS / 8;
+ for (var i = 0; i < import_vec_size / entsize; i++) {
+ const idx = memory_v.getBigInt64(
+ DEC_PTR(import_vec_begin) + i * entsize, true);
+ helper[i] = wasmTable.get(ENC_WASM_TABLE_IDX(idx));
+ }
+ const mod = new WebAssembly.Module(new Uint8Array(wasm));
+ const inst = new WebAssembly.Instance(mod, {
+ "env" : {
+ "memory" : wasmMemory,
+ },
+ "helper" : helper,
+ });
+
+ return ENC_PTR(addFunction(inst.exports.start, 'ii'));
+});
__thread uintptr_t tci_tb_ptr;
--
2.43.0