got Hello, World to work!
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 29 Jun 2022 04:03:51 +0000 (23:03 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 29 Jun 2022 04:03:51 +0000 (23:03 -0500)
include/bh.h
include/vm.h
include/vm_codebuilder.h
src/vm/code_builder.c
src/vm/vm.c
src/wasm/instance.c
src/wasm/module_parsing.c.incl

index 08238f5053dbcc0fb410ec0920487344cb022964..498ef089139844269d25f43ba4c1a4f4d04a8e0e 100644 (file)
@@ -174,6 +174,7 @@ BH_DEF u8* float_to_ieee754(f32 f, b32 reverse);
 BH_DEF u8* double_to_ieee754(f64 f, b32 reverse);
 
 BH_DEF u64 uleb128_to_uint(u8* bytes, i32 *byte_walker);
+BH_DEF i64 leb128_to_int(u8* bytes, i32 *byte_count);
 
 
 
@@ -1279,7 +1280,25 @@ BH_DEF u64 uleb128_to_uint(u8* bytes, i32 *byte_count) {
     return res;
 }
 
+BH_DEF i64 leb128_to_int(u8* bytes, i32 *byte_count) {
+    i64 res = 0;
+    u64 shift = 0;
+    u64 size = 64;
+
+    u8 byte;
+    while (1) {
+        byte = bytes[(*byte_count)++];
+        res |= (byte & 0x7f) << shift;
+        if ((byte & 0x80) == 0) break;
+        shift += 7;
+    }
 
+    if ((shift < size) && (byte & 0x40) != 0) {
+        return res | ((~0) << shift);
+    }
+    
+    return res;
+}
 
 //-------------------------------------------------------------------------------------
 // STRING IMPLEMENTATION
index 7eef740ecf59b55ecd62109f15a869e618e723da..7c3dd33906003848d8201e8e54ff17714469c350 100644 (file)
@@ -259,8 +259,8 @@ struct ovm_instr_t {
 
 #define OVMI_IMM               0x10   // %r = i/l/f/d
 #define OVMI_MOV               0x10   // %r = %a
-#define OVMI_LOAD              0x11   // %r = mem[%a]
-#define OVMI_STORE             0x12   // mem[%a] = %b
+#define OVMI_LOAD              0x11   // %r = mem[%a + %b]
+#define OVMI_STORE             0x12   // mem[%r + %b] = %a
 #define OVMI_COPY              0x13   // memcpy(%r, %a, %b)
 #define OVMI_FILL              0x14   // memset(%r, %a, %b)
 #define OVMI_REG_GET           0x15   // %r = #a
index b8f9a0b88c30108ee865efda747e218b248e9c17..9ea581741d47daf34b511d3e6575e8a3ada223b5 100644 (file)
@@ -31,6 +31,7 @@ enum label_kind_t {
     label_kind_func,
     label_kind_block,
     label_kind_loop,
+    label_kind_if,
 };
 
 struct label_target_t {
@@ -53,12 +54,15 @@ struct branch_patch_t {
 };
 
 ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count, i32 local_count);
+label_target_t     ovm_code_builder_wasm_target_idx(ovm_code_builder_t *builder, i32 idx);
+i32                ovm_code_builder_push_label_target(ovm_code_builder_t *builder, label_kind_t kind);
+void               ovm_code_builder_pop_label_target(ovm_code_builder_t *builder);
 void               ovm_code_builder_free(ovm_code_builder_t *builder);
 void               ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr);
 void               ovm_code_builder_add_unop(ovm_code_builder_t *builder, u32 instr);
 void               ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *imm);
 void               ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 label_idx);
-void               ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx);
+void               ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx, bool branch_if_true);
 void               ovm_code_builder_add_branch_table(ovm_code_builder_t *builder, i32 count, i32 *label_indicies, i32 default_label_idx);
 void               ovm_code_builder_add_return(ovm_code_builder_t *builder);
 void               ovm_code_builder_add_call(ovm_code_builder_t *builder, i32 func_idx, i32 param_count, bool has_return_value);
