From 7d2afbac956fc5694cecb525749181d646128e48 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sun, 5 Dec 2021 09:29:31 -0600 Subject: [PATCH] working example of loading a library and dynamically linking functions! --- build.sh | 2 +- {misc => include}/onyx_library.h | 12 +++--- modules/test_library/module.onyx | 6 ++- modules/test_library/test_library.c | 20 +++++++++ src/wasm_runtime.c | 63 +++++++++++++++++++++++------ 5 files changed, 82 insertions(+), 21 deletions(-) rename {misc => include}/onyx_library.h (91%) diff --git a/build.sh b/build.sh index 6fb93aa9..d13c6e58 100755 --- a/build.sh +++ b/build.sh @@ -45,7 +45,7 @@ fi C_FILES="$C_FILES wasm_runtime" FLAGS="$FLAGS -DENABLE_RUN_WITH_WASMER -rdynamic" -LIBS="-L$CORE_DIR/lib -lwasmer -Wl,-rpath=$CORE_DIR/lib -lpthread -ldl" +LIBS="-L$CORE_DIR/lib -lwasmer -Wl,-rpath=$CORE_DIR/lib:./ -lpthread -ldl" INCLUDES="-I$WASMER_INCLUDE_DIR" mkdir -p "$BUILD_DIR" diff --git a/misc/onyx_library.h b/include/onyx_library.h similarity index 91% rename from misc/onyx_library.h rename to include/onyx_library.h index d9d9ed17..2f7e8a5e 100644 --- a/misc/onyx_library.h +++ b/include/onyx_library.h @@ -18,6 +18,7 @@ typedef struct WasmFuncDefinition { } WasmFuncDefinition; #define STRINGIFY1(a) #a +#define STRINGIFY2(a) STRINGIFY1(a) #define CONCAT2(a, b) a ## _ ## b #define CONCAT3(a, b, c) a ## _ ## b ## _ ## c #define ONYX_MODULE_NAME_GEN(m) CONCAT2(__onyx_library, m) @@ -35,7 +36,7 @@ typedef struct WasmFuncDefinition { static wasm_trap_t* ONYX_FUNC_NAME(ONYX_LIBRARY_NAME, name)(const wasm_val_vec_t* params, wasm_val_vec_t* results); \ static struct WasmValkindBuffer ONYX_PARAM_NAME(ONYX_LIBRARY_NAME, name) = _VALS params_types; \ static struct WasmValkindBuffer ONYX_RESULT_NAME(ONYX_LIBRARY_NAME, name) = _VALS result_types; \ - static struct WasmFuncDefinition ONYX_DEF_NAME(ONYX_LIBRARY_NAME, name) = { STRINGIFY1(ONYX_LIBRARY_NAME), #name, ONYX_FUNC_NAME(ONYX_LIBRARY_NAME, name), & ONYX_PARAM_NAME(ONYX_LIBRARY_NAME, name), & ONYX_RESULT_NAME(ONYX_LIBRARY_NAME, name) }; \ + static struct WasmFuncDefinition ONYX_DEF_NAME(ONYX_LIBRARY_NAME, name) = { STRINGIFY2(ONYX_LIBRARY_NAME), #name, ONYX_FUNC_NAME(ONYX_LIBRARY_NAME, name), & ONYX_PARAM_NAME(ONYX_LIBRARY_NAME, name), & ONYX_RESULT_NAME(ONYX_LIBRARY_NAME, name) }; \ \ static wasm_trap_t* ONYX_FUNC_NAME(ONYX_LIBRARY_NAME, name)(const wasm_val_vec_t* params, wasm_val_vec_t* results) @@ -48,7 +49,8 @@ typedef struct WasmFuncDefinition { struct WasmFuncDefinition *ONYX_MODULE_NAME_GEN(ONYX_LIBRARY_NAME)[] = // Shorter names -#define I32 WASM_I32 -#define I64 WASM_I64 -#define F32 WASM_F32 -#define F64 WASM_F64 +#define INT WASM_I32 +#define LONG WASM_I64 +#define FLOAT WASM_F32 +#define DOUBLE WASM_F64 +#define PTR WASM_I32 diff --git a/modules/test_library/module.onyx b/modules/test_library/module.onyx index 7b505cb6..b0f3d387 100644 --- a/modules/test_library/module.onyx +++ b/modules/test_library/module.onyx @@ -1,5 +1,7 @@ package test_library -#library "test_library" +// #library "test_library" -foo :: () -> void #foreign "test_library" "foo" --- \ No newline at end of file +foo :: () -> void #foreign "test_library" "foo" --- +add :: (a, b: i32) -> i32 #foreign "test_library" "add" --- +print_string :: (s: str) -> void #foreign "test_library" "print_string" --- \ No newline at end of file diff --git a/modules/test_library/test_library.c b/modules/test_library/test_library.c index 08df6ad9..16e1b0f6 100644 --- a/modules/test_library/test_library.c +++ b/modules/test_library/test_library.c @@ -1,5 +1,6 @@ #include "onyx_library.h" #include +#include #define ONYX_LIBRARY_NAME test_library @@ -8,6 +9,25 @@ ONYX_DEF(foo, (), ()) { return NULL; } +ONYX_DEF(add, (INT, INT), (INT)) { + int a = params->data[0].of.i32; + int b = params->data[1].of.i32; + results->data[0] = WASM_I32_VAL(a + b); + return NULL; +} + +ONYX_DEF(print_string, (PTR, INT), ()) { + char *start = wasm_memory_data(wasm_memory) + params->data[0].of.i32; + int length = params->data[1].of.i32; + + write(1, start, length); + return NULL; +} + ONYX_LIBRARY { ONYX_FUNC(foo) + ONYX_FUNC(add) + ONYX_FUNC(print_string) + + NULL }; \ No newline at end of file diff --git a/src/wasm_runtime.c b/src/wasm_runtime.c index 3ca0ccf6..816093dd 100644 --- a/src/wasm_runtime.c +++ b/src/wasm_runtime.c @@ -8,6 +8,7 @@ #include #include #include + #include #endif #ifndef WASMER_VERSION @@ -498,11 +499,34 @@ WASM_INTEROP(onyx_process_destroy_impl) { return NULL; } -#include +#include "onyx_library.h" + +typedef void *(*LibraryLinker)(); +static bh_arr(WasmFuncDefinition **) linkable_functions = NULL; + +static void onyx_load_library(char *name) { + char *library_load_name = bh_aprintf(global_scratch_allocator, "onyx_library_%s", name); + LibraryLinker library_load; + + #ifdef _BH_LINUX + char *library_name = bh_aprintf(global_scratch_allocator, "%s.so", name); + void* handle = dlopen(library_name, RTLD_LAZY); + if (handle == NULL) { + printf("ERROR LOADING LIBRARY %s: %s\n", name, dlerror()); + return; + } + + library_load = (LibraryLinker) dlsym(handle, library_load_name); + #endif + + WasmFuncDefinition** funcs = library_load(); + bh_arr_push(linkable_functions, funcs); +} // Returns 1 if successful b32 onyx_run_wasm(bh_buffer wasm_bytes) { - + bh_arr_new(global_heap_allocator, linkable_functions, 4); + onyx_load_library("test_library"); wasm_instance_t* instance = NULL; wasmer_features_t* features = NULL; @@ -666,6 +690,30 @@ b32 onyx_run_wasm(bh_buffer wasm_bytes) { } } + bh_arr_each(WasmFuncDefinition **, library_funcs, linkable_functions) { + WasmFuncDefinition **pcurrent_function = *library_funcs; + while (*pcurrent_function != NULL) { + WasmFuncDefinition *cf = *pcurrent_function; + if (wasm_name_equals_string(module_name, cf->module_name) && wasm_name_equals_string(import_name, cf->import_name)) { + wasm_valtype_vec_t wasm_params; + wasm_valtype_vec_new_uninitialized(&wasm_params, cf->params->count); + fori (k, 0, cf->params->count) wasm_params.data[k] = wasm_valtype_new(cf->params->types[k]); + + wasm_valtype_vec_t wasm_results; + wasm_valtype_vec_new_uninitialized(&wasm_results, cf->results->count); + fori (k, 0, cf->results->count) wasm_results.data[k] = wasm_valtype_new(cf->results->types[k]); + + wasm_functype_t* wasm_functype = wasm_functype_new(&wasm_params, &wasm_results); + + wasm_func_t* wasm_func = wasm_func_new(wasm_store, wasm_functype, cf->func); + import = wasm_func_as_extern(wasm_func); + goto import_found; + } + + pcurrent_function += 1; + } + } + goto bad_import; import_found: @@ -680,17 +728,6 @@ b32 onyx_run_wasm(bh_buffer wasm_bytes) { wasm_trap_t* traps = NULL; - // NOCHECKIN - void* handle = dlopen("./test_library.so", RTLD_LAZY); - printf("HANDLE: %p\n", handle); - if (handle == NULL) { - printf("ERROR: %s\n", dlerror()); - } - void *wasm_library = dlsym(handle, "onyx_library_test_library"); - printf("LOADED: %p\n", wasm_library); - printf("TABLE: %p\n", ((void* (*)()) wasm_library)()); - dlclose(handle); - instance = wasm_instance_new(wasm_store, wasm_module, &wasm_imports, &traps); if (!instance) goto error_handling; -- 2.25.1