From 66094b585d8fce8fa80a08283bd0c10215c3c08a Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Mon, 18 Jan 2021 13:51:19 +0200 Subject: [PATCH] Use userdata for WASI context. Test Simple WASI on multiple platforms. #189 --- .github/workflows/tests.yml | 21 ++++++++++++-- platforms/app/main.c | 20 ++++++++----- source/m3_api_uvwasi.c | 45 +++++++++++++++++++--------- source/m3_api_wasi.c | 44 ++++++++++++++++++++-------- source/m3_api_wasi.h | 9 ++++++ source/m3_env.c | 58 ------------------------------------- source/m3_env.h | 4 --- source/wasm3.h | 2 +- 8 files changed, 105 insertions(+), 98 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 836fd38..caaaf84 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,6 +16,10 @@ jobs: - {target: clang-x86, cc: clang, flags: -DCMAKE_C_FLAGS="-m32", install: "gcc-multilib" } - {target: gcc, cc: gcc, } - {target: gcc-debug, cc: gcc, flags: -DCMAKE_BUILD_TYPE=Debug } + # Builds without uvwasi + - {target: gcc-no-uvwasi, cc: gcc, flags: -DBUILD_WASI=simple } + - {target: clang-no-uvwasi, cc: clang, flags: -DBUILD_WASI=simple } + # TODO: fails on numeric operations #- {target: gcc-x86, cc: gcc, flags: "-m32", install: "gcc-multilib" } @@ -63,15 +67,23 @@ jobs: build-mac: runs-on: macos-latest + name: build-mac-${{ matrix.config.target }} timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + config: + - {target: uvwasi, } + - {target: no-uvwasi, flags: -DBUILD_WASI=simple } + steps: - uses: actions/checkout@v2 - name: Configure run: | mkdir build cd build - cmake .. + cmake ${{ matrix.config.flags }} .. - name: Build run: | cmake --build build @@ -93,6 +105,11 @@ jobs: - {target: msvc-x64, platform: "-A x64", toolset: "" } - {target: clang-x86, platform: "-A Win32", toolset: "-T ClangCL" } - {target: msvc-x86, platform: "-A Win32", toolset: "" } + # Builds without uvwasi + - {target: clang-x64-no-uvwasi, platform: "-A x64", toolset: "-T ClangCL", flags: "-DBUILD_WASI=simple" } + - {target: msvc-x64-no-uvwasi, platform: "-A x64", toolset: "", flags: "-DBUILD_WASI=simple" } + - {target: clang-x86-no-uvwasi, platform: "-A Win32", toolset: "-T ClangCL", flags: "-DBUILD_WASI=simple" } + - {target: msvc-x86-no-uvwasi, platform: "-A Win32", toolset: "", flags: "-DBUILD_WASI=simple" } steps: - uses: actions/checkout@v2 @@ -100,7 +117,7 @@ jobs: run: | mkdir build cd build - cmake ${{ matrix.config.platform }} ${{ matrix.config.toolset }} .. + cmake ${{ matrix.config.platform }} ${{ matrix.config.toolset }} ${{ matrix.config.flags }} .. - name: Build run: | cmake --build build --config Release diff --git a/platforms/app/main.c b/platforms/app/main.c index 82ab502..aed94ba 100644 --- a/platforms/app/main.c +++ b/platforms/app/main.c @@ -316,14 +316,18 @@ int main (int i_argc, const char* i_argv[]) if (argFunc and not argRepl) { if (!strcmp(argFunc, "_start")) { + m3_wasi_context_t* wasi_ctx = m3_GetWasiContext(); // When passing args to WASI, include wasm filename as argv[0] - result = repl_call(runtime, argFunc, i_argc+1, i_argv-1); + wasi_ctx->argc = i_argc+1; + wasi_ctx->argv = i_argv-1; + result = repl_call(runtime, argFunc, 0, NULL); + if (result == m3Err_trapExit) { + return wasi_ctx->exit_code; + } } else { result = repl_call(runtime, argFunc, i_argc, i_argv); } - if (result == m3Err_trapExit) { - return runtime->exit_code; - } + if (result) { if (argDumpOnTrap) { repl_dump(runtime); @@ -358,7 +362,7 @@ int main (int i_argc, const char* i_argv[]) result = repl_load(runtime, argv[1]); } else if (!strcmp(":load-hex", argv[0])) { // :load-hex \n result = repl_load_hex(runtime, atol(argv[1])); - } else if (!strcmp(":dump", argv[0])) { // :load + } else if (!strcmp(":dump", argv[0])) { result = repl_dump(runtime); } else if (argv[0][0] == ':') { result = "no such command"; @@ -372,10 +376,10 @@ int main (int i_argc, const char* i_argv[]) M3ErrorInfo info; m3_GetErrorInfo (runtime, &info); fprintf (stderr, " (%s)\n", info.message); - if (result == m3Err_trapExit) { + //TODO: if (result == m3Err_trapExit) { // warn that exit was called - fprintf(stderr, M3_ARCH "-wasi: exit(%d)\n", runtime->exit_code); - } + // fprintf(stderr, M3_ARCH "-wasi: exit(%d)\n", runtime->exit_code); + //} } } diff --git a/source/m3_api_uvwasi.c b/source/m3_api_uvwasi.c index b24fd74..7e655f2 100644 --- a/source/m3_api_uvwasi.c +++ b/source/m3_api_uvwasi.c @@ -27,7 +27,8 @@ extern char** environ; #endif -uvwasi_t uvwasi; +static m3_wasi_context_t* wasi_context; +static uvwasi_t uvwasi; typedef struct wasi_iovec_t { @@ -45,14 +46,16 @@ m3ApiRawFunction(m3_wasi_unstable_args_get) m3ApiGetArgMem (uint32_t * , argv) m3ApiGetArgMem (char * , argv_buf) - if (runtime == NULL) { m3ApiReturn(UVWASI_EINVAL); } + m3_wasi_context_t* context = (m3_wasi_context_t*)userdata; - for (u32 i = 0; i < runtime->argc; ++i) + if (context == NULL) { m3ApiReturn(UVWASI_EINVAL); } + + for (u32 i = 0; i < context->argc; ++i) { m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); - size_t len = strlen (runtime->argv[i]); - memcpy (argv_buf, runtime->argv[i], len); + size_t len = strlen (context->argv[i]); + memcpy (argv_buf, context->argv[i], len); argv_buf += len; * argv_buf++ = 0; } @@ -66,15 +69,17 @@ m3ApiRawFunction(m3_wasi_unstable_args_sizes_get) m3ApiGetArgMem (uvwasi_size_t * , argc) m3ApiGetArgMem (uvwasi_size_t * , argv_buf_size) - if (runtime == NULL) { m3ApiReturn(UVWASI_EINVAL); } + m3_wasi_context_t* context = (m3_wasi_context_t*)userdata; + + if (context == NULL) { m3ApiReturn(UVWASI_EINVAL); } uvwasi_size_t buflen = 0; - for (u32 i = 0; i < runtime->argc; ++i) + for (u32 i = 0; i < context->argc; ++i) { - buflen += strlen (runtime->argv[i]) + 1; + buflen += strlen (context->argv[i]) + 1; } - m3ApiWriteMem32(argc, runtime->argc); + m3ApiWriteMem32(argc, context->argc); m3ApiWriteMem32(argv_buf_size, buflen); m3ApiReturn(UVWASI_ESUCCESS); @@ -428,7 +433,11 @@ m3ApiRawFunction(m3_wasi_unstable_proc_exit) { m3ApiGetArg (uint32_t, code) - runtime->exit_code = code; + m3_wasi_context_t* context = (m3_wasi_context_t*)userdata; + + if (context) { + context->exit_code = code; + } m3ApiTrap(m3Err_trapExit); } @@ -443,6 +452,11 @@ M3Result SuppressLookupFailure(M3Result i_result) return i_result; } +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + M3Result m3_LinkWASI (IM3Module module) { @@ -482,6 +496,11 @@ M3Result m3_LinkWASI (IM3Module module) return "uvwasi_init failed"; } + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; // fd_seek is incompatible @@ -492,8 +511,8 @@ _ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1" { const char* wasi = namespaces[i]; -_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_get", "i(**)", &m3_wasi_unstable_args_get))); -_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_unstable_args_sizes_get))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_unstable_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_unstable_args_sizes_get, wasi_context))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_unstable_clock_res_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_unstable_clock_time_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_unstable_environ_get))); @@ -533,7 +552,7 @@ _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_unstable_poll_oneoff))); -_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_exit", "v(i)", &m3_wasi_unstable_proc_exit))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_unstable_proc_exit, wasi_context))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_unstable_random_get))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); diff --git a/source/m3_api_wasi.c b/source/m3_api_wasi.c index 0f6649e..42e9c8e 100644 --- a/source/m3_api_wasi.c +++ b/source/m3_api_wasi.c @@ -53,6 +53,8 @@ # define close _close #endif +static m3_wasi_context_t* wasi_context; + typedef struct wasi_iovec_t { __wasi_size_t buf; @@ -187,14 +189,16 @@ m3ApiRawFunction(m3_wasi_unstable_args_get) m3ApiGetArgMem (uint32_t * , argv) m3ApiGetArgMem (char * , argv_buf) - if (runtime == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + m3_wasi_context_t* context = (m3_wasi_context_t*)userdata; + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } - for (u32 i = 0; i < runtime->argc; ++i) + for (u32 i = 0; i < context->argc; ++i) { m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); - size_t len = strlen (runtime->argv[i]); - memcpy (argv_buf, runtime->argv[i], len); + size_t len = strlen (context->argv[i]); + memcpy (argv_buf, context->argv[i], len); argv_buf += len; * argv_buf++ = 0; } @@ -208,15 +212,17 @@ m3ApiRawFunction(m3_wasi_unstable_args_sizes_get) m3ApiGetArgMem (__wasi_size_t * , argc) m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) - if (runtime == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + m3_wasi_context_t* context = (m3_wasi_context_t*)userdata; + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } __wasi_size_t buflen = 0; - for (u32 i = 0; i < runtime->argc; ++i) + for (u32 i = 0; i < context->argc; ++i) { - buflen += strlen (runtime->argv[i]) + 1; + buflen += strlen (context->argv[i]) + 1; } - m3ApiWriteMem32(argc, runtime->argc); + m3ApiWriteMem32(argc, context->argc); m3ApiWriteMem32(argv_buf_size, buflen); m3ApiReturn(__WASI_ERRNO_SUCCESS); @@ -630,7 +636,11 @@ m3ApiRawFunction(m3_wasi_unstable_proc_exit) { m3ApiGetArg (uint32_t, code) - runtime->exit_code = code; + m3_wasi_context_t* context = (m3_wasi_context_t*)userdata; + + if (context) { + context->exit_code = code; + } m3ApiTrap(m3Err_trapExit); } @@ -645,6 +655,11 @@ M3Result SuppressLookupFailure(M3Result i_result) return i_result; } +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + M3Result m3_LinkWASI (IM3Module module) { @@ -662,14 +677,19 @@ M3Result m3_LinkWASI (IM3Module module) } #endif + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; for (int i=0; i<2; i++) { const char* wasi = namespaces[i]; -_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_get", "i(**)", &m3_wasi_unstable_args_get))); -_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_unstable_args_sizes_get))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_unstable_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_unstable_args_sizes_get, wasi_context))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_unstable_clock_res_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_unstable_clock_time_get))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_unstable_environ_get))); @@ -709,7 +729,7 @@ _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", ))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_unstable_poll_oneoff))); -_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_exit", "v(i)", &m3_wasi_unstable_proc_exit))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_unstable_proc_exit, wasi_context))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); _ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_unstable_random_get))); //_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); diff --git a/source/m3_api_wasi.h b/source/m3_api_wasi.h index 194486f..8b0edc2 100644 --- a/source/m3_api_wasi.h +++ b/source/m3_api_wasi.h @@ -12,8 +12,17 @@ d_m3BeginExternC +typedef struct m3_wasi_context_t +{ + i32 exit_code; + u32 argc; + ccstr_t * argv; +} m3_wasi_context_t; + M3Result m3_LinkWASI (IM3Module io_module); +m3_wasi_context_t* m3_GetWasiContext(); + d_m3EndExternC #endif // m3_api_wasi_h diff --git a/source/m3_env.c b/source/m3_env.c index 26c8dff..2251a82 100644 --- a/source/m3_env.c +++ b/source/m3_env.c @@ -748,10 +748,6 @@ M3Result m3_CallWithArgs (IM3Function i_function, uint32_t i_argc, const char IM3Module module = i_function->module; IM3Runtime runtime = module->runtime; - runtime->argc = i_argc; - runtime->argv = i_argv; - if (i_function->name and strcmp (i_function->name, "_start") == 0) // WASI - i_argc = 0; IM3FuncType ftype = i_function->funcType; m3log (runtime, "calling %s", SPrintFuncTypeSignature (ftype)); @@ -821,60 +817,6 @@ _ ((M3Result) Call (i_function->compiled, (m3stack_t) stack, runtime->memo _catch: return result; } -#if 0 -M3Result m3_CallMain (IM3Function i_function, uint32_t i_argc, const char * const * i_argv) -{ - M3Result result = m3Err_none; - - if (i_function->compiled) - { - IM3Module module = i_function->module; - - IM3Runtime runtime = module->runtime; - - u8 * linearMemory = runtime->memory.wasmPages; - - m3stack_t stack = (m3stack_t) runtime->stack; - - if (i_argc) - { - IM3Memory memory = & runtime->memory; - // FIX: memory allocation in general - - i32 offset = AllocatePrivateHeap (memory, sizeof (i32) * i_argc); - - i32 * pointers = (i32 *) (memory->wasmPages + offset); - - for (u32 i = 0; i < i_argc; ++i) - { - size_t argLength = strlen (i_argv [i]) + 1; - - if (argLength < 4000) - { - i32 o = AllocatePrivateHeap (memory, (i32) argLength); - memcpy (memory->wasmPages + o, i_argv [i], argLength); - - * pointers++ = o; - } - else _throw ("insane argument string length"); - } - - stack [0] = i_argc; - stack [1] = offset; - } - -_ ((M3Result)Call (i_function->compiled, stack, linearMemory, d_m3OpDefaultArgs)); - - //u64 value = * (u64 *) (stack); - //m3log (runtime, "return64: % " PRIu64 " return32: %" PRIu32, value, (u32) value); - } - else _throw (m3Err_missingCompiledCode); - - _catch: return result; -} -#endif - - void ReleaseCodePageNoTrack (IM3Runtime i_runtime, IM3CodePage i_codePage) { if (i_codePage) diff --git a/source/m3_env.h b/source/m3_env.h index 020b4d5..7095165 100644 --- a/source/m3_env.h +++ b/source/m3_env.h @@ -220,10 +220,6 @@ typedef struct M3Runtime u32 stackSize; u32 numStackSlots; - i32 exit_code; - u32 argc; - ccstr_t * argv; - void * userdata; M3Memory memory; diff --git a/source/wasm3.h b/source/wasm3.h index fa4428c..2174c81 100644 --- a/source/wasm3.h +++ b/source/wasm3.h @@ -190,7 +190,7 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") const char * const i_moduleName, const char * const i_functionName, const char * const i_signature, - M3RawCall i_function); + M3RawCall i_function); M3Result m3_LinkRawFunctionEx (IM3Module io_module, const char * const i_moduleName,