@@ -70,6 +74,8 @@ void               ovm_code_builder_add_register_get(ovm_code_builder_t *builder
 void               ovm_code_builder_add_register_set(ovm_code_builder_t *builder, i32 local_idx);
 void               ovm_code_builder_add_load(ovm_code_builder_t *builder, u32 ovm_type, i32 offset);
 void               ovm_code_builder_add_store(ovm_code_builder_t *builder, u32 ovm_type, i32 offset);
+void               ovm_code_builder_add_atomic_load(ovm_code_builder_t *builder, u32 ovm_type, i32 offset);
+void               ovm_code_builder_add_atomic_store(ovm_code_builder_t *builder, u32 ovm_type, i32 offset);
 void               ovm_code_builder_add_cmpxchg(ovm_code_builder_t *builder, u32 ovm_type, i32 offset);
 void               ovm_code_builder_add_memory_copy(ovm_code_builder_t *builder);
 void               ovm_code_builder_add_memory_fill(ovm_code_builder_t *builder);
index 955ef9989d39d7a401bb3efa6bb1f32071d41593..07cb15989935f904afa05ad9b289b855ba336c25 100644 (file)
@@ -1,17 +1,29 @@
 
 #include "vm_codebuilder.h"
 
+#define BUILDER_DEBUG
+
+#if defined(BUILDER_DEBUG)
+    #define POP_VALUE(b)     (bh_arr_length((b)->execution_stack) == 0 ? (assert(("invalid value pop", 0)), 0) : bh_arr_pop((b)->execution_stack))
+#else
+    #define POP_VALUE(b) bh_arr_pop((b)->execution_stack)
+#endif
+
 #define PUSH_VALUE(b, r) (bh_arr_push((b)->execution_stack, r))
-#define POP_VALUE(b)     (bh_arr_length((b)->execution_stack) == 0 ? (assert(("invalid value pop", 0)), 0) : bh_arr_pop((b)->execution_stack))
-// #define POP_VALUE(b) bh_arr_pop((b)->execution_stack)
 
 static inline int NEXT_VALUE(ovm_code_builder_t *b) {
+#if defined(BUILDER_DEBUG)
+    b->highest_value_number += 1;
+    return b->highest_value_number;
+
+#else
     if (bh_arr_length(b->execution_stack) == 0) {
         return b->param_count + b->local_count;
     }
-
+    
     b->highest_value_number = bh_max(b->highest_value_number, bh_arr_last(b->execution_stack));
     return bh_arr_last(b->execution_stack) + 1;
+#endif
 }
 
 ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count, i32 local_count) {
@@ -41,6 +53,54 @@ void ovm_code_builder_free(ovm_code_builder_t *builder) {
     bh_arr_free(builder->branch_patches);
 }
 
+label_target_t ovm_code_builder_wasm_target_idx(ovm_code_builder_t *builder, i32 idx) {
+    i32 walker = bh_arr_length(builder->label_stack) - 1 - idx;
+    assert(walker >= 0);
+    return builder->label_stack[walker];
+}
+
+i32 ovm_code_builder_push_label_target(ovm_code_builder_t *builder, label_kind_t kind) {
+    label_target_t target;
+    target.kind = kind;
+    target.idx = builder->next_label_idx++;
+    target.instr = -1;
+
+    if (kind == label_kind_loop) {
+        target.instr = bh_arr_length(builder->program->code);
+    }
+
+    bh_arr_push(builder->label_stack, target);
+
+    return target.idx;
+}
+
+void ovm_code_builder_pop_label_target(ovm_code_builder_t *builder) {
+    label_target_t target = bh_arr_pop(builder->label_stack);
+    if (target.instr == -1) {
+        target.instr = bh_arr_length(builder->program->code);
+    }
+
+    fori (i, 0, bh_arr_length(builder->branch_patches)) {
+        branch_patch_t patch = builder->branch_patches[i];
+        if (patch.label_idx != target.idx) continue;
+
+        int br_delta = target.instr - patch.branch_instr - 1;
+
+        switch (patch.kind) {
+            case branch_patch_instr_a:
+                builder->program->code[patch.branch_instr].a = br_delta;
+                break;
+
+            case branch_patch_static_idx:
+                ovm_program_modify_static_int(builder->program, patch.static_arr, patch.static_idx, br_delta);
+                break;
+        }
+        
+        bh_arr_fastdelete(builder->branch_patches, i);
+        i--;
+    }
+}
+
 void ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr) {
     i32 right  = POP_VALUE(builder);
     i32 left   = POP_VALUE(builder);
@@ -102,9 +162,14 @@ void ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 label_idx) {
     ovm_program_add_instructions(builder->program, 1, &branch_instr);
 }
 
