Skip to content

Commit fdad3e9

Browse files
authored
[esm-integration] Enable DYNCALLS (#24374)
Now that #24399 has landed we can support dyncalls in ESM integration mode.
1 parent 7b73bff commit fdad3e9

File tree

5 files changed

+25
-12
lines changed

5 files changed

+25
-12
lines changed

site/source/docs/compiling/Modularized-Output.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,7 @@ Some additional limitations are:
168168
* :ref:`abort_on_wasm_exceptions` is not supported (requires wrapping wasm
169169
exports).
170170

171-
* :ref:`dyncalls` is not supported (depends on the ``Module`` global)
172-
173-
* :ref:`asyncify` is not supported (depends on :ref:`dyncalls`)
171+
* :ref:`asyncify` is not supported (depends on ``wasmExports`` global)
174172

175173
* Setting :ref:`wasm` to ``0`` is not supported.
176174

src/postamble.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ export default async function init(moduleArg = {}) {
314314
processModuleArgs();
315315
#if WASM_ESM_INTEGRATION
316316
updateMemoryViews();
317+
#if DYNCALLS && '$dynCalls' in addedLibraryItems
318+
319+
assignDynCalls();
320+
#endif
317321
#else
318322
wasmExports = await createWasm();
319323
#endif

test/test_core.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7020,7 +7020,6 @@ def test_EXPORTED_RUNTIME_METHODS(self):
70207020
self.do_core_test('EXPORTED_RUNTIME_METHODS.c')
70217021

70227022
@also_with_minimal_runtime
7023-
@no_esm_integration('WASM_ESM_INTEGRATION is not compatible with DYNCALLS')
70247023
def test_dyncall_specific(self):
70257024
if self.get_setting('WASM_BIGINT') != 0 and not self.is_wasm2js():
70267025
# define DYNCALLS because this test does test calling them directly, and
@@ -7047,8 +7046,6 @@ def test_dyncall_specific(self):
70477046
'legacy': (['-sDYNCALLS'],),
70487047
})
70497048
def test_dyncall_pointers(self, args):
7050-
if args and self.get_setting('WASM_ESM_INTEGRATION'):
7051-
self.skipTest('WASM_ESM_INTEGRATION is not compatible with DYNCALLS')
70527049
self.do_core_test('test_dyncall_pointers.c', emcc_args=args)
70537050

70547051
@also_with_wasm_bigint

tools/emscripten.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -928,18 +928,35 @@ def should_export(sym):
928928

929929

930930
def create_receiving(function_exports, tag_exports):
931+
generate_dyncall_assignment = settings.DYNCALLS and '$dynCall' in settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE
931932
receiving = ['\n// Imports from the Wasm binary.']
932933

933934
if settings.WASM_ESM_INTEGRATION:
934-
exports = tag_exports + list(function_exports.keys())
935-
exports = [f'{f} as {asmjs_mangle(f)}' for f in exports]
935+
exported_symbols = tag_exports + list(function_exports.keys())
936+
exports = []
937+
for sym in exported_symbols:
938+
mangled = asmjs_mangle(sym)
939+
if mangled != sym:
940+
exports.append(f'{sym} as {mangled}')
941+
else:
942+
exports.append(sym)
936943
if not settings.IMPORTED_MEMORY:
937944
exports.append('memory as wasmMemory')
938945
if not settings.RELOCATABLE:
939946
exports.append('__indirect_function_table as wasmTable')
940947
receiving.append('import {')
941948
receiving.append(' ' + ',\n '.join(exports))
942949
receiving.append(f"}} from './{settings.WASM_BINARY_FILE}';")
950+
951+
if generate_dyncall_assignment:
952+
receiving.append('\nfunction assignDynCalls() {')
953+
receiving.append(' // Construct dynCalls mapping')
954+
for sym in function_exports:
955+
if sym.startswith('dynCall_'):
956+
sig_str = sym.replace('dynCall_', '')
957+
receiving.append(f" dynCalls['{sig_str}'] = {sym};")
958+
receiving.append('}')
959+
943960
return '\n'.join(receiving) + '\n\n'
944961

945962
# When not declaring asm exports this section is empty and we instead programmatically export
@@ -952,7 +969,6 @@ def create_receiving(function_exports, tag_exports):
952969
# var _main;
953970
# function assignWasmExports(wasmExport) {
954971
# _main = wasmExports["_main"];
955-
generate_dyncall_assignment = settings.DYNCALLS and '$dynCall' in settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE
956972
exports = {name: sig for name, sig in function_exports.items() if name != building.WASM_CALL_CTORS}
957973

958974
if settings.ASSERTIONS:
@@ -981,7 +997,7 @@ def create_receiving(function_exports, tag_exports):
981997
receiving.append('\nfunction assignWasmExports(wasmExports) {')
982998
for sym, sig in exports.items():
983999
mangled = asmjs_mangle(sym)
984-
if generate_dyncall_assignment and mangled.startswith('dynCall_'):
1000+
if generate_dyncall_assignment and sym.startswith('dynCall_'):
9851001
sig_str = sym.replace('dynCall_', '')
9861002
dynCallAssignment = f"dynCalls['{sig_str}'] = "
9871003
else:

tools/link.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,6 @@ def phase_linker_setup(options, linker_args): # noqa: C901, PLR0912, PLR0915
814814
exit_with_error('WASM_ESM_INTEGRATION is not compatible with dynamic linking')
815815
if settings.ASYNCIFY == 1:
816816
exit_with_error('WASM_ESM_INTEGRATION is not compatible with -sASYNCIFY=1')
817-
if settings.DYNCALLS:
818-
exit_with_error('WASM_ESM_INTEGRATION is not compatible with DYNCALLS')
819817
if settings.WASM_WORKERS or settings.PTHREADS:
820818
exit_with_error('WASM_ESM_INTEGRATION is not compatible with multi-threading')
821819
if settings.USE_OFFSET_CONVERTER:

0 commit comments

Comments
 (0)