very very close to a full run of hello world
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 28 Jun 2022 03:39:53 +0000 (22:39 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 28 Jun 2022 03:39:53 +0000 (22:39 -0500)
include/onyx_wasm.h
include/vm.h
include/vm_codebuilder.h
src/vm/code_builder.c
src/vm/vm.c
src/wasm/instance.c
src/wasm/module.c
src/wasm/module_parsing.c.incl
src/wasm/store.c
src/wasm/trap.c

index d2e8bab1b1c700deede9ca83354ea86b1d750cc2..f5258b49b9fea5caa1bfcf9cfe7a6649b9313ba2 100644 (file)
@@ -72,6 +72,13 @@ struct wasm_importtype_t {
     wasm_name_t module_name;
     wasm_name_t import_name;
     wasm_externtype_t *type;
+
+    //
+    // This is only used by imported functions
+    // to specify which slot the function binding
+    // should be placed. When making a functype by
+    // hand, this proably will never be used.
+    int external_func_idx;
 };
 
 struct wasm_exporttype_t {
@@ -90,6 +97,7 @@ struct wasm_frame_t {
 };
 
 struct wasm_trap_t {
+    wasm_message_t msg;
 };
 
 struct wasm_foreign_t {
@@ -125,6 +133,9 @@ struct wasm_module_t {
 
     ovm_program_t *program;
     bool valid;
+    
+    int memory_init_idx;
+    int memory_init_external_idx;
 };
 
 struct wasm_func_inner_t {
index 080ae0417912a2bd90d02a4b075d060379f88817..7eef740ecf59b55ecd62109f15a869e618e723da 100644 (file)
@@ -71,8 +71,8 @@ void ovm_program_print_instructions(ovm_program_t *program, i32 start_instr, i32
 void ovm_raw_print_instructions(i32 instr_count, ovm_instr_t *instrs);
 
 int  ovm_program_register_static_ints(ovm_program_t *program, int len, int *data);
-void ovm_program_register_func(ovm_program_t *program, char *name, i32 instr, i32 param_count, i32 value_number_count);
-void ovm_program_register_external_func(ovm_program_t *program, char *name, i32 param_count, i32 external_func_idx);
+int  ovm_program_register_func(ovm_program_t *program, char *name, i32 instr, i32 param_count, i32 value_number_count);
+int  ovm_program_register_external_func(ovm_program_t *program, char *name, i32 param_count, i32 external_func_idx);
 void ovm_program_begin_func(ovm_program_t *program, char *name, i32 param_count, i32 value_number_count);
 void ovm_program_modify_static_int(ovm_program_t *program, int arr, int idx, int new_value);
 
@@ -124,6 +124,7 @@ 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_external_funcs(ovm_program_t *program, ovm_state_t *state, ovm_linkable_func_t *funcs);
 void ovm_state_register_external_func(ovm_state_t *state, i32 idx, void (*func)(void *, ovm_value_t *, ovm_value_t *), void *data);
+void ovm_state_register_set(ovm_state_t *state, i32 idx, ovm_value_t val);
 
 //
 //
index c3c2d7e677582984974a80703903cc77b962dae5..b8f9a0b88c30108ee865efda747e218b248e9c17 100644 (file)
@@ -24,7 +24,6 @@ struct ovm_code_builder_t {
     i32 start_instr;
 
     i32 func_table_arr_idx;
-    i32 next_external_func_idx;
     i32 highest_value_number;
 };
 
index b6b1be7fc13ce82fe0e90d06ba77e270d02c54f0..955ef9989d39d7a401bb3efa6bb1f32071d41593 100644 (file)
@@ -188,10 +188,16 @@ void ovm_code_builder_add_return(ovm_code_builder_t *builder) {
 }
 
 static void ovm_code_builder_add_params(ovm_code_builder_t *builder, i32 param_count) {
+    i32 *flipped_params = alloca(param_count * sizeof(i32));
+
+    fori (i, 0, param_count) {
+        flipped_params[i] = POP_VALUE(builder);
+    }
+
     fori (i, 0, param_count) {
         ovm_instr_t param_instr = {0};
         param_instr.full_instr = OVMI_PARAM;
-        param_instr.a = POP_VALUE(builder);
+        param_instr.a = flipped_params[param_count - 1 - i];
 
         ovm_program_add_instructions(builder->program, 1, &param_instr);
     }
@@ -316,8 +322,8 @@ void ovm_code_builder_add_load(ovm_code_builder_t *builder, u32 ovm_type, i32 of
     // add.i32 %n, %n, %i
     instrs[1].full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32);
     instrs[1].r = instrs[0].r;
-    instrs[1].a = instrs[0].r;
-    instrs[1].b = POP_VALUE(builder);
+    instrs[1].a = POP_VALUE(builder);
+    instrs[1].b = instrs[0].r;
 
     // load.x %m, %n
     instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_LOAD, ovm_type);
@@ -341,18 +347,21 @@ void ovm_code_builder_add_store(ovm_code_builder_t *builder, u32 ovm_type, i32 o
     }
 
     ovm_instr_t instrs[3] = {0};
-    instrs[2].b = POP_VALUE(builder);
+
+    // TODO: explain the ordering here.
 
     // imm.i32 %n, offset
     instrs[0].full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32);
     instrs[0].i = offset;
     instrs[0].r = NEXT_VALUE(builder);
 
+    instrs[2].b = POP_VALUE(builder);
+
     // add.i32 %n, %n, %i
     instrs[1].full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32);
     instrs[1].r = instrs[0].r;
-    instrs[1].a = instrs[0].r;
-    instrs[1].b = POP_VALUE(builder);
+    instrs[1].a = POP_VALUE(builder);
+    instrs[1].b = instrs[0].r;
 
     // store.x %m, %n
     instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_STORE, ovm_type);
@@ -374,22 +383,24 @@ void ovm_code_builder_add_cmpxchg(ovm_code_builder_t *builder, u32 ovm_type, i32
         PUSH_VALUE(builder, cmpxchg_instr.r);
         return;
     }
+    
+    // TODO: explain the ordering here.
 
     ovm_instr_t instrs[3] = {0};
-    int value_reg = POP_VALUE(builder);
-    int expected_reg = POP_VALUE(builder);
-    int addr_reg = POP_VALUE(builder);
-
     // imm.i32 %n, offset
     instrs[0].full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32);
     instrs[0].i = offset;
     instrs[0].r = NEXT_VALUE(builder);
 
+    int value_reg = POP_VALUE(builder);
+    int expected_reg = POP_VALUE(builder);
+    int addr_reg = POP_VALUE(builder);
+
     // add.i32 %n, %n, %i
     instrs[1].full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32);
     instrs[1].r = instrs[0].r;