-void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx) {
+void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx, bool branch_if_true) {
     ovm_instr_t branch_instr = {0};
-    branch_instr.full_instr = OVMI_BR_Z;
+    if (branch_if_true) {
+        branch_instr.full_instr = OVMI_BR_NZ;
+    } else {
+        branch_instr.full_instr = OVMI_BR_Z;
+    }
+
     branch_instr.a = -1;
     branch_instr.b = POP_VALUE(builder);
 
@@ -301,73 +366,26 @@ void ovm_code_builder_add_register_set(ovm_code_builder_t *builder, i32 reg_idx)
 }
 
 void ovm_code_builder_add_load(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
-    if (offset == 0) {
-        ovm_instr_t load_instr = {0};
-        load_instr.full_instr = OVM_TYPED_INSTR(OVMI_LOAD, ovm_type);
-        load_instr.a = POP_VALUE(builder);
-        load_instr.r = NEXT_VALUE(builder);
-
-        ovm_program_add_instructions(builder->program, 1, &load_instr);
-
-        PUSH_VALUE(builder, load_instr.r);
-        return;
-    }
+    ovm_instr_t load_instr = {0};
+    load_instr.full_instr = OVM_TYPED_INSTR(OVMI_LOAD, ovm_type);
+    load_instr.b = offset;
+    load_instr.a = POP_VALUE(builder);
+    load_instr.r = NEXT_VALUE(builder);
 
-    ovm_instr_t instrs[3] = {0};
-    // 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);
+    ovm_program_add_instructions(builder->program, 1, &load_instr);
 
-    // 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 = POP_VALUE(builder);
-    instrs[1].b = instrs[0].r;
-
-    // load.x %m, %n
-    instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_LOAD, ovm_type);
-    instrs[2].r = NEXT_VALUE(builder);
-    instrs[2].a = instrs[1].r;
-
-    ovm_program_add_instructions(builder->program, 3, instrs);
-
-    PUSH_VALUE(builder, instrs[2].r);
+    PUSH_VALUE(builder, load_instr.r);
 }
 
 void ovm_code_builder_add_store(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
-    if (offset == 0) {
-        ovm_instr_t store_instr = {0};
-        store_instr.full_instr = OVM_TYPED_INSTR(OVMI_STORE, ovm_type);
-        store_instr.b = POP_VALUE(builder);
-        store_instr.a = POP_VALUE(builder);
-
-        ovm_program_add_instructions(builder->program, 1, &store_instr);
-        return;
-    }
-
-    ovm_instr_t instrs[3] = {0};
-
-    // 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 = POP_VALUE(builder);
-    instrs[1].b = instrs[0].r;
-
-    // store.x %m, %n
-    instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_STORE, ovm_type);
-    instrs[2].a = instrs[1].r;
-
-    ovm_program_add_instructions(builder->program, 3, instrs);
+    ovm_instr_t store_instr = {0};
+    store_instr.full_instr = OVM_TYPED_INSTR(OVMI_STORE, ovm_type);
+    store_instr.b = offset;
+    store_instr.a = POP_VALUE(builder);
+    store_instr.r = POP_VALUE(builder);
+
+    ovm_program_add_instructions(builder->program, 1, &store_instr);
+    return;
 }
 
 void ovm_code_builder_add_cmpxchg(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
@@ -432,3 +450,29 @@ void ovm_code_builder_add_memory_fill(ovm_code_builder_t *builder) {
 
     ovm_program_add_instructions(builder->program, 1, &instr);
 }
+
+//
+// CopyNPaste from _add_load
+void ovm_code_builder_add_atomic_load(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
+    ovm_instr_t load_instr = {0};
+    load_instr.full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_LOAD, ovm_type);
+    load_instr.b = offset;
+    load_instr.a = POP_VALUE(builder);
+    load_instr.r = NEXT_VALUE(builder);
+
+    ovm_program_add_instructions(builder->program, 1, &load_instr);
+
+    PUSH_VALUE(builder, load_instr.r);
+}
+
+//
+// CopyNPaste from _add_store
+void ovm_code_builder_add_atomic_store(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
+    ovm_instr_t store_instr = {0};
+    store_instr.full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_STORE, ovm_type);
+    store_instr.b = offset;
+    store_instr.a = POP_VALUE(builder);
+    store_instr.r = POP_VALUE(builder);
+
+    ovm_program_add_instructions(builder->program, 1, &store_instr);
+}
index 37f539ba260beb6fbe124761e86b42fcc58c36da..b9c6f4bb6877014b48936f7579d70dd58cc6b873 100644 (file)
@@ -5,6 +5,17 @@
 #include <math.h> // REMOVE THIS!!!  only needed for sqrt
 #include <pthread.h>
 
+
+static inline void ovm_print_val(ovm_value_t val) {
+    switch (val.type) {
+        case OVM_TYPE_I32: printf("i32[%d]", val.i32); break;
+        case OVM_TYPE_I64: printf("i64[%ld]", val.i64); break;
+        case OVM_TYPE_F32: printf("f32[%f]", val.f32); break;
+        case OVM_TYPE_F64: printf("f64[%lf]", val.f64); break;
+    }
+}
+
+
 //
 // Store
 ovm_store_t *ovm_store_new() {
@@ -156,11 +167,23 @@ static char *ovm_instr_name(i32 full_instr) {
         C(OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_F32))
         C(OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_F64))
 
+        C(OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_F64))
+
         C(OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I8))
         C(OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I16))
         C(OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I32))
         C(OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I64))
 
+        C(OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I64))
+
         C(OVM_TYPED_INSTR(OVMI_AND, OVM_TYPE_I8))
         C(OVM_TYPED_INSTR(OVMI_AND, OVM_TYPE_I16))
         C(OVM_TYPED_INSTR(OVMI_AND, OVM_TYPE_I32))
@@ -453,7 +476,7 @@ ovm_state_t *ovm_state_new(ovm_engine_t *engine, ovm_program_t *program) {
     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->numbered_values, 128);
     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);
@@ -650,17 +673,29 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             OVM_OP(OVMI_MUL, OVM_TYPE_F32, *, f32)
             OVM_OP(OVMI_MUL, OVM_TYPE_F64, *, f64)
 
-            OVM_OP(OVMI_DIV, OVM_TYPE_I8 , /, i8)
-            OVM_OP(OVMI_DIV, OVM_TYPE_I16, /, i16)
-            OVM_OP(OVMI_DIV, OVM_TYPE_I32, /, i32)
-            OVM_OP(OVMI_DIV, OVM_TYPE_I64, /, i64)
+            OVM_OP(OVMI_DIV, OVM_TYPE_I8 , /, u8)
+            OVM_OP(OVMI_DIV, OVM_TYPE_I16, /, u16)
+            OVM_OP(OVMI_DIV, OVM_TYPE_I32, /, u32)
+            OVM_OP(OVMI_DIV, OVM_TYPE_I64, /, u64)
             OVM_OP(OVMI_DIV, OVM_TYPE_F32, /, f32)
             OVM_OP(OVMI_DIV, OVM_TYPE_F64, /, f64)
 
