summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Clayton <a.clayton@nginx.com>2023-10-26 22:43:46 +0100
committerAndrew Clayton <a.clayton@nginx.com>2023-10-26 22:51:19 +0100
commit4904aa341be9c74dec28e6eeea79b707211f2f06 (patch)
tree42666e982dc311b409f315a578e673664dce9d24
parent3aed80812e105cd99c43f11023012608aecd9f4a (diff)
downloadproject_blackbird-4904aa341be9c74dec28e6eeea79b707211f2f06.tar.gz
project_blackbird-4904aa341be9c74dec28e6eeea79b707211f2f06.tar.bz2
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 <a.clayton@nginx.com>
Diffstat (limited to '')
-rw-r--r--c/wasmtime-basic/.gitignore2
-rw-r--r--c/wasmtime-basic/Makefile17
-rw-r--r--c/wasmtime-basic/test.c26
-rw-r--r--c/wasmtime-basic/wasmtime.c128
4 files changed, 173 insertions, 0 deletions
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 <stdint.h>
+
+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 <stdio.h>
+#include <stdlib.h>
+
+#include <wasm.h>
+#include <wasi.h>
+#include <wasmtime.h>
+
+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;
+}