From: Brendan Hansen Date: Sun, 5 Dec 2021 15:29:31 +0000 (-0600) Subject: working example of loading a library and dynamically linking functions! X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=7d2afbac956fc5694cecb525749181d646128e48;p=onyx.git working example of loading a library and dynamically linking functions! --- 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/include/onyx_library.h b/include/onyx_library.h new file mode 100644 index 00000000..2f7e8a5e --- /dev/null +++ b/include/onyx_library.h @@ -0,0 +1,56 @@ + +#include "wasm.h" + +extern wasm_memory_t* wasm_memory; + +typedef struct WasmValkindBuffer { + unsigned int count; + wasm_valkind_t types[20]; +} WasmValkindBuffer; + +typedef struct WasmFuncDefinition { + char* module_name; + char* import_name; + wasm_func_callback_t func; + + WasmValkindBuffer *params; + WasmValkindBuffer *results; +} 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) +#define ONYX_LINK_NAME_GEN(m) CONCAT2(onyx_library, m) +#define ONYX_FUNC_NAME(m, n) CONCAT3(__onyx_internal, m, n) +#define ONYX_DEF_NAME(m, n) CONCAT3(__onyx_internal_def, m, n) +#define ONYX_PARAM_NAME(m, n) CONCAT3(__onyx_internal_param_buffer, m, n) +#define ONYX_RESULT_NAME(m, n) CONCAT3(__onyx_internal_result_buffer, m, n) +#define ONYX_IMPORT_NAME(m, n) STRINGIFY1(m) "_" #n + +#define NUM_VALS(...) (sizeof((wasm_valkind_t []){ 0, __VA_ARGS__ }) / sizeof(wasm_valkind_t)) +#define _VALS(...) { NUM_VALS(__VA_ARGS__) - 1, __VA_ARGS__ } + +#define ONYX_DEF(name, params_types, result_types) \ + 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) = { 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) + +#define ONYX_FUNC(name) & ONYX_DEF_NAME(ONYX_LIBRARY_NAME, name), +#define ONYX_LIBRARY \ + extern struct WasmFuncDefinition *ONYX_MODULE_NAME_GEN(ONYX_LIBRARY_NAME)[]; \ + WasmFuncDefinition** ONYX_LINK_NAME_GEN(ONYX_LIBRARY_NAME)() { \ + return ONYX_MODULE_NAME_GEN(ONYX_LIBRARY_NAME); \ + } \ + struct WasmFuncDefinition *ONYX_MODULE_NAME_GEN(ONYX_LIBRARY_NAME)[] = + +// Shorter names +#define INT WASM_I32 +#define LONG WASM_I64 +#define FLOAT WASM_F32 +#define DOUBLE WASM_F64 +#define PTR WASM_I32 diff --git a/misc/onyx_library.h b/misc/onyx_library.h deleted file mode 100644 index d9d9ed17..00000000 --- a/misc/onyx_library.h +++ /dev/null @@ -1,54 +0,0 @@ - -#include "wasm.h" - -extern wasm_memory_t* wasm_memory; - -typedef struct WasmValkindBuffer { - unsigned int count; - wasm_valkind_t types[20]; -} WasmValkindBuffer; - -typedef struct WasmFuncDefinition { - char* module_name; - char* import_name; - wasm_func_callback_t func; - - WasmValkindBuffer *params; - WasmValkindBuffer *results; -} WasmFuncDefinition; - -#define STRINGIFY1(a) #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) -#define ONYX_LINK_NAME_GEN(m) CONCAT2(onyx_library, m) -#define ONYX_FUNC_NAME(m, n) CONCAT3(__onyx_internal, m, n) -#define ONYX_DEF_NAME(m, n) CONCAT3(__onyx_internal_def, m, n) -#define ONYX_PARAM_NAME(m, n) CONCAT3(__onyx_internal_param_buffer, m, n) -#define ONYX_RESULT_NAME(m, n) CONCAT3(__onyx_internal_result_buffer, m, n) -#define ONYX_IMPORT_NAME(m, n) STRINGIFY1(m) "_" #n - -#define NUM_VALS(...) (sizeof((wasm_valkind_t []){ 0, __VA_ARGS__ }) / sizeof(wasm_valkind_t)) -#define _VALS(...) { NUM_VALS(__VA_ARGS__) - 1, __VA_ARGS__ } - -#define ONYX_DEF(name, params_types, result_types) \ - 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 wasm_trap_t* ONYX_FUNC_NAME(ONYX_LIBRARY_NAME, name)(const wasm_val_vec_t* params, wasm_val_vec_t* results) - -#define ONYX_FUNC(name) & ONYX_DEF_NAME(ONYX_LIBRARY_NAME, name), -#define ONYX_LIBRARY \ - extern struct WasmFuncDefinition *ONYX_MODULE_NAME_GEN(ONYX_LIBRARY_NAME)[]; \ - WasmFuncDefinition** ONYX_LINK_NAME_GEN(ONYX_LIBRARY_NAME)() { \ - return ONYX_MODULE_NAME_GEN(ONYX_LIBRARY_NAME); \ - } \ - 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 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;