-            OVM_OP(OVMI_REM, OVM_TYPE_I8 , %, i8)
-            OVM_OP(OVMI_REM, OVM_TYPE_I16, %, i16)
-            OVM_OP(OVMI_REM, OVM_TYPE_I32, %, i32)
-            OVM_OP(OVMI_REM, OVM_TYPE_I64, %, i64)
+            OVM_OP(OVMI_DIV_S, OVM_TYPE_I8 , /, i8)
+            OVM_OP(OVMI_DIV_S, OVM_TYPE_I16, /, i16)
+            OVM_OP(OVMI_DIV_S, OVM_TYPE_I32, /, i32)
+            OVM_OP(OVMI_DIV_S, OVM_TYPE_I64, /, i64)
+            OVM_OP(OVMI_DIV_S, OVM_TYPE_F32, /, f32)
+            OVM_OP(OVMI_DIV_S, OVM_TYPE_F64, /, f64)
+
+            OVM_OP(OVMI_REM, OVM_TYPE_I8 , %, u8)
+            OVM_OP(OVMI_REM, OVM_TYPE_I16, %, u16)
+            OVM_OP(OVMI_REM, OVM_TYPE_I32, %, u32)
+            OVM_OP(OVMI_REM, OVM_TYPE_I64, %, u64)
+
+            OVM_OP(OVMI_REM_S, OVM_TYPE_I8 , %, i8)
+            OVM_OP(OVMI_REM_S, OVM_TYPE_I16, %, i16)
+            OVM_OP(OVMI_REM_S, OVM_TYPE_I32, %, i32)
+            OVM_OP(OVMI_REM_S, OVM_TYPE_I64, %, i64)
 
             OVM_OP(OVMI_AND, OVM_TYPE_I8 , &, i8)
             OVM_OP(OVMI_AND, OVM_TYPE_I16, &, i16)
@@ -672,20 +707,25 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             OVM_OP(OVMI_OR, OVM_TYPE_I32, |, i32)
             OVM_OP(OVMI_OR, OVM_TYPE_I64, |, i64)
 
+            OVM_OP(OVMI_XOR, OVM_TYPE_I8 , ^, i8)
+            OVM_OP(OVMI_XOR, OVM_TYPE_I16, ^, i16)
+            OVM_OP(OVMI_XOR, OVM_TYPE_I32, ^, i32)
+            OVM_OP(OVMI_XOR, OVM_TYPE_I64, ^, i64)
+
             OVM_OP(OVMI_SHL, OVM_TYPE_I8 , <<, i8)
             OVM_OP(OVMI_SHL, OVM_TYPE_I16, <<, i16)
             OVM_OP(OVMI_SHL, OVM_TYPE_I32, <<, i32)
             OVM_OP(OVMI_SHL, OVM_TYPE_I64, <<, i64)
 
-            OVM_OP(OVMI_SHR, OVM_TYPE_I8 , >> (u8), i8)
-            OVM_OP(OVMI_SHR, OVM_TYPE_I16, >> (u16), i16)
-            OVM_OP(OVMI_SHR, OVM_TYPE_I32, >> (u32), i32)
-            OVM_OP(OVMI_SHR, OVM_TYPE_I64, >> (u64), i64)
+            OVM_OP(OVMI_SHR, OVM_TYPE_I8 , >>, u8)
+            OVM_OP(OVMI_SHR, OVM_TYPE_I16, >>, u16)
+            OVM_OP(OVMI_SHR, OVM_TYPE_I32, >>, u32)
+            OVM_OP(OVMI_SHR, OVM_TYPE_I64, >>, u64)
 
-            OVM_OP(OVMI_SAR, OVM_TYPE_I8 , >> (i8), i8)
-            OVM_OP(OVMI_SAR, OVM_TYPE_I16, >> (i16), i16)
-            OVM_OP(OVMI_SAR, OVM_TYPE_I32, >> (i32), i32)
-            OVM_OP(OVMI_SAR, OVM_TYPE_I64, >> (i64), i64)
+            OVM_OP(OVMI_SAR, OVM_TYPE_I8 , >>, i8)
+            OVM_OP(OVMI_SAR, OVM_TYPE_I16, >>, i16)
+            OVM_OP(OVMI_SAR, OVM_TYPE_I32, >>, i32)
+            OVM_OP(OVMI_SAR, OVM_TYPE_I64, >>, i64)
 
 #undef OVM_OP
 
@@ -695,15 +735,15 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                  VAL(instr.r).ctype = func( VAL(instr.a).ctype, VAL(instr.b).ctype ); \
                  break;
 
-            OVM_OP(OVMI_ROTL, OVM_TYPE_I8 , __rolb, i8)
-            OVM_OP(OVMI_ROTL, OVM_TYPE_I16, __rolw, i16)
-            OVM_OP(OVMI_ROTL, OVM_TYPE_I32, __rold, i32)
-            OVM_OP(OVMI_ROTL, OVM_TYPE_I64, __rolq, i64)
+            OVM_OP(OVMI_ROTL, OVM_TYPE_I8 , __rolb, u8)
+            OVM_OP(OVMI_ROTL, OVM_TYPE_I16, __rolw, u16)
+            OVM_OP(OVMI_ROTL, OVM_TYPE_I32, __rold, u32)
+            OVM_OP(OVMI_ROTL, OVM_TYPE_I64, __rolq, u64)
 
