diff --git a/emsdk/patches/dynCall_so.patch b/emsdk/patches/dynCall_so.patch index 9641d5868..1ed66303f 100644 --- a/emsdk/patches/dynCall_so.patch +++ b/emsdk/patches/dynCall_so.patch @@ -1,3 +1,5 @@ +Tests for this are in emsdk/tests/test_dyncall.py + --- a/emsdk/fastcomp/emscripten/src/support.js +++ b/emsdk/fastcomp/emscripten/src/support.js @@ -338,6 +338,11 @@ function relocateExports(exports, memoryBase, tableBase, moduleLocal) { diff --git a/emsdk/tests/common.py b/emsdk/tests/common.py index 04a297c5a..75ea45ccf 100644 --- a/emsdk/tests/common.py +++ b/emsdk/tests/common.py @@ -16,3 +16,28 @@ env = { "EM_CACHE": str(EMSDK / ".emscripten_cache"), "BINARYEN_ROOT": str(EMSDK / "binaryen"), } + +MAIN_C = """ +#include +#include + +int main() { + puts("hello from main"); + void *handle = dlopen("library.wasm", RTLD_NOW); + if (!handle) { + puts("cannot load side module"); + puts(dlerror()); + return 1; + } + typedef void (*type_v)(); + type_v side_func = (type_v) dlsym(handle, "foo"); + if (!side_func) { + puts("cannot load side function"); + puts(dlerror()); + return 1; + } else { + side_func(); + } + return 0; +} +""" diff --git a/emsdk/tests/test_dyncall.py b/emsdk/tests/test_dyncall.py new file mode 100644 index 000000000..5fb3ab022 --- /dev/null +++ b/emsdk/tests/test_dyncall.py @@ -0,0 +1,75 @@ +import subprocess +from . import common + + +def test_emulate_function(tmpdir): + with tmpdir.as_cwd(): + with open("library.c", "w") as f: + f.write( + """\ +#include +#include +#include +#include + +// This can be any function that has a signature not found in main. +__attribute__ ((noinline)) int indirect_function(int a, float b, int c, double d) { + return a; +} + +typedef int (*type_iifid) (int, float, int, double); + +void foo() { + // Hack to force inclusion of malloc + volatile int x = (int) malloc(1); + free((void *) x); + + type_iifid fp = &indirect_function; + + jmp_buf buf; + int i = setjmp(buf); + + printf("%d\\n", i); + assert(fp(i, 0, 0, 0) == i); + + if (i == 0) longjmp(buf, 1); +} +""" + ) + with open("main.c", "w") as f: + f.write(common.MAIN_C) + + subprocess.run( + [ + "emcc", + "-s", + "SIDE_MODULE=1", + "library.c", + "-o", + "library.wasm", + "-s", + "EMULATE_FUNCTION_POINTER_CASTS=1", + "-s", + "EXPORT_ALL=1", + ], + check=True, + env=common.env, + ) + subprocess.run( + [ + "emcc", + "-s", + "MAIN_MODULE=1", + "main.c", + "--embed-file", + "library.wasm", + "-s", + "EMULATE_FUNCTION_POINTER_CASTS=1", + ], + check=True, + env=common.env, + ) + out = subprocess.run( + ["node", "a.out.js"], capture_output=True, check=True, env=common.env + ) + assert out.stdout == b"hello from main\n0\n4\n" diff --git a/emsdk/tests/test_emulate.py b/emsdk/tests/test_emulate.py index 2ee746ae9..93fb38fee 100644 --- a/emsdk/tests/test_emulate.py +++ b/emsdk/tests/test_emulate.py @@ -14,31 +14,8 @@ void foo() { }""" ) with open("main.c", "w") as f: - f.write( - """\ -#include -#include + f.write(common.MAIN_C) -int main() { - puts("hello from main"); - void *f = dlopen("library.wasm", RTLD_NOW); - if (!f) { - puts("cannot load side module"); - puts(dlerror()); - return 1; - } - typedef void (*voidfunc)(); - voidfunc g = (voidfunc) dlsym(f, "foo"); - if (!g) { - puts("cannot load side function"); - return 1; - } else { - g(); - } - return 0; -} -""" - ) subprocess.run( [ "emcc",