From 4904aa341be9c74dec28e6eeea79b707211f2f06 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 26 Oct 2023 22:43:46 +0100 Subject: Add a basic C based wasmtime runtime This can be used for creating an equivalent rust based runtime with C bindings. Signed-off-by: Andrew Clayton --- c/wasmtime-basic/.gitignore | 2 + c/wasmtime-basic/Makefile | 17 ++++++ c/wasmtime-basic/test.c | 26 +++++++++ c/wasmtime-basic/wasmtime.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 c/wasmtime-basic/.gitignore create mode 100644 c/wasmtime-basic/Makefile create mode 100644 c/wasmtime-basic/test.c create mode 100644 c/wasmtime-basic/wasmtime.c diff --git a/c/wasmtime-basic/.gitignore b/c/wasmtime-basic/.gitignore new file mode 100644 index 0000000..17d08f1 --- /dev/null +++ b/c/wasmtime-basic/.gitignore @@ -0,0 +1,2 @@ +test.wasm +wasmtime diff --git a/c/wasmtime-basic/Makefile b/c/wasmtime-basic/Makefile new file mode 100644 index 0000000..ad70fce --- /dev/null +++ b/c/wasmtime-basic/Makefile @@ -0,0 +1,17 @@ +CC = gcc +CFLAGS = -Wall -Wextra -g -I$(WASMTIME_C_API)/include -L$(WASMTIME_C_API)/lib +LDFLAGS = -Wl,-rpath,$(WASMTIME_C_API)/lib + +WASM_CC = clang +WASM_CFLAGS = -Wall -Wextra -fno-strict-aliasing --target=wasm32-wasi --sysroot=$(WASI_SYSROOT) + +all: wasmtime test.wasm + +wasmtime: wasmtime.c + $(CC) $(CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< -lwasmtime + +test.wasm: test.c + $(WASM_CC) $(WASM_CFLAGS) -o $@ $< + +clean: + rm -f wasmtime test.wasm diff --git a/c/wasmtime-basic/test.c b/c/wasmtime-basic/test.c new file mode 100644 index 0000000..f6e8723 --- /dev/null +++ b/c/wasmtime-basic/test.c @@ -0,0 +1,26 @@ +/* + * test.c + */ + +#include + +typedef uint32_t u32; +typedef uint8_t u8; + +__attribute__((import_module("env"), import_name("imported_func"))) +void imported_func(void); + +__attribute__((export_name("exported_func"))) +int exported_func(u8 *addr, u32 mem_size) +{ + (void)addr; + (void)mem_size; + imported_func(); + + return 0; +} + +int main(void) +{ + return 0; +} diff --git a/c/wasmtime-basic/wasmtime.c b/c/wasmtime-basic/wasmtime.c new file mode 100644 index 0000000..90ff0a3 --- /dev/null +++ b/c/wasmtime-basic/wasmtime.c @@ -0,0 +1,128 @@ +#include +#include + +#include +#include +#include + +static void exit_with_error(const char *message, wasmtime_error_t *error, + wasm_trap_t *trap) +{ + wasm_byte_vec_t error_message; + + fprintf(stderr, "error: %s\n", message); + if (error != NULL) { + wasmtime_error_message(error, &error_message); + wasmtime_error_delete(error); + } else { + wasm_trap_message(trap, &error_message); + wasm_trap_delete(trap); + } + fprintf(stderr, "%.*s\n", (int) error_message.size, error_message.data); + wasm_byte_vec_delete(&error_message); + + exit(1); +} + +static wasm_trap_t *imported_func(void *env, wasmtime_caller_t *caller, + const wasmtime_val_t *args, size_t nargs, + wasmtime_val_t *results, size_t nresults) +{ + (void)env; + (void)caller; + (void)args; + (void)nargs; + (void)results; + (void)nresults; + + return NULL; +} + +int main(void) +{ + wasm_engine_t *engine; + wasmtime_store_t *store; + wasmtime_context_t *context; + wasmtime_module_t *module = NULL; + wasmtime_linker_t *linker; + wasmtime_error_t *error; + wasm_byte_vec_t wasm; + wasmtime_extern_t item; + wasm_functype_t *func_ty; + wasi_config_t *wasi_config; + FILE *file; + size_t file_size; + bool ok; + + printf("Initializing...\n"); + engine = wasm_engine_new(); + store = wasmtime_store_new(engine, NULL, NULL); + context = wasmtime_store_context(store); + + linker = wasmtime_linker_new(engine); + error = wasmtime_linker_define_wasi(linker); + if (error != NULL) + exit_with_error("failed to link wasi", error, NULL); + + printf("Loading binary...\n"); + file = fopen("test.wasm", "rb"); + if (!file) { + printf("> Error loading file!\n"); + exit(1); + } + fseek(file, 0L, SEEK_END); + file_size = ftell(file); + wasm_byte_vec_new_uninitialized(&wasm, file_size); + fseek(file, 0L, SEEK_SET); + if (fread(wasm.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + exit(1); + } + fclose(file); + + printf("Compiling module...\n"); + error = wasmtime_module_new(engine, (uint8_t*)wasm.data, wasm.size, + &module); + if (!module) + exit_with_error("failed to compile module", error, NULL); + wasm_byte_vec_delete(&wasm); + + printf("Setting fumction import...\n"); + func_ty = wasm_functype_new_0_0(); + wasmtime_linker_define_func(linker, "env", 3, + "imported_func", 13, func_ty, + imported_func, context, NULL); + wasm_functype_delete(func_ty); + + printf("Initialising WASI...\n"); + wasi_config = wasi_config_new(); + wasi_config_inherit_env(wasi_config); + wasi_config_inherit_stdin(wasi_config); + wasi_config_inherit_stdout(wasi_config); + wasi_config_inherit_stderr(wasi_config); + error = wasmtime_context_set_wasi(context, wasi_config); + if (error) + exit_with_error("failed to initialise WASI", error, NULL); + + printf("Instantiating module...\n"); + error = wasmtime_linker_module(linker, context, "", 0, module); + if (error != NULL) + exit_with_error("failed to instantiate module", error, NULL); + + printf("Getting function export...\n"); + ok = wasmtime_linker_get(linker, context, "", 0, "exported_func", 13, + &item); + if (!ok) { + printf("> Error getting function export\n"); + exit(1); + } + + printf("Shutting down...\n"); + wasmtime_module_delete(module); + wasmtime_store_delete(store); + wasm_engine_delete(engine); + + printf("Done.\n"); + + return 0; +} -- cgit