-            OVM_OP(OVMI_ROTR, OVM_TYPE_I8 , __rorb, i8)
-            OVM_OP(OVMI_ROTR, OVM_TYPE_I16, __rorw, i16)
-            OVM_OP(OVMI_ROTR, OVM_TYPE_I32, __rord, i32)
-            OVM_OP(OVMI_ROTR, OVM_TYPE_I64, __rorq, i64)
+            OVM_OP(OVMI_ROTR, OVM_TYPE_I8 , __rorb, u8)
+            OVM_OP(OVMI_ROTR, OVM_TYPE_I16, __rorw, u16)
+            OVM_OP(OVMI_ROTR, OVM_TYPE_I32, __rord, u32)
+            OVM_OP(OVMI_ROTR, OVM_TYPE_I64, __rorq, u64)
 
             OVM_OP(OVMI_MIN, OVM_TYPE_F32, bh_min, f32)
             OVM_OP(OVMI_MAX, OVM_TYPE_F32, bh_max, f32)
@@ -719,20 +759,20 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                  VAL(instr.r).ctype = (ctype) op (VAL(instr.a).ctype); \
                  break;
 
-            OVM_OP(OVMI_CLZ, OVM_TYPE_I8 , __builtin_clz, i8)
-            OVM_OP(OVMI_CLZ, OVM_TYPE_I16, __builtin_clz, i16)
-            OVM_OP(OVMI_CLZ, OVM_TYPE_I32, __builtin_clz, i32)
-            OVM_OP(OVMI_CLZ, OVM_TYPE_I64, __builtin_clz, i64)
+            OVM_OP(OVMI_CLZ, OVM_TYPE_I8 , __builtin_clz, u8)
+            OVM_OP(OVMI_CLZ, OVM_TYPE_I16, __builtin_clz, u16)
+            OVM_OP(OVMI_CLZ, OVM_TYPE_I32, __builtin_clz, u32)
+            OVM_OP(OVMI_CLZ, OVM_TYPE_I64, __builtin_clz, u64)
 
-            OVM_OP(OVMI_CTZ, OVM_TYPE_I8 , __builtin_ctz, i8)
-            OVM_OP(OVMI_CTZ, OVM_TYPE_I16, __builtin_ctz, i16)
-            OVM_OP(OVMI_CTZ, OVM_TYPE_I32, __builtin_ctz, i32)
-            OVM_OP(OVMI_CTZ, OVM_TYPE_I64, __builtin_ctz, i64)
+            OVM_OP(OVMI_CTZ, OVM_TYPE_I8 , __builtin_ctz, u8)
+            OVM_OP(OVMI_CTZ, OVM_TYPE_I16, __builtin_ctz, u16)
+            OVM_OP(OVMI_CTZ, OVM_TYPE_I32, __builtin_ctz, u32)
+            OVM_OP(OVMI_CTZ, OVM_TYPE_I64, __builtin_ctz, u64)
 
-            OVM_OP(OVMI_POPCNT, OVM_TYPE_I8 , __builtin_popcount, i8)
-            OVM_OP(OVMI_POPCNT, OVM_TYPE_I16, __builtin_popcount, i16)
-            OVM_OP(OVMI_POPCNT, OVM_TYPE_I32, __builtin_popcount, i32)
-            OVM_OP(OVMI_POPCNT, OVM_TYPE_I64, __builtin_popcount, i64)
+            OVM_OP(OVMI_POPCNT, OVM_TYPE_I8 , __builtin_popcount, u8)
+            OVM_OP(OVMI_POPCNT, OVM_TYPE_I16, __builtin_popcount, u16)
+            OVM_OP(OVMI_POPCNT, OVM_TYPE_I32, __builtin_popcount, u32)
+            OVM_OP(OVMI_POPCNT, OVM_TYPE_I64, __builtin_popcount, u64)
 
             OVM_OP(OVMI_ABS,     OVM_TYPE_F32, __ovm_abs, f32);
             OVM_OP(OVMI_NEG,     OVM_TYPE_F32, -, f32);
@@ -755,13 +795,13 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 #define OVM_OP(i, t, op, ctype, cast_type) \
             case OVM_TYPED_INSTR(i, t): \
                  VAL(instr.r).type = OVM_TYPE_I32; \
-                 VAL(instr.r).i32 = (i32) ((cast_type) VAL(instr.a).ctype op (cast_type) VAL(instr.b).ctype); \
+                 VAL(instr.r).i32 = (i32) (VAL(instr.a).ctype op VAL(instr.b).ctype); \
                  break;
 
-            OVM_OP(OVMI_LT, OVM_TYPE_I8 , <, i8,  u8)
-            OVM_OP(OVMI_LT, OVM_TYPE_I16, <, i16, u16)
-            OVM_OP(OVMI_LT, OVM_TYPE_I32, <, i32, u32)
-            OVM_OP(OVMI_LT, OVM_TYPE_I64, <, i64, u64)
+            OVM_OP(OVMI_LT, OVM_TYPE_I8 , <, u8,  u8)
+            OVM_OP(OVMI_LT, OVM_TYPE_I16, <, u16, u16)
+            OVM_OP(OVMI_LT, OVM_TYPE_I32, <, u32, u32)
+            OVM_OP(OVMI_LT, OVM_TYPE_I64, <, u64, u64)
             OVM_OP(OVMI_LT, OVM_TYPE_F32, <, f32, f32)
             OVM_OP(OVMI_LT, OVM_TYPE_F64, <, f64, f32)
 
@@ -772,10 +812,10 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             OVM_OP(OVMI_LT_S, OVM_TYPE_F32, <, f32, f32)
             OVM_OP(OVMI_LT_S, OVM_TYPE_F64, <, f64, f32)
 