-    instrs[1].a = instrs[0].r;
-    instrs[1].b = addr_reg;
+    instrs[1].a = addr_reg;
+    instrs[1].b = instrs[0].r;
 
     // cmpxchg.x %m, %n
     instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_CMPXCHG, ovm_type);
index 5b058e9a8f8e77544efceeebb2062e9874f5112f..37f539ba260beb6fbe124761e86b42fcc58c36da 100644 (file)
@@ -31,8 +31,14 @@ ovm_program_t *ovm_program_new(ovm_store_t *store) {
     program->store = store;
     program->register_count = 0;
 
+    program->funcs = NULL;
+    program->code  = NULL;
+    program->static_integers = NULL;
+    program->static_data  = NULL;
     bh_arr_new(store->heap_allocator, program->funcs, 16);
     bh_arr_new(store->heap_allocator, program->code, 1024);
+    bh_arr_new(store->heap_allocator, program->static_integers, 128);
+    bh_arr_new(store->heap_allocator, program->static_data, 128);
 
     return program;
 }
@@ -40,6 +46,8 @@ 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->code);
+    bh_arr_free(program->static_integers);
+    bh_arr_free(program->static_data);
 
     bh_free(program->store->heap_allocator, program);
 }
@@ -67,7 +75,7 @@ void ovm_program_modify_static_int(ovm_program_t *program, int arr, int idx, int
     program->static_integers[array.start_idx + idx] = new_value;
 }
 
