From: Brendan Hansen Date: Sun, 19 Jun 2022 04:15:18 +0000 (-0500) Subject: refactoring native_funcs out of program to state X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=2ceb803ebab89eb710106a7b34e814e1679df069;p=onyx-embedder.git refactoring native_funcs out of program to state --- diff --git a/docs/wasm_wtf.md b/docs/wasm_wtf.md new file mode 100644 index 0000000..be20c4e --- /dev/null +++ b/docs/wasm_wtf.md @@ -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 + + diff --git a/include/onyx_wasm.h b/include/onyx_wasm.h index e388dea..fa1ddc0 100644 --- a/include/onyx_wasm.h +++ b/include/onyx_wasm.h @@ -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 diff --git a/include/vm.h b/include/vm.h index 6018f6f..e83d73a 100644 --- a/include/vm.h +++ b/include/vm.h @@ -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); // // diff --git a/src/cli.c b/src/cli.c index 449ce3e..330685e 100644 --- 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[] = { diff --git a/src/vm/program_loader.c b/src/vm/program_loader.c index 4b71042..a179100 100644 --- a/src/vm/program_loader.c +++ b/src/vm/program_loader.c @@ -12,7 +12,10 @@ // 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; diff --git a/src/vm/vm.c b/src/vm/vm.c index 82bd96c..278cc02 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -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}; \ diff --git a/src/wasm/type.c b/src/wasm/type.c index 05f1881..b4dabdd 100644 --- a/src/wasm/type.c +++ b/src/wasm/type.c @@ -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 +