-            OVM_OP(OVMI_LE, OVM_TYPE_I8 , <=, i8,  u8)
-            OVM_OP(OVMI_LE, OVM_TYPE_I16, <=, i16, u16)
-            OVM_OP(OVMI_LE, OVM_TYPE_I32, <=, i32, u32)
-            OVM_OP(OVMI_LE, OVM_TYPE_I64, <=, i64, u64)
+            OVM_OP(OVMI_LE, OVM_TYPE_I8 , <=, u8,  u8)
+            OVM_OP(OVMI_LE, OVM_TYPE_I16, <=, u16, u16)
+            OVM_OP(OVMI_LE, OVM_TYPE_I32, <=, u32, u32)
+            OVM_OP(OVMI_LE, OVM_TYPE_I64, <=, u64, u64)
             OVM_OP(OVMI_LE, OVM_TYPE_F32, <=, f32, f32)
             OVM_OP(OVMI_LE, OVM_TYPE_F64, <=, f64, f64)
 
@@ -793,10 +833,10 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             OVM_OP(OVMI_EQ, OVM_TYPE_F32, ==, f32, f32)
             OVM_OP(OVMI_EQ, OVM_TYPE_F64, ==, f64, f64)
 
-            OVM_OP(OVMI_GE, OVM_TYPE_I8 , >=, i8,  u8)
-            OVM_OP(OVMI_GE, OVM_TYPE_I16, >=, i16, u16)
-            OVM_OP(OVMI_GE, OVM_TYPE_I32, >=, i32, u32)
-            OVM_OP(OVMI_GE, OVM_TYPE_I64, >=, i64, u64)
+            OVM_OP(OVMI_GE, OVM_TYPE_I8 , >=, u8,  u8)
+            OVM_OP(OVMI_GE, OVM_TYPE_I16, >=, u16, u16)
+            OVM_OP(OVMI_GE, OVM_TYPE_I32, >=, u32, u32)
+            OVM_OP(OVMI_GE, OVM_TYPE_I64, >=, u64, u64)
             OVM_OP(OVMI_GE, OVM_TYPE_F32, >=, f32, f32)
             OVM_OP(OVMI_GE, OVM_TYPE_F64, >=, f64, f64)
 
@@ -807,10 +847,10 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             OVM_OP(OVMI_GE_S, OVM_TYPE_F32, >=, f32, f32)
             OVM_OP(OVMI_GE_S, OVM_TYPE_F64, >=, f64, f64)
 
-            OVM_OP(OVMI_GT, OVM_TYPE_I8 , >, i8,  u8)
-            OVM_OP(OVMI_GT, OVM_TYPE_I16, >, i16, u16)
-            OVM_OP(OVMI_GT, OVM_TYPE_I32, >, i32, u32)
-            OVM_OP(OVMI_GT, OVM_TYPE_I64, >, i64, u64)
+            OVM_OP(OVMI_GT, OVM_TYPE_I8 , >, u8,  u8)
+            OVM_OP(OVMI_GT, OVM_TYPE_I16, >, u16, u16)
+            OVM_OP(OVMI_GT, OVM_TYPE_I32, >, u32, u32)
+            OVM_OP(OVMI_GT, OVM_TYPE_I64, >, u64, u64)
             OVM_OP(OVMI_GT, OVM_TYPE_F32, >, f32, f32)
             OVM_OP(OVMI_GT, OVM_TYPE_F64, >, f64, f64)
 
@@ -850,11 +890,12 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                 break;
 
 #define OVM_LOAD(type_, stype) \
-            case OVM_TYPED_INSTR(OVMI_LOAD, type_): \
+            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;
+                VAL(instr.r).stype = * (stype *) &((u8 *) engine->memory)[VAL(instr.a).u32 + instr.b]; \
+                break; \
+            }
 
             OVM_LOAD(OVM_TYPE_I8,  i8)
             OVM_LOAD(OVM_TYPE_I16, i16)
@@ -867,8 +908,8 @@ 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; \
+                assert(VAL(instr.r).type == OVM_TYPE_I32); \
+                * (stype *) &((u8 *) engine->memory)[VAL(instr.r).u32 + instr.b] = VAL(instr.a).stype; \
                 break;
 
             OVM_STORE(OVM_TYPE_I8,  i8)
@@ -886,7 +927,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                 i32 count = VAL(instr.b).i32;
 
                 u8 *base = engine->memory;
-                memcpy(&base[dest], &base[src], count);
+                memmove(&base[dest], &base[src], count);
                 break;
             }
 
@@ -937,6 +978,10 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                     VAL(frame.return_number_value) = val;
                 }
 
+                printf("Returning from %s to %s: ", frame.func->name, bh_arr_last(state->stack_frames).func->name); 
+                ovm_print_val(val);
+                printf("\n\n");
+                
                 state->pc = frame.return_address;
                 break;
             }
@@ -1053,11 +1098,14 @@ 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_CMPXCHG, otype): {\
         ctype *addr = (ctype *) &((u8 *) engine->memory)[VAL(instr.r).i32]; \
+ \
+        VAL(instr.r).i32 = 0; \
+        VAL(instr.r).type = otype; \
+        VAL(instr.r).ctype = *addr; \
+ \
         if (*addr == VAL(instr.a).ctype) { \
             *addr = VAL(instr.b).ctype ; \
         } \
-        VAL(instr.r).type = otype; \
-        VAL(instr.r).ctype = *addr; \
         break; \
     }
 
