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 wasm32/tcg-target.c.inc, QEMU's memory is imported into the
module as "env.buffer", and helper functions are imported as
"helper.<id>". 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.

Note Since FireFox 138, WebAssembly.Module no longer accepts a
SharedArrayBuffer as input [2] as reported by Nicolas Vandeginste in my
downstream fork[3]. 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://bugzilla.mozilla.org/show_bug.cgi?id=1965217
[3] https://github.com/ktock/qemu-wasm/pull/25

Signed-off-by: Kohei Tokunaga <ktokunaga.m...@gmail.com>
---
 tcg/wasm32.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tcg/wasm32.c b/tcg/wasm32.c
index b238ccf6d6..f2269c0a22 100644
--- a/tcg/wasm32.c
+++ b/tcg/wasm32.c
@@ -25,6 +25,7 @@
 #include "disas/dis-asm.h"
 #include "tcg-has.h"
 #include <ffi.h>
+#include <emscripten.h>
 
 
 #define ctpop_tr    glue(ctpop, TCG_TARGET_REG_BITS)
@@ -44,6 +45,29 @@
 
 __thread uintptr_t tci_tb_ptr;
 
+EM_JS(int, instantiate_wasm, (int wasm_begin,
+                              int wasm_size,
+                              int import_vec_begin,
+                              int import_vec_size),
+{
+    const memory_v = new DataView(HEAP8.buffer);
+    const wasm = HEAP8.subarray(wasm_begin, wasm_begin + wasm_size);
+    var helper = {};
+    for (var i = 0; i < import_vec_size / 4; i++) {
+        helper[i] = wasmTable.get(
+            memory_v.getInt32(import_vec_begin + i * 4, true));
+    }
+    const mod = new WebAssembly.Module(new Uint8Array(wasm));
+    const inst = new WebAssembly.Instance(mod, {
+            "env" : {
+                "buffer" : wasmMemory,
+            },
+            "helper" : helper,
+    });
+
+    return addFunction(inst.exports.start, 'ii');
+});
+
 static void tci_write_reg64(tcg_target_ulong *regs, uint32_t high_index,
                             uint32_t low_index, uint64_t value)
 {
-- 
2.43.0


Reply via email to