refactoring native_funcs out of program to state
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 19 Jun 2022 04:15:18 +0000 (23:15 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 19 Jun 2022 04:15:18 +0000 (23:15 -0500)
docs/wasm_wtf.md [new file with mode: 0644]
include/onyx_wasm.h
include/vm.h
src/cli.c
src/vm/program_loader.c
src/vm/vm.c
src/wasm/type.c

diff --git a/docs/wasm_wtf.md b/docs/wasm_wtf.md
new file mode 100644 (file)
index 0000000..be20c4e
--- /dev/null
@@ -0,0 +1,48 @@
+# How TF do you use WASM-C-API
+
+In the WASM-C-API, this is the rough construction order
+for objects to run a simple `.wasm` binary.
+
+```
+    config := wasm_config_new();
+    // Set configs...
+    engine := wasm_engine_new_with_config(config)
+
+    store  := wasm_store_new(engine);
+
+    module := wasm_module_new(store, module_bytes);
+
+    import_vector: wasm_extern_vec_t;
+    wasm_extern_vec_new_unintialized(&import_vector, size);
+
+    // Fill in imports using wasm_..._as_extern
+
+    instance := wasm_instance_new(store, module, import_vector, traps);
+```
+
+
+In the OVM, this is the rough construction order for objects.
+
+```
+    store  := ovm_store_new();
+    prog   := ovm_program_new(store);
+    engine := ovm_engine_new(store);
+
+    ovm_program_load_from_file(prog, engine, filename);
+    ovm_program_link_native_funcs(prog, native_funcs);
+
+    state := ovm_state_new(engine, prog);
+
+    ovm_func_call(engine, state, prog, func, arg_count, args);
+```
+
+
+
+Roughly, these concepts correspond between OVM and WASM
+
+OVM Store   <-> Nothing (but is stored on WASM Engine)
+OVM Program <-> WASM Module
+OVM Engine  <-> WASM Engine
+OVM State   <-> WASM Instance
+
+
index e388dea66f4dab3cbc9ec095ca1d981b6c057ed5..fa1ddc01437c2465fb1c98fea40e0478a7403bee 100644 (file)
@@ -10,6 +10,8 @@ struct wasm_config_t {
     bool debug_enabled;
 };
 
+void wasm_config_enable_debug(wasm_config_t *config, bool enabled);
+
 struct wasm_engine_t {
     wasm_config_t *config;
 
@@ -84,6 +86,7 @@ struct wasm_foreign_t {
 };
 
 struct wasm_module_t {
+    ovm_program_t *program;
 };
 
 struct wasm_func_t {
@@ -102,6 +105,8 @@ struct wasm_extern_t {
 };
 
 struct wasm_instance_t {
+    wasm_module_t *module;
+    ovm_state_t *state;
 };
 
 #endif
index 6018f6fc13906c95035ecaa25298005a7438e158..e83d73a00ab1947359f68a41e802731f4fe993ba 100644 (file)
@@ -45,7 +45,6 @@ struct ovm_static_data_t {
 struct ovm_program_t {
     bh_arr(ovm_instr_t)       code;
     bh_arr(ovm_func_t)        funcs;
-    bh_arr(ovm_native_func_t) native_funcs;
 
     i32 register_count;
     ovm_store_t *store;
@@ -59,8 +58,6 @@ void ovm_raw_print_instructions(i32 instr_count, ovm_instr_t *instrs);
 
 void ovm_program_register_func(ovm_program_t *program, char *name, i32 instr, i32 param_count, i32 value_number_count);
 void ovm_program_begin_func(ovm_program_t *program, char *name, i32 param_count, i32 value_number_count);
-void ovm_program_register_native_func(ovm_program_t *program, char *name,
-        void (*func)(void *, ovm_value_t *, ovm_value_t *), void *data, i32 param_count);
 
 //
 // Represents the running configuration and static
@@ -78,8 +75,8 @@ ovm_engine_t *ovm_engine_new(ovm_store_t *store);
 void          ovm_engine_delete(ovm_engine_t *engine);
 void          ovm_engine_memory_copy(ovm_engine_t *engine, i64 target, void *data, i64 size);
 
-bool ovm_program_load_from_file(ovm_program_t *program, ovm_engine_t *engine, char *filename);
-void ovm_program_link_native_funcs(ovm_program_t *program, ovm_native_func_t *funcs);
+bool ovm_program_load_from_file(ovm_program_t *program, ovm_engine_t *engine,
+    ovm_state_t *state, char *filename);
 
 //
 // Represents ephemeral state / execution context.
@@ -95,11 +92,21 @@ struct ovm_state_t {
     bh_arr(ovm_value_t) params;
     bh_arr(ovm_stack_frame_t) stack_frames;
     bh_arr(ovm_value_t) registers;
+
+    //
+    // Originally, these were stored on the ovm_program that
+    // this state corresponds with. However, that does not line
+    // up with the specifications needed by WASM. In theory, different
+    // running instances of the program *could* have different
+    // native functions linked.
+    bh_arr(ovm_native_func_t) native_funcs;
 };
 
 ovm_state_t *ovm_state_new(ovm_engine_t *engine, ovm_program_t *program);
 void         ovm_state_delete(ovm_state_t *state);
-
+void ovm_state_link_native_funcs(ovm_state_t *state, ovm_native_func_t *funcs);
+void ovm_state_register_native_func(ovm_state_t *state, char *name,
+        void (*func)(void *, ovm_value_t *, ovm_value_t *), void *data, i32 param_count);
 
 //
 //
index 449ce3ef26a69b92594e9957d9ec408f4eea1933..330685e137386a40357c2f98c151d136f9ae1015 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -26,13 +26,12 @@ int main(int argc, char *argv[]) {
     ovm_store_t *store = ovm_store_new();
     ovm_program_t *prog = ovm_program_new(store);
     ovm_engine_t *engine = ovm_engine_new(store);
+    ovm_state_t  *state = ovm_state_new(engine, prog);
 
-    ovm_program_load_from_file(prog, engine, "./out.ovm");
-    ovm_program_link_native_funcs(prog, native_funcs);
-
+    ovm_program_load_from_file(prog, engine, state, "./out.ovm");
     ovm_program_print_instructions(prog, 0, bh_arr_length(prog->code));
 
-    ovm_state_t  *state = ovm_state_new(engine, prog);
+    ovm_state_link_native_funcs(state, native_funcs);
 
     state->pc = 0;
     ovm_value_t values[] = {
index 4b710420091a2f6c12483d9685ef2ff068aada47..a179100972a5f1559e4fbcc2120f8f22f8cedd63 100644 (file)
 // I wish this didn't take the engine as a parameter... but currently the memory
 // is stored on the engine. So unless the data section elements can be aggregated
 // into an array to be applied later, this is best I got...
-bool ovm_program_load_from_file(ovm_program_t *program, ovm_engine_t *engine, char *filename) {
+//
+// ALSO, I wish this didn't have to take a state... but because native_funcs are stored
+// on the state, this is also the best I got...
+bool ovm_program_load_from_file(ovm_program_t *program, ovm_engine_t *engine, ovm_state_t *state, char *filename) {
     bh_file file;
     bh_file_error error = bh_file_open(&file, filename);
     if (error != BH_FILE_ERROR_NONE) {
@@ -78,7 +81,7 @@ bool ovm_program_load_from_file(ovm_program_t *program, ovm_engine_t *engine, ch
         char *name_buf = bh_alloc_array(program->store->arena_allocator, char, name_len);
         bh_file_read(&file, name_buf, name_len);
 
-        ovm_program_register_native_func(program, name_buf, NULL, NULL, param_count);
+        ovm_state_register_native_func(state, name_buf, NULL, NULL, param_count);
     }
 
     //
@@ -100,8 +103,8 @@ bool ovm_program_load_from_file(ovm_program_t *program, ovm_engine_t *engine, ch
     return true;
 }
 
-void ovm_program_link_native_funcs(ovm_program_t *program, ovm_native_func_t *funcs) {
-    bh_arr_each(ovm_native_func_t, nf, program->native_funcs) {
+void ovm_state_link_native_funcs(ovm_state_t *state, ovm_native_func_t *funcs) {
+    bh_arr_each(ovm_native_func_t, nf, state->native_funcs) {
         if (nf->native_func || nf->userdata) continue;
         
         ovm_native_func_t *func = funcs;
index 82bd96cc5b66d6debcfa422b30994f12b8e5623a..278cc02536a8075a2c289a84d1d380a26fb2c7ea 100644 (file)
@@ -29,8 +29,6 @@ ovm_program_t *ovm_program_new(ovm_store_t *store) {
     program->register_count = 0;
 
     bh_arr_new(store->heap_allocator, program->funcs, 16);
-    bh_arr_new(store->heap_allocator, program->native_funcs, 16);
-
     bh_arr_new(store->heap_allocator, program->code, 1024);
 
     return program;
@@ -38,7 +36,6 @@ ovm_program_t *ovm_program_new(ovm_store_t *store) {
 
 void ovm_program_delete(ovm_program_t *program) {
     bh_arr_free(program->funcs);
-    bh_arr_free(program->native_funcs);
     bh_arr_free(program->code);
 
     bh_free(program->store->heap_allocator, program);
@@ -55,18 +52,6 @@ void ovm_program_register_func(ovm_program_t *program, char *name, i32 instr, i3
     bh_arr_push(program->funcs, func);
 }
 
-void ovm_program_register_native_func(ovm_program_t *program, char *name,
-        void (*func)(void *, ovm_value_t *, ovm_value_t *), void *data, i32 param_count) {
-
-    ovm_native_func_t native_func;
-    native_func.name = name;
-    native_func.param_count = param_count;
-    native_func.native_func = func;
-    native_func.userdata = data;
-
-    bh_arr_push(program->native_funcs, native_func);
-}
-
 void ovm_program_begin_func(ovm_program_t *program, char *name, i32 param_count, i32 value_number_count) {
     ovm_func_t func;
     func.id = bh_arr_length(program->funcs);
@@ -402,6 +387,18 @@ void ovm_state_delete(ovm_state_t *state) {
     bh_free(store->heap_allocator, state);
 }
 
+void ovm_state_register_native_func(ovm_state_t *state, char *name,
+        void (*func)(void *, ovm_value_t *, ovm_value_t *), void *data, i32 param_count) {
+
+    ovm_native_func_t native_func;
+    native_func.name = name;
+    native_func.param_count = param_count;
+    native_func.native_func = func;
+    native_func.userdata = data;
+
+    bh_arr_push(state->native_funcs, native_func);
+}
+
 
 //
 // Function calling
@@ -748,7 +745,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 #undef OVM_CALL_CODE
 
 #define OVM_NATIVE_CALL_CODE(func_idx) \
-            ovm_native_func_t native_func = program->native_funcs[func_idx]; \
+            ovm_native_func_t native_func = state->native_funcs[func_idx]; \
             assert(native_func.param_count == bh_arr_length(state->params)); \
  \
             ovm_value_t result = {0}; \
index 05f18819ecf0c1ff70c90157fe5af51501f18497..b4dabdd1633598e4bade03c6902db59aaac5b3b0 100644 (file)
@@ -249,3 +249,51 @@ void wasm_tabletype_vec_delete(wasm_tabletype_vec_t *vec) {
 }
 
 
+// wasm_memorytype_t
+
+wasm_memorytype_t *wasm_memorytype_new(const wasm_limits_t *limits) {
+    wasm_memorytype_t *memorytype = malloc(sizeof(*memorytype));
+    memorytype->limits = *limits;
+
+    return memorytype;
+}
+
+void wasm_memorytype_delete(wasm_memorytype_t *memorytype) {
+    if (memorytype) free(memorytype);
+}
+
+const wasm_limits_t* wasm_memorytype_limits(const wasm_memorytype_t *memorytype) {
+    return &memorytype->limits;
+}
+
+
+void wasm_memorytype_vec_new_empty(wasm_memorytype_vec_t *out) {
+    out->size = 0;
+    out->data = NULL;
+}
+
+void wasm_memorytype_vec_new_uninitialized(wasm_memorytype_vec_t *out, size_t size) {
+    out->data = malloc(sizeof(wasm_memorytype_t) * size);
+    out->size = size;
+}
+
+void wasm_memorytype_vec_new(wasm_memorytype_vec_t *out, size_t size, wasm_memorytype_t* const data[]) {
+    out->data = malloc(sizeof(wasm_memorytype_t) * size);
+    out->size = size;
+
+    fori (i, 0, (i32) size) {
+        out->data[i] = data[i];
+    }
+}
+
+void wasm_memorytype_vec_copy(wasm_memorytype_vec_t *out, const wasm_memorytype_vec_t *in) {
+    wasm_memorytype_vec_new(out, in->size, in->data);
+}
+
+void wasm_memorytype_vec_delete(wasm_memorytype_vec_t *vec) {
+    if (vec->data) free(vec->data);
+}
+
+
+// wasm_externtype_t
+