index 4ab07c8ea3f80ed228ba52fab5d2ddf88f063486..4864eca89933abfae70dc8b356c973ff9defe49a 100644 (file)
@@ -104,8 +104,6 @@ static void ovm_to_wasm_func_call_binding(void *env, ovm_value_t* params, ovm_va
         OVM_TO_WASM(params[i], wasm_params.data[i]);
     }
 
-    // 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;
@@ -124,9 +122,6 @@ static void wasm_memory_init(void *env, ovm_value_t* params, ovm_value_t *res) {
     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);
 }
 
index 5f411a900ad6a449f3e154557d6c7f8f293c9238..134bc20aa185c96c36909f01fa3ad50aed4a3121 100644 (file)
@@ -361,48 +361,6 @@ static void parse_data_count_section(build_context *ctx) {
 // Instruction building
 //
 
-static int push_label_target(build_context *ctx, label_kind_t kind) {
-    label_target_t target;
-    target.kind = kind;
-    target.idx = ctx->builder.next_label_idx++;
-    target.instr = -1;
-
-    if (kind == label_kind_loop) {
-        target.instr = bh_arr_length(ctx->program->code);
-    }
-
-    bh_arr_push(ctx->builder.label_stack, target);
-
-    return target.idx;
-}
-
-static void pop_label_target(build_context *ctx) {
-    label_target_t target = bh_arr_pop(ctx->builder.label_stack);
-    if (target.instr == -1) {
-        target.instr = bh_arr_length(ctx->program->code);
-    }
-
-    fori (i, 0, bh_arr_length(ctx->builder.branch_patches)) {
-        branch_patch_t patch = ctx->builder.branch_patches[i];
-        if (patch.label_idx != target.idx) continue;
-
-        int br_delta = target.instr - patch.branch_instr - 1;
-
-        switch (patch.kind) {
-            case branch_patch_instr_a:
-                ctx->program->code[patch.branch_instr].a = br_delta;
-                break;
-
-            case branch_patch_static_idx:
-                ovm_program_modify_static_int(ctx->program, patch.static_arr, patch.static_idx, br_delta);
-                break;
-        }
-        
-        bh_arr_fastdelete(ctx->builder.branch_patches, i);
-        i--;
-    }
-}
-
 static void parse_expression(build_context *ctx);
 
 static void parse_fc_instruction(build_context *ctx) {
@@ -455,7 +413,7 @@ static void parse_fe_instruction(build_context *ctx) {
         case num : { \
             int alignment = uleb128_to_uint(ctx->binary.data, &ctx->offset); \
             int offset    = uleb128_to_uint(ctx->binary.data, &ctx->offset); \
-            ovm_code_builder_add_load(&ctx->builder, OVMI_ATOMIC | type, offset); \
+            ovm_code_builder_add_atomic_load(&ctx->builder, type, offset); \
             break; \
         }
 
@@ -473,7 +431,7 @@ static void parse_fe_instruction(build_context *ctx) {
         case num : { \
             int alignment = uleb128_to_uint(ctx->binary.data, &ctx->offset); \
             int offset    = uleb128_to_uint(ctx->binary.data, &ctx->offset); \
-            ovm_code_builder_add_store(&ctx->builder, OVMI_ATOMIC | type, offset); \
+            ovm_code_builder_add_atomic_store(&ctx->builder, type, offset); \
             break; \
         }
 
@@ -517,26 +475,26 @@ static void parse_instruction(build_context *ctx) {
         case 0x02: {
             // Currently, only "void" block types are valid.
             assert(CONSUME_BYTE(ctx) == 0x40);
-            push_label_target(ctx, label_kind_block);
+            ovm_code_builder_push_label_target(&ctx->builder, label_kind_block);
             break;
         }
 
         case 0x03: {
             // Currently, only "void" block types are valid.
             assert(CONSUME_BYTE(ctx) == 0x40);
-            push_label_target(ctx, label_kind_loop);
+            ovm_code_builder_push_label_target(&ctx->builder, label_kind_loop);
             break;
         }
 
         case 0x04: {
             // Currently, only "void" block types are valid.
             assert(CONSUME_BYTE(ctx) == 0x40);
-            int if_target = push_label_target(ctx, label_kind_block);
+            int if_target = ovm_code_builder_push_label_target(&ctx->builder, label_kind_if);
 
             //
             // This uses the pattern of "branch if zero" to skip a section of
             // code if the condition was not true.
-            ovm_code_builder_add_cond_branch(&ctx->builder, if_target);
+            ovm_code_builder_add_cond_branch(&ctx->builder, if_target, false);
             break;
         }
 
@@ -550,21 +508,21 @@ static void parse_instruction(build_context *ctx) {
             // Therefore, this "peeks" at what the next label index will be, so it can
             // know what label to track for where to jump. It feels like there should be
             // a better way to do this.
-            ovm_code_builder_add_branch(&ctx->builder, bh_arr_last(ctx->builder.label_stack).idx);
-            pop_label_target(ctx);
-            push_label_target(ctx, label_kind_block);
+            ovm_code_builder_pop_label_target(&ctx->builder);
+            int else_target = ovm_code_builder_push_label_target(&ctx->builder, label_kind_if);
+            ovm_code_builder_add_branch(&ctx->builder, else_target);
             break;
         }
 
         case 0x0B: {
-            pop_label_target(ctx);
+            ovm_code_builder_pop_label_target(&ctx->builder);
             break;
         }
 
         case 0x0C: {
             int label_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
 
-            label_target_t target = *((&bh_arr_last(ctx->builder.label_stack)) - label_idx);
+            label_target_t target = ovm_code_builder_wasm_target_idx(&ctx->builder, label_idx);
             ovm_code_builder_add_branch(&ctx->builder, target.idx);
             break;
         }
@@ -572,8 +530,8 @@ static void parse_instruction(build_context *ctx) {
         case 0x0D: {
             int label_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
 
-            label_target_t target = *((&bh_arr_last(ctx->builder.label_stack)) - label_idx);
-            ovm_code_builder_add_cond_branch(&ctx->builder, target.idx);
+            label_target_t target = ovm_code_builder_wasm_target_idx(&ctx->builder, label_idx);
+            ovm_code_builder_add_cond_branch(&ctx->builder, target.idx, true);
             break;
         }
 
@@ -583,12 +541,15 @@ 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] = ctx->builder.label_stack[label_stack_count - 1 - uleb128_to_uint(ctx->binary.data, &ctx->offset)].idx;
+                int label_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+                label_target_t target = ovm_code_builder_wasm_target_idx(&ctx->builder, label_idx);
+                entries[i] = target.idx;
             }
 
-            int default_entry = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+            int default_entry_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+            label_target_t target = ovm_code_builder_wasm_target_idx(&ctx->builder, default_entry_idx);
+            int default_entry = target.idx;
 
             ovm_code_builder_add_branch_table(&ctx->builder, entry_count, entries, default_entry);
             break;
@@ -723,13 +684,16 @@ static void parse_instruction(build_context *ctx) {
         }
 
         case 0x41: {
-            int value = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+            long long value = leb128_to_int(ctx->binary.data, &ctx->offset);
+
+            // NOTE: This assumes a little-endian CPU as the address is assumes
+            // to be the least significant byte.
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &value);
             break;
         }
 
         case 0x42: {
-            long long value = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+            unsigned long long value = uleb128_to_uint(ctx->binary.data, &ctx->offset);
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I64, &value);
             break;
         }
@@ -749,12 +713,11 @@ static void parse_instruction(build_context *ctx) {
         }
 
         case 0x45: {
-            int zero = 0;
+            unsigned int zero = 0;
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &zero);
             ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I32));
             break;
         }
