From 14d37a3782ec8bef76e7590e62d87651432cef76 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 01/11] vendor toywasm --- .gitmodules | 3 +++ runtimes/native/vendor/toywasm | 1 + 2 files changed, 4 insertions(+) create mode 160000 runtimes/native/vendor/toywasm diff --git a/.gitmodules b/.gitmodules index d70e90bf..23d83816 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "runtimes/native/vendor/cubeb"] path = runtimes/native/vendor/cubeb url = https://github.com/mozilla/cubeb +[submodule "runtimes/native/vendor/toywasm"] + path = runtimes/native/vendor/toywasm + url = https://github.com/yamt/toywasm diff --git a/runtimes/native/vendor/toywasm b/runtimes/native/vendor/toywasm new file mode 160000 index 00000000..8c77bbb6 --- /dev/null +++ b/runtimes/native/vendor/toywasm @@ -0,0 +1 @@ +Subproject commit 8c77bbb6e058700bb018cd7f3170752b187b53a2 From e86db889a0d61ab7d7847de0d8184453355baafc Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 02/11] add toywasm support --- runtimes/native/CMakeLists.txt | 88 ++++- runtimes/native/src/backend/wasm_toywasm.c | 397 +++++++++++++++++++++ 2 files changed, 476 insertions(+), 9 deletions(-) create mode 100644 runtimes/native/src/backend/wasm_toywasm.c diff --git a/runtimes/native/CMakeLists.txt b/runtimes/native/CMakeLists.txt index 2e89e532..9ee45e1b 100644 --- a/runtimes/native/CMakeLists.txt +++ b/runtimes/native/CMakeLists.txt @@ -1,6 +1,18 @@ cmake_minimum_required(VERSION 3.7) project(WASM4) +set(WASM_RUNTIME "wasm3" CACHE STRING "webassembly runtime") + +set (WASM3 OFF) +set (TOYWASM OFF) +if (WASM_RUNTIME STREQUAL "wasm3") +set (WASM3 ON) +elseif (WASM_RUNTIME STREQUAL "toywasm") +set (TOYWASM ON) +else () +message (FATAL_ERROR "Unrecognized WASM_RUNTIME value: ${WASM_RUNTIME}") +endif () + # Prevent BUILD_SHARED_LIBS and other options from being cleared by vendor CMakeLists # https://stackoverflow.com/a/66342383 set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) @@ -25,6 +37,43 @@ set(BUILD_SHARED_LIBS OFF) set(BUILD_TESTS OFF) set(BUILD_TOOLS OFF) +# wasm3 +if (WASM3) +file(GLOB M3_SOURCES RELATIVE "${CMAKE_SOURCE_DIR}" "vendor/wasm3/source/*.c") +set(WASM3_SOURCES + src/backend/wasm_wasm3.c + ${M3_SOURCES} +) +endif () + +# toywasm +if (TOYWASM) +set(toywasm_tmp_install ${CMAKE_CURRENT_BINARY_DIR}/install) + +include(ExternalProject) +ExternalProject_Add(toywasm + SOURCE_DIR "${CMAKE_SOURCE_DIR}/vendor/toywasm" + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${toywasm_tmp_install} + -DBUILD_TESTING=OFF + -DTOYWASM_BUILD_CLI=OFF + -DTOYWASM_BUILD_UNITTEST=OFF + -DTOYWASM_ENABLE_WASI=OFF + -DTOYWASM_ENABLE_WASM_SIMD=OFF + -DTOYWASM_USE_SHORT_ENUMS=OFF + -DTOYWASM_USE_SMALL_CELLS=OFF + BUILD_COMMAND + cmake --build . + INSTALL_COMMAND + cmake --build . --target install +) + +set(TOYWASM_SOURCES + src/backend/wasm_toywasm.c +) +endif () # TOYWASM + + # MiniFB options set(MINIFB_BUILD_EXAMPLES OFF) set(USE_OPENGL_API OFF) @@ -51,7 +100,6 @@ add_subdirectory(vendor/cubeb) endif () file(GLOB COMMON_SOURCES RELATIVE "${CMAKE_SOURCE_DIR}" "src/*.c") -file(GLOB M3_SOURCES RELATIVE "${CMAKE_SOURCE_DIR}" "vendor/wasm3/source/*.c") # Include a strnlen polyfill for some platforms where it's missing (OSX PPC, maybe others) include(CheckSymbolExists) @@ -68,13 +116,24 @@ if (NOT LIBRETRO) set(MINIFB_SOURCES src/backend/main.c - src/backend/wasm_wasm3.c src/backend/window_minifb.c ) -add_executable(wasm4 ${COMMON_SOURCES} ${MINIFB_SOURCES} ${M3_SOURCES}) -target_include_directories(wasm4 PRIVATE "${CMAKE_SOURCE_DIR}/vendor/wasm3/source") -target_link_libraries(wasm4 minifb cubeb) +add_executable(wasm4 ${COMMON_SOURCES} ${MINIFB_SOURCES} + $<$:${WASM3_SOURCES}> + $<$:${TOYWASM_SOURCES}>) +if (TOYWASM) +add_dependencies(wasm4 toywasm) +endif () + +target_include_directories(wasm4 PRIVATE + $<$:${CMAKE_SOURCE_DIR}/vendor/wasm3/source> + $<$:${toywasm_tmp_install}/include>) +target_link_directories(wasm4 PRIVATE + $<$:${toywasm_tmp_install}/lib>) + +target_link_libraries(wasm4 minifb cubeb + $<$:toywasm-core>) set_target_properties(wasm4 PROPERTIES C_STANDARD 99) install(TARGETS wasm4) endif () @@ -117,15 +176,26 @@ endif () # set(LIBRETRO_SOURCES src/backend/main_libretro.c - src/backend/wasm_wasm3.c ) if(LIBRETRO_STATIC) - add_library(wasm4_libretro STATIC ${COMMON_SOURCES} ${LIBRETRO_SOURCES} ${M3_SOURCES}) + add_library(wasm4_libretro STATIC ${COMMON_SOURCES} ${LIBRETRO_SOURCES} + $<$:${WASM3_SOURCES}> + $<$:${TOYWASM_SOURCES}>) else() - add_library(wasm4_libretro SHARED ${COMMON_SOURCES} ${LIBRETRO_SOURCES} ${M3_SOURCES}) + add_library(wasm4_libretro SHARED ${COMMON_SOURCES} ${LIBRETRO_SOURCES} + $<$:${WASM3_SOURCES}> + $<$:${TOYWASM_SOURCES}>) endif() -target_include_directories(wasm4_libretro PRIVATE "${CMAKE_SOURCE_DIR}/vendor/wasm3/source") +if (TOYWASM) +add_dependencies(wasm4_libretro toywasm) +endif () +target_include_directories(wasm4_libretro PRIVATE + $<$:${CMAKE_SOURCE_DIR}/vendor/wasm3/source> + $<$:${toywasm_tmp_install}/include>) +target_link_directories(wasm4_libretro PRIVATE + $<$:${toywasm_tmp_install}/lib>) target_include_directories(wasm4_libretro PRIVATE "${CMAKE_SOURCE_DIR}/vendor/libretro/include") +target_link_libraries(wasm4_libretro $<$:toywasm-core>) set_target_properties(wasm4_libretro PROPERTIES C_STANDARD 99) install(TARGETS wasm4_libretro ARCHIVE DESTINATION lib diff --git a/runtimes/native/src/backend/wasm_toywasm.c b/runtimes/native/src/backend/wasm_toywasm.c new file mode 100644 index 00000000..983f46e1 --- /dev/null +++ b/runtimes/native/src/backend/wasm_toywasm.c @@ -0,0 +1,397 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../runtime.h" +#include "../wasm.h" + +static const struct memtype memtype = { + .lim = + { + .min = 1, + .max = 1, + }, + .flags = 0, +#if defined(TOYWASM_ENABLE_WASM_CUSTOM_PAGE_SIZES) + .page_shift = 16, +#endif +}; + +static struct mem_context mctx; +static struct meminst *meminst; +static struct import_object *host_import_obj; +static struct import_object *mem_import_obj; +static struct module *module; +static struct instance *instance; +static uint32_t start; +static uint32_t update; + +static void *convert_to_ptr(struct exec_context *ctx, uint32_t wp) { + /* + * XXX we can't perform proper bounds check because we don't + * know the size of the access. especially for things like tracef. + */ + void *p; + int ret = host_func_getptr(ctx, meminst, wp, 1, &p); + if (ret != 0) { + fprintf(stderr, + "host_func_getptr failed with %d: wasm ptr 0x%" PRIx32 "\n", + ret, wp); + if (ret == ETOYWASMTRAP) { + print_trace(ctx); + } + exit(1); + } + return p; +} + +#define W4_HOST_FUNC(n, t) HOST_FUNC_PREFIX(w4_, n, t) +#define W4_HOST_FUNC_DECL(n) HOST_FUNC_DECL(w4_##n) + +#define HOST_FUNC_PARAM_PTR(ft, params, i) \ + convert_to_ptr(ctx, HOST_FUNC_PARAM(ft, params, i, i32)) + +static W4_HOST_FUNC_DECL(blit) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *sprite = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t x = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t width = HOST_FUNC_PARAM(ft, params, 3, i32); + uint32_t height = HOST_FUNC_PARAM(ft, params, 4, i32); + uint32_t flags = HOST_FUNC_PARAM(ft, params, 5, i32); + w4_runtimeBlit(sprite, x, y, width, height, flags); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(blitSub) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *sprite = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t x = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t width = HOST_FUNC_PARAM(ft, params, 3, i32); + uint32_t height = HOST_FUNC_PARAM(ft, params, 4, i32); + uint32_t srcX = HOST_FUNC_PARAM(ft, params, 5, i32); + uint32_t srcY = HOST_FUNC_PARAM(ft, params, 6, i32); + uint32_t stride = HOST_FUNC_PARAM(ft, params, 7, i32); + uint32_t flags = HOST_FUNC_PARAM(ft, params, 8, i32); + w4_runtimeBlitSub(sprite, x, y, width, height, srcX, srcY, stride, flags); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(line) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + uint32_t x1 = HOST_FUNC_PARAM(ft, params, 0, i32); + uint32_t y1 = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t x2 = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t y2 = HOST_FUNC_PARAM(ft, params, 3, i32); + w4_runtimeLine(x1, y1, x2, y2); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(hline) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + uint32_t x = HOST_FUNC_PARAM(ft, params, 0, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t len = HOST_FUNC_PARAM(ft, params, 2, i32); + w4_runtimeHLine(x, y, len); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(vline) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + uint32_t x = HOST_FUNC_PARAM(ft, params, 0, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t len = HOST_FUNC_PARAM(ft, params, 2, i32); + w4_runtimeVLine(x, y, len); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(oval) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + uint32_t x = HOST_FUNC_PARAM(ft, params, 0, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t width = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t height = HOST_FUNC_PARAM(ft, params, 3, i32); + w4_runtimeOval(x, y, width, height); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(rect) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + uint32_t x = HOST_FUNC_PARAM(ft, params, 0, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t width = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t height = HOST_FUNC_PARAM(ft, params, 3, i32); + w4_runtimeRect(x, y, width, height); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(text) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *str = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t x = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 2, i32); + w4_runtimeText(str, x, y); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(textUtf8) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *str = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t byteLength = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t x = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 3, i32); + w4_runtimeTextUtf8(str, byteLength, x, y); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(textUtf16) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint16_t *str = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t byteLength = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t x = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t y = HOST_FUNC_PARAM(ft, params, 3, i32); + w4_runtimeTextUtf16(str, byteLength, x, y); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(tone) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + uint32_t frequency = HOST_FUNC_PARAM(ft, params, 0, i32); + uint32_t duration = HOST_FUNC_PARAM(ft, params, 1, i32); + uint32_t volume = HOST_FUNC_PARAM(ft, params, 2, i32); + uint32_t flags = HOST_FUNC_PARAM(ft, params, 3, i32); + w4_runtimeTone(frequency, duration, volume, flags); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(diskr) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + uint8_t *dest = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t size = HOST_FUNC_PARAM(ft, params, 1, i32); + int wasmret = w4_runtimeDiskr(dest, size); + HOST_FUNC_RESULT_SET(ft, results, 0, i32, wasmret); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(diskw) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *src = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t size = HOST_FUNC_PARAM(ft, params, 1, i32); + int wasmret = w4_runtimeDiskw(src, size); + HOST_FUNC_RESULT_SET(ft, results, 0, i32, wasmret); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(trace) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *str = HOST_FUNC_PARAM_PTR(ft, params, 0); + w4_runtimeTrace(str); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(traceUtf8) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *str = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t byteLength = HOST_FUNC_PARAM(ft, params, 1, i32); + w4_runtimeTraceUtf8(str, byteLength); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(traceUtf16) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint16_t *str = HOST_FUNC_PARAM_PTR(ft, params, 0); + uint32_t byteLength = HOST_FUNC_PARAM(ft, params, 1, i32); + w4_runtimeTraceUtf16(str, byteLength); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static W4_HOST_FUNC_DECL(tracef) { + HOST_FUNC_CONVERT_PARAMS(ft, params); + const uint8_t *str = HOST_FUNC_PARAM_PTR(ft, params, 0); + const void *stack = HOST_FUNC_PARAM_PTR(ft, params, 1); + w4_runtimeTracef(str, stack); + HOST_FUNC_FREE_CONVERTED_PARAMS(); + return 0; +} + +static const struct host_func host_inst_funcs[] = { + W4_HOST_FUNC(blit, "(iiiiii)"), W4_HOST_FUNC(blitSub, "(iiiiiiiii)"), + W4_HOST_FUNC(line, "(iiii)"), W4_HOST_FUNC(hline, "(iii)"), + W4_HOST_FUNC(vline, "(iii)"), W4_HOST_FUNC(oval, "(iiii)"), + W4_HOST_FUNC(rect, "(iiii)"), W4_HOST_FUNC(text, "(iii)"), + W4_HOST_FUNC(textUtf8, "(iiii)"), W4_HOST_FUNC(textUtf16, "(iiii)"), + W4_HOST_FUNC(tone, "(iiii)"), W4_HOST_FUNC(diskr, "(ii)i"), + W4_HOST_FUNC(diskw, "(ii)i"), W4_HOST_FUNC(trace, "(i)"), + W4_HOST_FUNC(traceUtf8, "(ii)"), W4_HOST_FUNC(traceUtf16, "(ii)"), + W4_HOST_FUNC(tracef, "(ii)"), +}; + +static const struct name name_env = NAME_FROM_CSTR_LITERAL("env"); +static const struct name name_memory = NAME_FROM_CSTR_LITERAL("memory"); + +static const struct host_module host_modules[] = {{ + .module_name = &name_env, + .funcs = host_inst_funcs, + .nfuncs = ARRAYCOUNT(host_inst_funcs), +}}; + +uint8_t *w4_wasmInit() { + int ret; + mem_context_init(&mctx); + ret = memory_instance_create(&mctx, &meminst, &memtype); + if (ret != 0) { + fprintf(stderr, "memory_instance_create failed with %d\n", ret); + exit(1); + } + void *p; + bool moved; + ret = memory_instance_getptr2(meminst, 0, 0, 64 * 1024, &p, &moved); + if (ret != 0) { + fprintf(stderr, "memory_instance_getptr2 failed with %d\n", ret); + exit(1); + } + return p; +} + +void w4_wasmDestroy() { + if (instance != NULL) { + instance_destroy(instance); + } + if (module != NULL) { + module_destroy(&mctx, module); + } + if (host_import_obj != NULL) { + import_object_destroy(&mctx, host_import_obj); + } + if (mem_import_obj != NULL) { + import_object_destroy(&mctx, mem_import_obj); + } + if (meminst != NULL) { + memory_instance_destroy(&mctx, meminst); + } + mem_context_clear(&mctx); +} + +static uint32_t find_func(const struct module *m, const char *name_cstr, + bool require) { + struct name name; + uint32_t idx; + int ret; + set_name_cstr(&name, name_cstr); + ret = module_find_export(m, &name, EXTERNTYPE_FUNC, &idx); + if (ret != 0) { + if (!require) { + return (uint32_t)-1; + } + fprintf(stderr, "module_find_export (%s) failed with %d\n", name_cstr, + ret); + exit(1); + } + return idx; +} + +int run_func(struct instance *inst, uint32_t funcidx) { + struct exec_context ctx; + int ret; + exec_context_init(&ctx, inst, &mctx); + ret = instance_execute_func_nocheck(&ctx, funcidx); + ret = instance_execute_handle_restart(&ctx, ret); + if (ret == ETOYWASMTRAP) { + fprintf(stderr, "wasm function execution failed: %s\n", + report_getmessage(ctx.report)); + print_trace(&ctx); + exit(1); + } + exec_context_clear(&ctx); + return ret; +} + +void w4_wasmLoadModule(const uint8_t *wasmBuffer, int byteLength) { + struct import_object *import_obj; + int ret; + + ret = import_object_alloc(&mctx, 1, &mem_import_obj); + if (ret != 0) { + fprintf(stderr, "import_object_alloc failed with %d\n", ret); + exit(1); + } + mem_import_obj->entries[0].module_name = &name_env; + mem_import_obj->entries[0].name = &name_memory; + mem_import_obj->entries[0].type = EXTERNTYPE_MEMORY; + mem_import_obj->entries[0].u.mem = meminst; + ret = import_object_create_for_host_funcs( + &mctx, host_modules, ARRAYCOUNT(host_modules), NULL, &host_import_obj); + if (ret != 0) { + fprintf(stderr, "import_object_create_for_host_funcs failed with %d\n", + ret); + exit(1); + } + import_obj = host_import_obj; + host_import_obj->next = mem_import_obj; + + struct load_context lctx; + load_context_init(&lctx, &mctx); + ret = module_create(&module, wasmBuffer, wasmBuffer + byteLength, &lctx); + if (ret != 0) { + fprintf(stderr, "module_create failed with %d: %s\n", ret, + report_getmessage(&lctx.report)); + exit(1); + } + load_context_clear(&lctx); + + struct report report; + report_init(&report); + ret = instance_create(&mctx, module, &instance, import_obj, &report); + if (ret != 0) { + fprintf(stderr, "instance_create failed with %d: %s\n", ret, + report_getmessage(&report)); + exit(1); + } + report_clear(&report); + + start = find_func(module, "start", false); + update = find_func(module, "update", true); + uint32_t init = find_func(module, "_initialize", false); + if (init != (uint32_t)-1) { + run_func(instance, init); + } +} + +void w4_wasmCallStart() { + if (start != (uint32_t)-1) { + run_func(instance, start); + } +} + +void w4_wasmCallUpdate() { + if (update != (uint32_t)-1) { + run_func(instance, update); + } +} From 410c53de9d12817d02c8017baa95a37cb66952cb Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 03/11] CI: build with toywasm --- .github/workflows/build.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35376b1d..54bbe31b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,11 @@ jobs: wasm4: bin/wasm4 libretro: lib/wasm4_libretro.so + wasm_runtime: + - wasm3 + + - toywasm + name: Build ${{ matrix.config.artifact }} runs-on: ${{ matrix.config.os }} defaults: @@ -43,7 +48,7 @@ jobs: - name: Build run: | - cmake -B build -DCMAKE_BUILD_TYPE=Release + cmake -B build -DCMAKE_BUILD_TYPE=Release -DWASM_RUNTIME=${{ matrix.wasm_runtime }} cmake --build build --config Release --parallel - name: Install @@ -53,13 +58,13 @@ jobs: uses: actions/upload-artifact@v4.4.0 with: path: runtimes/native/instdir/${{ matrix.config.wasm4 }} - name: wasm4-${{ matrix.config.artifact }} + name: wasm4-${{ matrix.wasm_runtime }}-${{ matrix.config.artifact }} - name: Upload libretro artifact uses: actions/upload-artifact@v4.4.0 with: path: runtimes/native/instdir/${{ matrix.config.libretro }} - name: wasm4-libretro-${{ matrix.config.artifact }} + name: wasm4-libretro-${{ matrix.wasm_runtime }}-${{ matrix.config.artifact }} build-cli: name: Build w4 CLI @@ -95,9 +100,9 @@ jobs: run: | mkdir -p assets/natives ls -R ../artifacts - mv ../artifacts/wasm4-windows/wasm4.exe assets/natives/wasm4-windows.exe - mv ../artifacts/wasm4-mac/wasm4 assets/natives/wasm4-mac - mv ../artifacts/wasm4-linux/wasm4 assets/natives/wasm4-linux + mv ../artifacts/wasm4-wasm3-windows/wasm4.exe assets/natives/wasm4-windows.exe + mv ../artifacts/wasm4-wasm3-mac/wasm4 assets/natives/wasm4-mac + mv ../artifacts/wasm4-wasm3-linux/wasm4 assets/natives/wasm4-linux chmod +x assets/natives/wasm4-* - name: Test CLI From e4bd318c3e30affd38622057a9dbb6a5eba7ebb3 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 04/11] CI: exclude windows + toywasm --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54bbe31b..79aa2e10 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,6 +28,12 @@ jobs: - toywasm + # toywasm doesn't support windows + exclude: + - wasm_runtime: toywasm + config: + os: windows-latest + name: Build ${{ matrix.config.artifact }} runs-on: ${{ matrix.config.os }} defaults: From b6975e760ae6375740e28d0ccb06889ccb97659d Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 05/11] bump toywasm to v63.0.0 --- runtimes/native/vendor/toywasm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtimes/native/vendor/toywasm b/runtimes/native/vendor/toywasm index 8c77bbb6..d7bb4aae 160000 --- a/runtimes/native/vendor/toywasm +++ b/runtimes/native/vendor/toywasm @@ -1 +1 @@ -Subproject commit 8c77bbb6e058700bb018cd7f3170752b187b53a2 +Subproject commit d7bb4aaef08be2d7821891f17bd9ef82ac1ba358 From c874e6237c85dd58ce930c913eb02ee0fdf3805d Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 06/11] Revert "CI: exclude windows + toywasm" This reverts commit 73a255ce09439f61a5b7a310d1bd1ed0c8410db2. --- .github/workflows/build.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79aa2e10..54bbe31b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,12 +28,6 @@ jobs: - toywasm - # toywasm doesn't support windows - exclude: - - wasm_runtime: toywasm - config: - os: windows-latest - name: Build ${{ matrix.config.artifact }} runs-on: ${{ matrix.config.os }} defaults: From b6a9b1c53a10034e3f264ce1e3b6dbb97b901e8f Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 07/11] bump toywasm version a bit --- runtimes/native/vendor/toywasm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtimes/native/vendor/toywasm b/runtimes/native/vendor/toywasm index d7bb4aae..4924e0ef 160000 --- a/runtimes/native/vendor/toywasm +++ b/runtimes/native/vendor/toywasm @@ -1 +1 @@ -Subproject commit d7bb4aaef08be2d7821891f17bd9ef82ac1ba358 +Subproject commit 4924e0efe7785b2482131a681928a61ca9916910 From 984163a5307ee7a709012143d07f1c38094dd64b Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:18 +0900 Subject: [PATCH 08/11] rename WASM_RUNTIME to WASM_BACKEND to match the naming used here. (src/backend) --- runtimes/native/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runtimes/native/CMakeLists.txt b/runtimes/native/CMakeLists.txt index 9ee45e1b..23459ad8 100644 --- a/runtimes/native/CMakeLists.txt +++ b/runtimes/native/CMakeLists.txt @@ -1,16 +1,16 @@ cmake_minimum_required(VERSION 3.7) project(WASM4) -set(WASM_RUNTIME "wasm3" CACHE STRING "webassembly runtime") +set(WASM_BACKEND "wasm3" CACHE STRING "webassembly runtime") set (WASM3 OFF) set (TOYWASM OFF) -if (WASM_RUNTIME STREQUAL "wasm3") +if (WASM_BACKEND STREQUAL "wasm3") set (WASM3 ON) -elseif (WASM_RUNTIME STREQUAL "toywasm") +elseif (WASM_BACKEND STREQUAL "toywasm") set (TOYWASM ON) else () -message (FATAL_ERROR "Unrecognized WASM_RUNTIME value: ${WASM_RUNTIME}") +message (FATAL_ERROR "Unrecognized WASM_BACKEND value: ${WASM_BACKEND}") endif () # Prevent BUILD_SHARED_LIBS and other options from being cleared by vendor CMakeLists From 63ddcc6660eeb7b746574a3ce6f167d324467948 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:19 +0900 Subject: [PATCH 09/11] rename WASM_RUNTIME to WASM_BACKEND --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54bbe31b..d7fd1ac5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: wasm4: bin/wasm4 libretro: lib/wasm4_libretro.so - wasm_runtime: + wasm_backend: - wasm3 - toywasm @@ -48,7 +48,7 @@ jobs: - name: Build run: | - cmake -B build -DCMAKE_BUILD_TYPE=Release -DWASM_RUNTIME=${{ matrix.wasm_runtime }} + cmake -B build -DCMAKE_BUILD_TYPE=Release -DWASM_BACKEND=${{ matrix.wasm_backend }} cmake --build build --config Release --parallel - name: Install @@ -58,13 +58,13 @@ jobs: uses: actions/upload-artifact@v4.4.0 with: path: runtimes/native/instdir/${{ matrix.config.wasm4 }} - name: wasm4-${{ matrix.wasm_runtime }}-${{ matrix.config.artifact }} + name: wasm4-${{ matrix.wasm_backend }}-${{ matrix.config.artifact }} - name: Upload libretro artifact uses: actions/upload-artifact@v4.4.0 with: path: runtimes/native/instdir/${{ matrix.config.libretro }} - name: wasm4-libretro-${{ matrix.wasm_runtime }}-${{ matrix.config.artifact }} + name: wasm4-libretro-${{ matrix.wasm_backend }}-${{ matrix.config.artifact }} build-cli: name: Build w4 CLI From 82caf6dbf6d8db4e05c92b512e55edc385f739e3 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 15 Aug 2024 23:51:19 +0900 Subject: [PATCH 10/11] runtimes/native: toywasm: limit memory usage for better sandboxing --- runtimes/native/src/backend/wasm_toywasm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/runtimes/native/src/backend/wasm_toywasm.c b/runtimes/native/src/backend/wasm_toywasm.c index 983f46e1..b515ef3e 100644 --- a/runtimes/native/src/backend/wasm_toywasm.c +++ b/runtimes/native/src/backend/wasm_toywasm.c @@ -265,6 +265,16 @@ static const struct host_module host_modules[] = {{ uint8_t *w4_wasmInit() { int ret; mem_context_init(&mctx); + /* + * set an arbitrary limit. + * this includes the 64KB linear memory. + * REVISIT: how much operand stack etc typical carts can consume? + */ + ret = mem_context_setlimit(&mctx, 128 * 1024); + if (ret != 0) { + fprintf(stderr, "failed to set memory limit with %d\n", ret); + exit(1); + } ret = memory_instance_create(&mctx, &meminst, &memtype); if (ret != 0) { fprintf(stderr, "memory_instance_create failed with %d\n", ret); From f9809af698af144f9b747347d9a5a8acb976c117 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 25 Sep 2024 20:14:28 +0900 Subject: [PATCH 11/11] runtimes/native/README.md: document WASM_BACKEND option --- runtimes/native/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/runtimes/native/README.md b/runtimes/native/README.md index ce667dfe..a55d5646 100644 --- a/runtimes/native/README.md +++ b/runtimes/native/README.md @@ -19,6 +19,18 @@ cmake -B build cmake --build build ``` +By default, it uses [wasm3] as a WebAssembly runtime. +Alternatively, you can use [toywasm] instead by setting +the `WASM_BACKEND` cmake option: + +```shell +cmake -B build -DWASM_BACKEND=toywasm +cmake --build build +``` + +[wasm3]: https://github.com/wasm3/wasm3 +[toywasm]: https://github.com/yamt/toywasm + Running: ```shell