Skip to content

Commit

Permalink
Enable EM_JS in side modules
Browse files Browse the repository at this point in the history
This works in a similar way to EM_ASM. See #18228.

Depends on WebAssembly/binaryen#5780
  • Loading branch information
sbc100 committed Jun 24, 2023
1 parent b020474 commit 3ae2e6e
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 3 deletions.
1 change: 1 addition & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ def process_dynamic_libs(dylibs, lib_dirs):
for dylib in dylibs:
exports = webassembly.get_exports(dylib)
exports = set(e.name for e in exports)
exports = [utils.removeprefix(e, '__em_js__') for e in exports]
settings.SIDE_MODULE_EXPORTS.extend(sorted(exports))

imports = webassembly.get_imports(dylib)
Expand Down
2 changes: 0 additions & 2 deletions emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,6 @@ def emscript(in_wasm, out_wasm, outfile_js, memfile, js_syms):
diagnostics.warning('em-js-i64', 'using 64-bit arguments in EM_JS function without WASM_BIGINT is not yet fully supported: `%s` (%s, %s)', em_js_func, c_sig, signature.params)

if settings.SIDE_MODULE:
if metadata.emJsFuncs:
exit_with_error('EM_JS is not supported in side modules')
logger.debug('emscript: skipping remaining js glue generation')
return

Expand Down
27 changes: 26 additions & 1 deletion src/library_dylink.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ var LibraryDylink = {
'__wasm_call_ctors',
'__start_em_asm',
'__stop_em_asm',
].includes(symName)
'__start_em_js',
'__stop_em_js',
].includes(symName) || symName.startsWith('__em_js__')
#if SPLIT_MODULE
// Exports synthesized by wasm-split should be prefixed with '%'
|| symName[0] == '%'
Expand Down Expand Up @@ -779,6 +781,29 @@ var LibraryDylink = {
start = HEAPU8.indexOf(0, start) + 1;
}
}

function addEmJs(name, sig, body) {
sig = sig.slice(1, -1).split(',');
var args = [];
for (var i in sig) {
args.push(sig[i].split(' ').pop());
}
var func = `(${args}) => ${body};`;
#if DYLINK_DEBUG
dbg(`adding new EM_JS function: ${name} = ${func}`);
#endif
{{{ makeEval('wasmImports[name] = eval(func)') }}};
}

for (var name in moduleExports) {
if (name.startsWith('__em_js__')) {
var start = moduleExports[name]
{{{ from64('start') }}}
var jsString = UTF8ToString(start);
var parts = jsString.split('<::>');
addEmJs(name.replace('__em_js__', ''), parts[0], parts[1]);
}
}
#endif

// initialize the module
Expand Down
9 changes: 9 additions & 0 deletions test/core/test_em_js_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <stdio.h>
#include <emscripten.h>

int test_side();

int main() {
printf("in main\n");
return test_side();
}
2 changes: 2 additions & 0 deletions test/core/test_em_js_main.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
in main
hello from side module 42 + hello
11 changes: 11 additions & 0 deletions test/core/test_em_js_side.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <emscripten/em_js.h>
#include <stdio.h>

EM_JS(void*, js_side_func, (int num, char* ptr), {
out(`hello from side module ${num} + ${UTF8ToString(ptr)}`);
return 99;
});

void test_side() {
js_side_func(42, "hello");
}
5 changes: 5 additions & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2322,6 +2322,11 @@ def test_em_js_address_taken(self):
self.set_setting('MAIN_MODULE', 2)
self.do_core_test('test_em_js_address_taken.c')

@needs_dylink
def test_em_js_side_module(self):
self.build(test_file('core/test_em_js_side.c'), js_outfile=False, emcc_args=['-sSIDE_MODULE'], output_basename='side')
self.do_core_test('test_em_js_main.c', emcc_args=['-sMAIN_MODULE=2', 'side.wasm'])

def test_runtime_stacksave(self):
self.do_runf(test_file('core/test_runtime_stacksave.c'), 'success')

Expand Down
7 changes: 7 additions & 0 deletions tools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ def safe_ensure_dirs(dirname):
os.makedirs(dirname, exist_ok=True)


# TODO(sbc): Replace with str.removeprefix once we update to python3.9
def removeprefix(string, prefix):
if string.startswith(prefix):
return string[len(prefix):]
return string


@contextlib.contextmanager
def chdir(dir):
"""A context manager that performs actions in the given directory."""
Expand Down

0 comments on commit 3ae2e6e

Please sign in to comment.