-
         case 0x46: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I32)); break;
         case 0x47: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_I32)); break;
         case 0x48: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LT_S, OVM_TYPE_I32)); break;
@@ -767,7 +730,7 @@ static void parse_instruction(build_context *ctx) {
         case 0x4F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE, OVM_TYPE_I32)); break;
 
         case 0x50: {
-            long long zero = 0;
+            unsigned long long zero = 0;
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I64, &zero);
             ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I64));
             break;
@@ -803,10 +766,10 @@ static void parse_instruction(build_context *ctx) {
         case 0x6A: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32)); break;
         case 0x6B: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_I32)); break;
         case 0x6C: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_I32)); break;
-        case 0x6D: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_I32)); break;
-        case 0x6E: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I32)); break;
-        case 0x6F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I32)); break;
-        case 0x70: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I32)); break;
+        case 0x6D: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I32)); break;
+        case 0x6E: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_I32)); break;
+        case 0x6F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I32)); break;
+        case 0x70: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I32)); break;
         case 0x71: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_AND, OVM_TYPE_I32)); break;
         case 0x72: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_OR, OVM_TYPE_I32)); break;
         case 0x73: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_XOR, OVM_TYPE_I32)); break;
@@ -822,10 +785,10 @@ static void parse_instruction(build_context *ctx) {
         case 0x7C: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I64)); break;
         case 0x7D: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_I64)); break;
         case 0x7E: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_I64)); break;
-        case 0x7F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_I64)); break;
-        case 0x80: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I64)); break;
-        case 0x81: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I64)); break;
-        case 0x82: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I64)); break;
+        case 0x7F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I64)); break;
+        case 0x80: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_I64)); break;
+        case 0x81: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I64)); break;
+        case 0x82: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I64)); break;
         case 0x83: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_AND, OVM_TYPE_I64)); break;
         case 0x84: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_OR, OVM_TYPE_I64)); break;
         case 0x85: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_XOR, OVM_TYPE_I64)); break;
@@ -938,9 +901,10 @@ static void parse_code_section(build_context *ctx) {
         ctx->builder = ovm_code_builder_new(ctx->program, param_count, total_locals);
         ctx->builder.func_table_arr_idx = ctx->func_table_arr_idx;
 
-        push_label_target(ctx, label_kind_func);
+        ovm_code_builder_push_label_target(&ctx->builder, label_kind_func);
         parse_expression(ctx);
         ovm_code_builder_add_return(&ctx->builder);
+        ovm_code_builder_pop_label_target(&ctx->builder);
 
         char *func_name = bh_aprintf(bh_heap_allocator(), "wasm_loaded_%d", bh_arr_length(ctx->program->funcs));
         ovm_program_register_func(ctx->program, func_name, ctx->builder.start_instr, ctx->builder.param_count, ctx->builder.highest_value_number + 1);