--- /dev/null
+# 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
+
+
bool debug_enabled;
};
+void wasm_config_enable_debug(wasm_config_t *config, bool enabled);
+
struct wasm_engine_t {
wasm_config_t *config;
};
struct wasm_module_t {
+ ovm_program_t *program;
};
struct wasm_func_t {
};
struct wasm_instance_t {
+ wasm_module_t *module;
+ ovm_state_t *state;
};
#endif
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;
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
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.
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);
//
//
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[] = {
// 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) {
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);
}
//
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;
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;
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);
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);
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
#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}; \
}
+// 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
+