-void ovm_program_register_func(ovm_program_t *program, char *name, i32 instr, i32 param_count, i32 value_number_count) {
+int ovm_program_register_func(ovm_program_t *program, char *name, i32 instr, i32 param_count, i32 value_number_count) {
     ovm_func_t func;
     func.kind = OVM_FUNC_INTERNAL;
     func.id = bh_arr_length(program->funcs);
@@ -77,9 +85,10 @@ void ovm_program_register_func(ovm_program_t *program, char *name, i32 instr, i3
     func.value_number_count = value_number_count;
 
     bh_arr_push(program->funcs, func);
+    return func.id;
 }
 
-void ovm_program_register_external_func(ovm_program_t *program, char *name, i32 param_count, i32 external_func_idx) {
+int ovm_program_register_external_func(ovm_program_t *program, char *name, i32 param_count, i32 external_func_idx) {
     ovm_func_t func;
     func.kind = OVM_FUNC_EXTERNAL;
     func.id = bh_arr_length(program->funcs);
@@ -88,6 +97,7 @@ void ovm_program_register_external_func(ovm_program_t *program, char *name, i32
     func.external_func_idx = external_func_idx;
 
     bh_arr_push(program->funcs, func);
+    return func.id;
 }
 
 void ovm_program_begin_func(ovm_program_t *program, char *name, i32 param_count, i32 value_number_count) {
@@ -374,7 +384,7 @@ static char *ovm_instr_name(i32 full_instr) {
 }
 
 void ovm_program_print_instructions(ovm_program_t *program, i32 start_instr, i32 instr_count) {
-    fori (i, start_instr, instr_count) {
+    fori (i, start_instr, start_instr + instr_count) {
         //
         // Horribly inefficient way of checking to see if this instruction
         // is the start of a function, but for now, it'll do. -brendanfh 06/13/2022
@@ -385,14 +395,14 @@ void ovm_program_print_instructions(ovm_program_t *program, i32 start_instr, i32
         }
 
         ovm_instr_t instr = program->code[i];
-        printf("%50s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
+        printf("%6lx  %50s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", i, ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
     }
 }
 
 void ovm_raw_print_instructions(i32 instr_count, ovm_instr_t *instrs) {
     fori (i, 0, instr_count) {
         ovm_instr_t instr = instrs[i];
-        printf("%50s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
+        printf("%6lx  %50s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", i, ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
     }
 }
 
@@ -403,7 +413,8 @@ ovm_engine_t *ovm_engine_new(ovm_store_t *store) {
 
     engine->store = store;
     engine->memory_size = 1ull << 32;
-    engine->memory = mmap(NULL, engine->memory_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+    engine->memory = mmap(NULL, engine->memory_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    pthread_mutex_init(&engine->atomic_mutex, NULL);
 
     return engine;
 }
@@ -438,12 +449,17 @@ ovm_state_t *ovm_state_new(ovm_engine_t *engine, ovm_program_t *program) {
     state->pc = 0;
     state->value_number_offset = 0;
 
+    state->numbered_values = NULL;
+    state->params = NULL;
+    state->stack_frames = NULL;
+    state->registers = NULL;
     bh_arr_new(store->heap_allocator, state->numbered_values, 64);
     bh_arr_new(store->heap_allocator, state->params, 16);
     bh_arr_new(store->heap_allocator, state->stack_frames, 32);
     bh_arr_new(store->heap_allocator, state->registers, program->register_count);
     bh_arr_insert_end(state->registers, program->register_count);
 
+    state->external_funcs = NULL;
     bh_arr_new(store->heap_allocator, state->external_funcs, 8);
 
     return state;
@@ -468,6 +484,11 @@ void ovm_state_register_external_func(ovm_state_t *state, i32 idx, void (*func)(
     bh_arr_set_at(state->external_funcs, idx, external_func);
 }
 
+void ovm_state_register_set(ovm_state_t *state, i32 idx, ovm_value_t val) {
+    if (idx >= bh_arr_length(state->registers)) return;
+
+    state->registers[idx] = val;
+}
 
 //
 // Function calling
@@ -582,6 +603,8 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
     bool release_mutex_at_end = false;
    
     while (state->pc < bh_arr_length(program->code)) {
+        ovm_program_print_instructions(program, state->pc, 1);
+
         //
         // Incrementing the program counter here.
         // All instructions that compute something relative
@@ -828,6 +851,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 
 #define OVM_LOAD(type_, stype) \
             case OVM_TYPED_INSTR(OVMI_LOAD, type_): \
+                assert(VAL(instr.a).type == OVM_TYPE_I32); \
                 VAL(instr.r).type = type_; \
                 VAL(instr.r).stype = * (stype *) &((u8 *) engine->memory)[(u32) VAL(instr.a).i32]; \
                 break;
@@ -843,6 +867,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 
 #define OVM_STORE(type_, stype) \
             case OVM_TYPED_INSTR(OVMI_STORE, type_): \
+                assert(VAL(instr.a).type == OVM_TYPE_I32); \
                 * (stype *) &((u8 *) engine->memory)[(u32) VAL(instr.a).i32] = VAL(instr.b).stype; \
                 break;
 
@@ -901,6 +926,12 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                 ovm_value_t val = VAL(instr.a);
                 bh_arr_fastdeleten(state->numbered_values, frame.value_number_count);
 
+                if (bh_arr_length(state->stack_frames) == 0) {
+                    state->value_number_offset = 0;
+                    VAL(frame.return_number_value) = val;
+                    return;
+                }
+
                 state->value_number_offset = bh_arr_last(state->stack_frames).value_number_base;
                 if (frame.return_number_value >= 0) {
                     VAL(frame.return_number_value) = val;
@@ -1020,11 +1051,15 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 
 
 #define CMPXCHG(otype, ctype) \
-    case OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_CMPXCHG, otype): \
-        if (VAL(instr.r).ctype == VAL(instr.a).ctype) { \
-            VAL(instr.r).ctype = VAL(instr.b).ctype ; \
+    case OVM_TYPED_INSTR(OVMI_CMPXCHG, otype): {\
+        ctype *addr = (ctype *) &((u8 *) engine->memory)[VAL(instr.r).i32]; \
+        if (*addr == VAL(instr.a).ctype) { \
+            *addr = VAL(instr.b).ctype ; \
         } \
-        break;
+        VAL(instr.r).type = otype; \
+        VAL(instr.r).ctype = *addr; \
+        break; \
+    }
 
             CMPXCHG(OVM_TYPE_I8,  i8)
             CMPXCHG(OVM_TYPE_I16, i16)
index f9d249dc622117e139b38a20ba12945ebeddcdcf..4ab07c8ea3f80ed228ba52fab5d2ddf88f063486 100644 (file)
@@ -12,105 +12,195 @@ struct wasm_ovm_binding {
     ovm_program_t *program;
 };
 
+typedef struct ovm_wasm_binding ovm_wasm_binding;
+struct ovm_wasm_binding {
+    int param_count;
+    int result_count;
+    wasm_func_t *func;
+};
+
+#define WASM_TO_OVM(w, o) \
+    switch ((w).kind) { \
+        case WASM_I32: \
+            (o).type = OVM_TYPE_I32; \
+            (o).i32  = (w).of.i32; \
+            break; \
+ \
+        case WASM_I64: \
+            (o).type = OVM_TYPE_I64; \
+            (o).i64  = (w).of.i64; \
+            break; \
+ \
+        case WASM_F32: \
+            (o).type = OVM_TYPE_F32; \
+            (o).f32  = (w).of.f32; \
+            break; \
+ \
+        case WASM_F64: \
+            (o).type = OVM_TYPE_F64; \
+            (o).f64  = (w).of.f64; \
+            break; \
+ \
+        default: assert(("invalid wasm value type for conversion", 0)); \
+    }
+
+#define OVM_TO_WASM(o, w) \
+    switch ((o).type) { \
+        case OVM_TYPE_I8: \
+            (w).kind = WASM_I32; \
+            (w).of.i32 = (i32) (o).i8; \
+            break; \
+ \
+        case OVM_TYPE_I16: \
+            (w).kind = WASM_I32; \
+            (w).of.i32 = (i32) (o).i16; \
+            break; \
+ \
+        case OVM_TYPE_I32: \
+            (w).kind = WASM_I32; \
+            (w).of.i32 = (i32) (o).i32; \
+            break; \
+ \
+        case OVM_TYPE_I64: \
+            (w).kind = WASM_I64; \
+            (w).of.i64 = (o).i64; \
+            break; \
+ \
+        case OVM_TYPE_F32: \
+            (w).kind = WASM_F32; \
+            (w).of.f32 = (o).f32; \
+            break; \
+ \
+        case OVM_TYPE_F64: \
+            (w).kind = WASM_F64; \
+            (w).of.f64 = (o).f64; \
+            break; \
+    }
+
 static wasm_trap_t *wasm_to_ovm_func_call_binding(void *vbinding, const wasm_val_vec_t *args, wasm_val_vec_t *res) {
     wasm_ovm_binding *binding = (wasm_ovm_binding *) vbinding;
 
     ovm_value_t *vals = alloca(sizeof(*vals) * args->size);
     fori (i, 0, (int) args->size) {
-        switch (args->data[i].kind) {
-            case WASM_I32:
-                vals[i].type = OVM_TYPE_I32;
-                vals[i].i32  = args->data[i].of.i32;
-                break;
+        WASM_TO_OVM(args->data[i], vals[i]);
+    }
 
-            case WASM_I64:
-                vals[i].type = OVM_TYPE_I64;
-                vals[i].i64  = args->data[i].of.i64;
-                break;
+    ovm_value_t ovm_res = ovm_func_call(binding->engine, binding->state, binding->program, binding->func_idx, args->size, vals);
+    if (!res || res->size == 0) return NULL;
 
-            case WASM_F32:
-                vals[i].type = OVM_TYPE_F32;
-                vals[i].f32  = args->data[i].of.f32;
-                break;
+    OVM_TO_WASM(ovm_res, res->data[0]);
 
-            case WASM_F64:
-                vals[i].type = OVM_TYPE_F64;
-                vals[i].f64  = args->data[i].of.f64;
-                break;
+    return NULL;
+}
 
-            default: assert(("invalid wasm value type for conversion", 0));
-        }
-    }
+static void ovm_to_wasm_func_call_binding(void *env, ovm_value_t* params, ovm_value_t *res) {
+    ovm_wasm_binding *binding = (ovm_wasm_binding *) env;
 
-    ovm_value_t ovm_res = ovm_func_call(binding->engine, binding->state, binding->program, binding->func_idx, args->size, vals);
-    if (!res || res->size == 0) return NULL;
+    wasm_val_vec_t wasm_params;
+    wasm_params.data = alloca(sizeof(wasm_val_t) * binding->param_count);
+    wasm_params.size = binding->param_count;
 
-    switch (ovm_res.type) {
-        case OVM_TYPE_I8:
-            res->data[0].kind = WASM_I32;
-            res->data[0].of.i32 = (i32) ovm_res.i8;
-            break;
-
-        case OVM_TYPE_I16:
-            res->data[0].kind = WASM_I32;
-            res->data[0].of.i32 = (i32) ovm_res.i16;
-            break;
-
-        case OVM_TYPE_I32:
-            res->data[0].kind = WASM_I32;
-            res->data[0].of.i32 = (i32) ovm_res.i32;
-            break;
-
-        case OVM_TYPE_I64:
-            res->data[0].kind = WASM_I64;
-            res->data[0].of.i64 = ovm_res.i64;
-            break;
-
-        case OVM_TYPE_F32:
-            res->data[0].kind = WASM_F32;
-            res->data[0].of.f32 = ovm_res.f32;
-            break;
-
-        case OVM_TYPE_F64:
-            res->data[0].kind = WASM_F64;
-            res->data[0].of.f64 = ovm_res.f64;
-            break;
+    fori (i, 0, binding->param_count) {
+        OVM_TO_WASM(params[i], wasm_params.data[i]);
     }
 
-    return NULL;
+    // asm("int $3");
+
+    wasm_val_vec_t wasm_results;
+    wasm_results.data = alloca(sizeof(wasm_val_t) * binding->result_count);
+    wasm_results.size = binding->result_count;
+
+    wasm_trap_t *trap = wasm_func_call(binding->func, &wasm_params, &wasm_results);
+    assert(!trap);
+
+    if (binding->result_count > 0) WASM_TO_OVM(wasm_results.data[0], *res);
+}
+
+static void wasm_memory_init(void *env, ovm_value_t* params, ovm_value_t *res) {
+    wasm_instance_t *instr = (wasm_instance_t *) env;
+
+    assert(params[0].type == OVM_TYPE_I32);
+    assert(params[1].type == OVM_TYPE_I32);
+    assert(params[2].type == OVM_TYPE_I32);
+    assert(params[3].type == OVM_TYPE_I32);
+
+    // if (params[0].i32 == 63) asm("int $3");
+
+    printf("Initializing data from: %p\n", instr->module->data_entries[params[3].i32].data);
+    ovm_engine_memory_copy(instr->store->engine->engine, params[0].i32, instr->module->data_entries[params[3].i32].data, params[2].i32);
 }
 
 static void prepare_instance(wasm_instance_t *instance, const wasm_extern_vec_t *imports) {
+    ovm_store_t   *ovm_store   = instance->store->engine->store;
+    ovm_engine_t  *ovm_engine  = instance->store->engine->engine;
+    ovm_state_t   *ovm_state   = instance->state;
+    ovm_program_t *ovm_program = instance->module->program;
+
     //
     // Place imports in their corresponding "bucket"
     fori (i, 0, (int) imports->size) {
         switch (wasm_extern_kind(imports->data[i])) {
-            case WASM_EXTERN_FUNC: 
-                bh_arr_push(instance->funcs, wasm_extern_as_func(imports->data[i]));
+            case WASM_EXTERN_FUNC: {
+                wasm_func_t *func = wasm_extern_as_func(imports->data[i]);
+                bh_arr_push(instance->funcs, func);
+
+                wasm_importtype_t *importtype = instance->module->imports.data[i];
+                struct wasm_functype_inner_t *functype = &importtype->type->func;
+
+                ovm_wasm_binding *binding = bh_alloc(ovm_store->arena_allocator, sizeof(*binding));
+                binding->param_count  = functype->params.size;
+                binding->result_count = functype->results.size;
+                binding->func         = func;
+
+                ovm_state_register_external_func(ovm_state, importtype->external_func_idx, ovm_to_wasm_func_call_binding, binding);
                 break;
+            }
 
-            case WASM_EXTERN_MEMORY:
-                bh_arr_push(instance->memories, wasm_extern_as_memory(imports->data[i]));
+            case WASM_EXTERN_MEMORY: {
+                wasm_memory_t *memory = wasm_extern_as_memory(imports->data[i]);
+                bh_arr_push(instance->memories, memory);
+
+                memory->inner.memory.engine = ovm_engine;
                 break;
+            }
+
+            case WASM_EXTERN_GLOBAL: {
+                wasm_global_t *global = wasm_extern_as_global(imports->data[i]);
+
+                global->inner.global.engine = ovm_engine;
+                global->inner.global.state  = ovm_state;
+                global->inner.global.register_index = bh_arr_length(instance->globals);
 
-            case WASM_EXTERN_GLOBAL:
-                bh_arr_push(instance->globals, wasm_extern_as_global(imports->data[i]));
+                ovm_value_t val = {0};
+                WASM_TO_OVM(global->inner.global.initial_value, val);
+                ovm_state_register_set(ovm_state, global->inner.global.register_index, val);
+
+                bh_arr_push(instance->globals, global);
                 break;
+            }
+
+            case WASM_EXTERN_TABLE: {
+                wasm_table_t *table = wasm_extern_as_table(imports->data[i]);
+                table->inner.table.engine = ovm_engine;
+                table->inner.table.program = ovm_program;
+                table->inner.table.static_arr = instance->module->imports.data[i]->type->table.static_arr;
 
-            case WASM_EXTERN_TABLE:
-                bh_arr_push(instance->tables, wasm_extern_as_table(imports->data[i]));
+                bh_arr_push(instance->tables, table);
                 break;
+            }
         }
     }
 
+    ovm_state_register_external_func(ovm_state, instance->module->memory_init_external_idx, wasm_memory_init, instance);
+
     //
     // Create function objects
     fori (i, 0, (int) instance->module->functypes.size) {
         wasm_ovm_binding *binding = bh_alloc(instance->store->engine->store->arena_allocator, sizeof(*binding));
-        binding->engine = instance->store->engine->engine;
+        binding->engine   = ovm_engine;
         binding->func_idx = bh_arr_length(instance->funcs);
-        binding->program = instance->module->program;
-        binding->state = instance->state;
+        binding->program  = ovm_program;
+        binding->state    = ovm_state;
         
         wasm_func_t *func = wasm_func_new_with_env(instance->store, instance->module->functypes.data[i], 
             wasm_to_ovm_func_call_binding, binding, NULL);
@@ -122,7 +212,7 @@ static void prepare_instance(wasm_instance_t *instance, const wasm_extern_vec_t
     // Create memory objects
     fori (i, 0, (int) instance->module->memorytypes.size) {
         wasm_memory_t *memory = wasm_memory_new(instance->store, instance->module->memorytypes.data[i]);
-        memory->inner.memory.engine = instance->store->engine->engine;
+        memory->inner.memory.engine = ovm_engine;
 
         bh_arr_push(instance->memories, memory);
     }
@@ -131,8 +221,8 @@ static void prepare_instance(wasm_instance_t *instance, const wasm_extern_vec_t
     // Create table objects
     fori (i, 0, (int) instance->module->tabletypes.size) {
         wasm_table_t *table = wasm_table_new(instance->store, instance->module->tabletypes.data[i], NULL);
-        table->inner.table.engine = instance->store->engine->engine;
-        table->inner.table.program = instance->module->program;
+        table->inner.table.engine     = ovm_engine;
+        table->inner.table.program    = ovm_program;
         table->inner.table.static_arr = instance->module->tabletypes.data[i]->type.table.static_arr;
 
         bh_arr_push(instance->tables, table);
@@ -143,10 +233,15 @@ static void prepare_instance(wasm_instance_t *instance, const wasm_extern_vec_t
     fori (i, 0, (int) instance->module->globaltypes.size) {
         wasm_global_t *global = wasm_global_new(instance->store, instance->module->globaltypes.data[i],
             &instance->module->globaltypes.data[i]->type.global.initial_value);
-        global->inner.global.engine = instance->store->engine->engine;
-        global->inner.global.state = instance->state;
+
+        global->inner.global.engine         = ovm_engine;
+        global->inner.global.state          = ovm_state;
         global->inner.global.register_index = bh_arr_length(instance->globals);
 
+        ovm_value_t val = {0};
+        WASM_TO_OVM(global->inner.global.initial_value, val);
+        ovm_state_register_set(ovm_state, global->inner.global.register_index, val);
+
         bh_arr_push(instance->globals, global);
     }
 
@@ -157,7 +252,38 @@ static void prepare_instance(wasm_instance_t *instance, const wasm_extern_vec_t
         struct wasm_data_t *datum = &instance->module->data_entries[i];
         if (datum->passive) continue;
 
-        ovm_engine_memory_copy(instance->store->engine->engine, datum->offset, datum->data, datum->length);
+        ovm_engine_memory_copy(ovm_engine, datum->offset, datum->data, datum->length);
+    }
+
+    wasm_extern_vec_new_uninitialized(&instance->exports, instance->module->exports.size);
+    fori (i, 0, (int) instance->module->exports.size) {
+        wasm_exporttype_t *externtype = instance->module->exports.data[i];
+
+        switch (externtype->type->kind) {
+            case WASM_EXTERN_FUNC: {
+                wasm_func_t *func = instance->funcs[externtype->index];
+                instance->exports.data[i] = wasm_func_as_extern(func);
+                break;
+            }
+
+            case WASM_EXTERN_MEMORY: {
+                wasm_memory_t *memory = instance->memories[externtype->index];
+                instance->exports.data[i] = wasm_memory_as_extern(memory);
+                break;
+            }
+
+            case WASM_EXTERN_GLOBAL: {
+                wasm_global_t *global = instance->globals[externtype->index];
+                instance->exports.data[i] = wasm_global_as_extern(global);
+                break;
+            }
+
+            case WASM_EXTERN_TABLE: {
+                wasm_table_t *table = instance->tables[externtype->index];
+                instance->exports.data[i] = wasm_table_as_extern(table);
+                break;
+            }
+        }
     }
 }
 
@@ -178,10 +304,6 @@ wasm_instance_t *wasm_instance_new(wasm_store_t *store, const wasm_module_t *mod
     bh_arr_new(store->engine->store->heap_allocator, instance->globals, module->globaltypes.size);
 
     instance->state = ovm_state_new(store->engine->engine, module->program);
-    
-    // TODO
-    instance->exports.size = 0;
-    instance->exports.data = NULL;
 
     prepare_instance(instance, imports);
 
@@ -190,3 +312,16 @@ wasm_instance_t *wasm_instance_new(wasm_store_t *store, const wasm_module_t *mod
     return instance;
 }
 
+void wasm_instance_delete(wasm_instance_t *instance) {
+    bh_arr_free(instance->funcs);
+    bh_arr_free(instance->memories);
+    bh_arr_free(instance->globals);
+    bh_arr_free(instance->tables);
+
+    wasm_extern_vec_delete(&instance->exports);
+    ovm_state_delete(instance->state);
+}
+
+void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out) {
+    *out = instance->exports;
+}
index c4305703e17783d7dbe8581a7249da233ae7355b..70c4848800432fcd33746b5775ecb2d785e49213 100644 (file)
@@ -15,6 +15,7 @@ static bool module_build(wasm_module_t *module, const wasm_byte_vec_t *binary) {
     ctx.module  = module;
     ctx.program = module->program;
     ctx.store   = engine->store;
+    ctx.next_external_func_idx = 0;
 
     while (ctx.offset < binary->size) {
         parse_section(&ctx);
@@ -23,7 +24,7 @@ static bool module_build(wasm_module_t *module, const wasm_byte_vec_t *binary) {
     // TODO: This is not correct when the module imports a global.
     // But Onyx does not do this, so I don't care at the moment.
     module->program->register_count = module->globaltypes.size;
-    
+
     return true;
 }
 
@@ -67,6 +68,10 @@ wasm_module_t *wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binar
     return module;
 }
 
+void wasm_module_delete(wasm_module_t *module) {
+    ovm_program_delete(module->program);
+}
+
 bool wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) {
     // Hmmm...
     return false;
index d37d6e2fb6be04274b032ca3d690f958efcae1c1..5f411a900ad6a449f3e154557d6c7f8f293c9238 100644 (file)
@@ -19,6 +19,7 @@ struct build_context {
     ovm_store_t   *store;
 
     int func_table_arr_idx;
+    int next_external_func_idx;
 
     // This will be set/reset for every code (function) entry.
     ovm_code_builder_t builder;
@@ -163,7 +164,8 @@ static void parse_import_section(build_context *ctx) {
                 module_name.data, module_name.size,
                 import_name.data, import_name.size);
 
-            int external_func_idx = ctx->builder.next_external_func_idx++;
+            int external_func_idx = ctx->next_external_func_idx++;
+            import->external_func_idx = external_func_idx;
 
             ovm_program_register_external_func(ctx->program, external_func_name, import_type->func.params.size, external_func_idx);
         }
@@ -420,11 +422,8 @@ static void parse_fc_instruction(build_context *ctx) {
             int dataidx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
             assert(CONSUME_BYTE(ctx) == 0x00);
 
-            ovm_code_builder_drop_value(&ctx->builder);
-            ovm_code_builder_drop_value(&ctx->builder);
-            ovm_code_builder_drop_value(&ctx->builder);
-
-            // TODO: MEMORY INIT INSTRUCTION
+            ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &dataidx);
+            ovm_code_builder_add_call(&ctx->builder, ctx->module->memory_init_idx, 4, false);
             break;
         }
 
@@ -583,8 +582,10 @@ static void parse_instruction(build_context *ctx) {
 
             int entry_count = uleb128_to_uint(ctx->binary.data, &ctx->offset);
             int *entries = bh_alloc_array(bh_heap_allocator(), int, entry_count);
+
+            int label_stack_count = bh_arr_length(ctx->builder.label_stack);
             fori (i, 0, entry_count) {
-                entries[i] = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+                entries[i] = ctx->builder.label_stack[label_stack_count - 1 - uleb128_to_uint(ctx->binary.data, &ctx->offset)].idx;
             }
 
             int default_entry = uleb128_to_uint(ctx->binary.data, &ctx->offset);
@@ -707,13 +708,17 @@ static void parse_instruction(build_context *ctx) {
         case 0x3F: {
             assert(CONSUME_BYTE(ctx) == 0x00);
 
-            int memory_size = 65536;
+            int memory_size = 65535;
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &memory_size);
             break;
         }
 
         case 0x40: {
             assert(CONSUME_BYTE(ctx) == 0x00);
+            ovm_code_builder_drop_value(&ctx->builder);
+
+            int value = -1;
+            ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &value);
             break;
         }
 
@@ -909,6 +914,11 @@ static void parse_code_section(build_context *ctx) {
     unsigned int code_count = uleb128_to_uint(ctx->binary.data, &ctx->offset);
     assert(ctx->module->functypes.size == code_count);
 
+    ctx->module->memory_init_external_idx = ctx->next_external_func_idx++;
+    
+    // HACK HACK HACK THIS IS SUCH A BAD WAY OF DOING THIS
+    ctx->module->memory_init_idx = bh_arr_length(ctx->program->funcs) + code_count;
+
     fori (i, 0, (int) code_count) {
         unsigned int code_size = uleb128_to_uint(ctx->binary.data, &ctx->offset);
         unsigned int local_sections_count = uleb128_to_uint(ctx->binary.data, &ctx->offset);
@@ -936,6 +946,8 @@ static void parse_code_section(build_context *ctx) {
         ovm_program_register_func(ctx->program, func_name, ctx->builder.start_instr, ctx->builder.param_count, ctx->builder.highest_value_number + 1);
         ovm_code_builder_free(&ctx->builder);
     }
+
+    ovm_program_register_external_func(ctx->program, "__internal_wasm_memory_init", 4, ctx->module->memory_init_external_idx);
 }
 
 
index 07a3bc19d7c8f2dd6f83f3b890a7accbde9be8f3..0f805b72df47c5d259872f63e322245a0cb8c694 100644 (file)
@@ -9,6 +9,5 @@ wasm_store_t *wasm_store_new(wasm_engine_t *engine) {
 }
 
 void wasm_store_delete(wasm_store_t *store) {
-    free(store);
 }
 
index 0ade447ecfc2027a78dd2352e36079425e0fd4ec..7909867cf6050384080489e9ed95b6cb764d8c53 100644 (file)
@@ -1,2 +1,23 @@
 
-// TODO
+#include "onyx_wasm.h"
+#include "vm.h"
+
+wasm_trap_t *wasm_trap_new(wasm_store_t *store, const wasm_message_t *msg) {
+    wasm_trap_t *trap = bh_alloc(store->engine->store->arena_allocator, sizeof(*trap));
+    trap->msg = *msg;
+
+    return trap;
+}
+
+void wasm_trap_message(const wasm_trap_t *trap, wasm_message_t *out) {
+    *out = trap->msg;
+}
+
+wasm_frame_t *wasm_trap_origin(const wasm_trap_t *trap) {
+    return NULL;
+}
+
+void wasm_trap_trace(const wasm_trap_t *trap, wasm_frame_vec_t *frames) {
+    frames->size = 0;
+    frames->data = NULL;
+}