successfully compiling 'real.onyx' to ovm!
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 26 Jun 2022 22:03:50 +0000 (17:03 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 26 Jun 2022 22:03:50 +0000 (17:03 -0500)
12 files changed:
build.sh
include/vm.h
include/vm_codebuilder.h
src/tools/assembler.c
src/vm/code_builder.c
src/vm/vm.c
src/wasm/module_parsing.c.incl
src/wasm_cli_test.c
tests/ovm/out.ovm
tests/ovm/test.asm
tests/wasm/out.wasm
tests/wasm/tiny.onyx

index 42da70a793b8c0658404cd0aded20fd8f9cb253f..160e4565e3a07b4bdb49c758614569f3f8208fcd 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -3,7 +3,7 @@
 CC="gcc"
 WARNINGS='-Wimplicit -Wmisleading-indentation -Wparentheses -Wsequence-point -Wreturn-type -Wshift-negative-value -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-function -Wunused-label -Wmaybe-uninitialized -Wsign-compare -Wstrict-overflow -Wduplicated-branches -Wduplicated-cond -Wtrigraphs -Waddress -Wlogical-op'
 FLAGS="-g3"
-LIBS=
+LIBS="-pthread"
 INCLUDES="-I include"
 TARGET="libonyx_embedder.so"
 C_FILES="src/wasm.c src/vm/*.c src/wasm/*.c"
@@ -13,7 +13,7 @@ $CC $FLAGS $INCLUDES -shared -fPIC -o $TARGET $C_FILES $LIBS $WARNINGS
 
 C_FILES="src/ovm_cli_test.c"
 TARGET=bin/ovm_cli_test
-LIBS="-L$(pwd) -lonyx_embedder -lm -Wl,-rpath=./"
+LIBS="-L$(pwd) -lonyx_embedder -pthread -lm -Wl,-rpath=./"
 
 $CC $FLAGS $INCLUDES -o $TARGET $C_FILES $LIBS $WARNINGS
 
index 2b5157b4a41d0e495c7735a9abd66e77823d3682..080ae0417912a2bd90d02a4b075d060379f88817 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "bh.h"
 #include <stdbool.h>
+#include <pthread.h>
 
 typedef u8  ovm_valtype_t;
 typedef i32 ovm_valnum_t;
@@ -73,6 +74,7 @@ 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);
 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);
 
 //
 // Represents the running configuration and static
@@ -82,6 +84,8 @@ void ovm_program_begin_func(ovm_program_t *program, char *name, i32 param_count,
 struct ovm_engine_t {
     ovm_store_t *store;
 
+    pthread_mutex_t atomic_mutex;
+
     i64   memory_size; // This is probably going to always be 4GiB.
     void *memory;
 };
@@ -234,6 +238,7 @@ struct ovm_instr_t {
 #define OVM_INSTR_TYPE(instr)  ((instr).full_instr >> 24)
 #define OVM_INSTR_INSTR(instr) ((instr).full_instr & 0xffffff)
 
+#define OVMI_ATOMIC            0x00800000 // Flag an instruction as atomic
 
 #define OVMI_NOP               0x00
 #define OVMI_ADD               0x01   // %r = %a + %b
@@ -322,6 +327,8 @@ struct ovm_instr_t {
 #define OVMI_TRANSMUTE_F32     0x6C   // %r = *(t *) &%a (reinterpret bytes)
 #define OVMI_TRANSMUTE_F64     0x6D   // %r = *(t *) &%a (reinterpret bytes)
 
+#define OVMI_CMPXCHG           0x70   // %r = %r == %a ? %b : %r 
+
 //
 // OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32) == instruction for adding i32s
 //
index cd078d0d98fee810ca61cb90e1bca99747188779..c3c2d7e677582984974a80703903cc77b962dae5 100644 (file)
@@ -40,9 +40,17 @@ struct label_target_t {
     i32 instr;
 };
 
+enum branch_patch_kind_t {
+    branch_patch_instr_a,    // For patching the '.a' register of a branch instruction.
+    branch_patch_static_idx, // For patching an integer in the static integers section.
+};
+
 struct branch_patch_t {
+    enum branch_patch_kind_t kind;
     i32 branch_instr;
     i32 label_idx;
+    i32 static_arr;
+    i32 static_idx;
 };
 
 ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count, i32 local_count);
@@ -52,6 +60,7 @@ void               ovm_code_builder_add_unop(ovm_code_builder_t *builder, u32 in
 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_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);
 void               ovm_code_builder_add_indirect_call(ovm_code_builder_t *builder, i32 param_count, bool has_return_value);
@@ -62,6 +71,7 @@ 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_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 2610ffe9b985e1a6d56c20602841ca0cc308be0d..147a5fef1c87173820addfd7aa761c47538f7c0e 100644 (file)
@@ -191,6 +191,8 @@ static struct instruction_mapping_t instr_map[] = {
     { "cvt.f64.i32", OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32), op_reg, op_reg },
     { "cvt.f64.i64", OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64), op_reg, op_reg },
     { "cvt.f64.f32", OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32), op_reg, op_reg },
+
+    { "atomic.add.i32", OVM_TYPED_INSTR(OVMI_ADD | OVMI_ATOMIC, OVM_TYPE_I32), op_reg, op_reg, op_reg },
 };
 
 void parse_register(i32 *dest) {
index 3701078ea2b88c7f3036d0c4c609b6fc841db8d1..b6b1be7fc13ce82fe0e90d06ba77e270d02c54f0 100644 (file)
@@ -93,6 +93,7 @@ void ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 label_idx) {
     branch_instr.a = -1;
 
     branch_patch_t patch;
+    patch.kind = branch_patch_instr_a;
     patch.branch_instr = bh_arr_length(builder->program->code);
     patch.label_idx = label_idx;
 
@@ -108,6 +109,7 @@ void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx
     branch_instr.b = POP_VALUE(builder);
 
     branch_patch_t patch;
+    patch.kind = branch_patch_instr_a;
     patch.branch_instr = bh_arr_length(builder->program->code);
     patch.label_idx = label_idx;
 
@@ -116,6 +118,61 @@ void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx
     ovm_program_add_instructions(builder->program, 1, &branch_instr);
 }
 
+void ovm_code_builder_add_branch_table(ovm_code_builder_t *builder, i32 count, i32 *label_indicies, i32 default_label_idx) {
+    //
+    // Passing label indicies here is a little disingenuous, because that is not
+    // what the data will have to be. But since it is already the correct length
+    // I am using it as a subsitute.
+    int table_idx = ovm_program_register_static_ints(builder->program, count, label_indicies);
+    assert(table_idx > 0);
+
+    ovm_instr_t instrs[5] = {0};
+    int tmp_register = NEXT_VALUE(builder);
+    int index_register = POP_VALUE(builder);
+    PUSH_VALUE(builder, tmp_register);
+
+    instrs[0].full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32);
+    instrs[0].r = tmp_register;
+    instrs[0].i = count;
+
+    instrs[1].full_instr = OVM_TYPED_INSTR(OVMI_LE, OVM_TYPE_I32);
+    instrs[1].r = tmp_register;
+    instrs[1].a = index_register;
+    instrs[1].b = tmp_register;
+
+    instrs[2].full_instr = OVMI_BR_Z;
+    instrs[2].a = -1;
+    instrs[2].b = tmp_register;
+
+    instrs[3].full_instr = OVMI_IDX_ARR;
+    instrs[3].r = tmp_register;
+    instrs[3].a = table_idx;
+    instrs[3].b = index_register;
+    
+    instrs[4].full_instr = OVMI_BRI;
+    instrs[4].a = tmp_register;
+    
+    POP_VALUE(builder);
+    
+    fori (i, 0, count) {
+        branch_patch_t patch;
+        patch.kind = branch_patch_static_idx;
+        patch.branch_instr = bh_arr_length(builder->program->code) + 4;
+        patch.label_idx = label_indicies[i];
+        patch.static_arr = table_idx;
+        patch.static_idx = i;
+        bh_arr_push(builder->branch_patches, patch);
+    }
+
+    branch_patch_t default_patch;
+    default_patch.kind = branch_patch_instr_a;
+    default_patch.branch_instr = bh_arr_length(builder->program->code) + 2;
+    default_patch.label_idx = default_label_idx;
+    bh_arr_push(builder->branch_patches, default_patch);
+
+    ovm_program_add_instructions(builder->program, 5, instrs);
+}
+
 void ovm_code_builder_add_return(ovm_code_builder_t *builder) {
     ovm_instr_t instr = {0};
     instr.full_instr = OVMI_RETURN;
@@ -304,6 +361,47 @@ void ovm_code_builder_add_store(ovm_code_builder_t *builder, u32 ovm_type, i32 o
     ovm_program_add_instructions(builder->program, 3, instrs);
 }
 
+void ovm_code_builder_add_cmpxchg(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
+    if (offset == 0) {
+        ovm_instr_t cmpxchg_instr = {0};
+        cmpxchg_instr.full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_CMPXCHG, ovm_type);
+        cmpxchg_instr.b = POP_VALUE(builder);
+        cmpxchg_instr.a = POP_VALUE(builder);
+        cmpxchg_instr.r = POP_VALUE(builder);
+
+        ovm_program_add_instructions(builder->program, 1, &cmpxchg_instr);
+
+        PUSH_VALUE(builder, cmpxchg_instr.r);
+        return;
+    }
+
+    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);
+
+    // 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;
+
+    // cmpxchg.x %m, %n
+    instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_CMPXCHG, ovm_type);
+    instrs[2].r = instrs[1].r;
+    instrs[2].a = expected_reg;
+    instrs[2].b = value_reg;
+
+    ovm_program_add_instructions(builder->program, 3, instrs);
+
+    PUSH_VALUE(builder, instrs[2].r);
+}
+
 void ovm_code_builder_add_memory_copy(ovm_code_builder_t *builder) {
     ovm_instr_t instr = {0};
     instr.full_instr = OVMI_COPY;
index 3ef3af151a9e8a5e0dd6efebc27f6a9c18cd3022..7084ac312915e834b4c6715396c577131adfe86c 100644 (file)
@@ -3,6 +3,7 @@
 #include <sys/mman.h>
 #include <x86intrin.h>
 #include <math.h> // REMOVE THIS!!!  only needed for sqrt
+#include <pthread.h>
 
 //
 // Store
@@ -57,6 +58,15 @@ int ovm_program_register_static_ints(ovm_program_t *program, int len, int *data)
     return bh_arr_length(program->static_data) - 1;
 }
 
+void ovm_program_modify_static_int(ovm_program_t *program, int arr, int idx, int new_value) {
+    if (arr >= bh_arr_length(program->static_data)) return;
+    
+    ovm_static_integer_array_t array = program->static_data[arr];
+    if (idx >= array.len) return;
+
+    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) {
     ovm_func_t func;
     func.kind = OVM_FUNC_INTERNAL;
@@ -99,7 +109,9 @@ void ovm_program_add_instructions(ovm_program_t *program, i32 instr_count, ovm_i
 
 
 static char *ovm_instr_name(i32 full_instr) {
-#define C(...) case __VA_ARGS__: return #__VA_ARGS__;
+#define C(...) \
+    case __VA_ARGS__: return #__VA_ARGS__; \
+    case __VA_ARGS__ | OVMI_ATOMIC: return "ATOMIC_" #__VA_ARGS__;
 
     static char buf[64];
 
@@ -350,6 +362,11 @@ static char *ovm_instr_name(i32 full_instr) {
         C(OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64))
         C(OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32))
 
+        C(OVM_TYPED_INSTR(OVMI_CMPXCHG, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_CMPXCHG, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_CMPXCHG, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_CMPXCHG, OVM_TYPE_I64))
+
         default:
             snprintf(buf, 64, "unknown (%d)", full_instr);
             return buf;
@@ -547,6 +564,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 #define VAL(loc) (state->numbered_values[(u32) (loc + state->value_number_offset)])
 
     ovm_instr_t *code = program->code;
+    bool release_mutex_at_end = false;
    
     while (state->pc < bh_arr_length(program->code)) {
         //
@@ -557,6 +575,13 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
         // being executed.                  - brendanfh 2022/06/13
         ovm_instr_t instr = code[state->pc++];
 
+        if (instr.full_instr & OVMI_ATOMIC) {
+            pthread_mutex_lock(&engine->atomic_mutex);
+            release_mutex_at_end = true;
+
+            instr.full_instr &= ~OVMI_ATOMIC;
+        }
+
         switch (instr.full_instr) {
             case OVMI_NOP: break;
 
@@ -978,6 +1003,21 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 
 #undef CVT
 
+
+#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 ; \
+        } \
+        break;
+
+            CMPXCHG(OVM_TYPE_I8,  i8)
+            CMPXCHG(OVM_TYPE_I16, i16)
+            CMPXCHG(OVM_TYPE_I32, i32)
+            CMPXCHG(OVM_TYPE_I64, i64)
+
+#undef CMPXCHG
+
             default:
                 printf("ERROR:\n");
                 ovm_program_print_instructions(program, state->pc - 1, 1);
@@ -985,6 +1025,11 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                 assert(("ILLEGAL INSTRUCTION", 0));
                 break;
         }
+
+        if (release_mutex_at_end) {
+            pthread_mutex_unlock(&engine->atomic_mutex);
+            release_mutex_at_end = false;
+        }
     }
 }
 
index 2ee8941affbadbbffe3e6c72ec6c82b7a06e6996..1b4e7dd185bd6a9f92a5b35e250c6e3fef67ea2f 100644 (file)
@@ -18,6 +18,8 @@ struct build_context {
     ovm_program_t *program;
     ovm_store_t   *store;
 
+    int func_table_arr_idx;
+
     // This will be set/reset for every code (function) entry.
     ovm_code_builder_t builder;
 };
@@ -301,6 +303,8 @@ static void parse_elem_section(build_context *ctx) {
     fori (i, 0, (int) entry_count) {
         ctx->module->elem_entries[i] = uleb128_to_uint(ctx->binary.data, &ctx->offset);
     }
+
+    ctx->func_table_arr_idx = ovm_program_register_static_ints(ctx->program, entry_count, ctx->module->elem_entries);
 }
 
 static void parse_data_section(build_context *ctx) {
@@ -377,7 +381,18 @@ static void pop_label_target(build_context *ctx) {
         branch_patch_t patch = ctx->builder.branch_patches[i];
         if (patch.label_idx != target.idx) continue;
 
-        ctx->program->code[patch.branch_instr].a = target.instr - patch.branch_instr - 1;
+        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--;
     }
@@ -429,6 +444,69 @@ static void parse_fc_instruction(build_context *ctx) {
     }
 }
 
+static void parse_fe_instruction(build_context *ctx) {
+    int instr_num = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+
+    switch (instr_num) {
+
+#define LOAD_CASE(num, type) \
+        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); \
+            break; \
+        }
+
+        LOAD_CASE(0x10, OVM_TYPE_I32)
+        LOAD_CASE(0x11, OVM_TYPE_I64)
+        LOAD_CASE(0x12, OVM_TYPE_I8)
+        LOAD_CASE(0x13, OVM_TYPE_I16)
+        LOAD_CASE(0x14, OVM_TYPE_I8)
+        LOAD_CASE(0x15, OVM_TYPE_I16)
+        LOAD_CASE(0x16, OVM_TYPE_I32)
+
+#undef LOAD_CASE
+
+#define STORE_CASE(num, type) \
+        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); \
+            break; \
+        }
+
+        STORE_CASE(0x17, OVM_TYPE_I32)
+        STORE_CASE(0x18, OVM_TYPE_I64)
+        STORE_CASE(0x19, OVM_TYPE_I8)
+        STORE_CASE(0x1A, OVM_TYPE_I16)
+        STORE_CASE(0x1B, OVM_TYPE_I8)
+        STORE_CASE(0x1C, OVM_TYPE_I16)
+        STORE_CASE(0x1D, OVM_TYPE_I32)
+
+#undef STORE_CASE
+
+#define CMPXCHG_CASE(num, type) \
+        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_cmpxchg(&ctx->builder, type, offset); \
+            break; \
+        }
+
+        CMPXCHG_CASE(0x48, OVM_TYPE_I32)
+        CMPXCHG_CASE(0x49, OVM_TYPE_I64)
+        CMPXCHG_CASE(0x4A, OVM_TYPE_I8)
+        CMPXCHG_CASE(0x4B, OVM_TYPE_I16)
+        CMPXCHG_CASE(0x4C, OVM_TYPE_I8)
+        CMPXCHG_CASE(0x4D, OVM_TYPE_I16)
+        CMPXCHG_CASE(0x4E, OVM_TYPE_I32)
+
+#undef CMPXCHG_CASE
+
+        default: assert(("UNHANDLED ATOMIC INSTRUCTION... SORRY :/", 0));
+    }
+}
+
 static void parse_instruction(build_context *ctx) {
     unsigned char instr_byte = CONSUME_BYTE(ctx);
     switch (instr_byte) {
@@ -470,7 +548,7 @@ 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, ctx->builder.next_label_idx);
+            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);
             break;
@@ -497,8 +575,18 @@ static void parse_instruction(build_context *ctx) {
             break;
         }
 
-        case 0x0E: assert(0); {
-            // TODO: Branch tables
+        case 0x0E: {
+            // Branch tables are the most complicated thing ever :/
+
+            int entry_count = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+            int *entries = bh_alloc_array(bh_heap_allocator(), int, entry_count);
+            fori (i, 0, entry_count) {
+                entries[i] = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+            }
+
+            int default_entry = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+
+            ovm_code_builder_add_branch_table(&ctx->builder, entry_count, entries, default_entry);
             break;
         }
 
@@ -618,6 +706,7 @@ static void parse_instruction(build_context *ctx) {
 
             int memory_size = 65536;
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &memory_size);
+            break;
         }
 
         case 0x40: {
@@ -646,7 +735,7 @@ static void parse_instruction(build_context *ctx) {
 
         case 0x44: {
             double value = * (f64 *) &ctx->binary.data[ctx->offset];
-            ctx->offset += 4;
+            ctx->offset += 8;
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_F64, &value);
             break;
         }
@@ -800,6 +889,7 @@ static void parse_instruction(build_context *ctx) {
         case 0xC4: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64)); break;
 
         case 0xFC: parse_fc_instruction(ctx); break;
+        case 0xFE: parse_fe_instruction(ctx); break;
 
         default: assert(("UNHANDLED INSTRUCTION", 0));
     }
@@ -830,10 +920,10 @@ static void parse_code_section(build_context *ctx) {
 
         // Set up a lot of stuff...
 
-        i32 param_count = wasm_module_index_functype(ctx->module, i)->type.func.params.size;
+        i32 param_count = ctx->module->functypes.data[i]->type.func.params.size;
 
         ctx->builder = ovm_code_builder_new(ctx->program, param_count, total_locals);
-        ctx->builder.func_table_arr_idx = 0; // This might not be right
+        ctx->builder.func_table_arr_idx = ctx->func_table_arr_idx;
 
         push_label_target(ctx, label_kind_func);
         parse_expression(ctx);
index f0d841419009dfe8b4eafcdecd659bd3ec0c646c..5f06ea99810ef764dd19e3640b3163c090db740d 100644 (file)
@@ -46,6 +46,6 @@ int main(int argc, char *argv[]) {
         bh_printf("exports: %b  %d\n", export_name->data, export_name->size, wasm_externtype_kind(wasm_exporttype_type(exports.data[i])));
     }
 
-    ovm_program_print_instructions(module->program, 0, 150);
+    ovm_program_print_instructions(module->program, 0, bh_arr_length(module->program->code));
 }
 
index 208d51a39ba22233904f4543dbe08b13c8111277..19fd7f28f90bd1e007a58ee37ed305e792ee9008 100644 (file)
Binary files a/tests/ovm/out.ovm and b/tests/ovm/out.ovm differ
index f6d8ffbd8897168b632e81cf34d04879ba4cd465..0571ebf2a7cc143f1fb617756381eff29d9e5ee5 100644 (file)
@@ -48,6 +48,7 @@
     calli %4
 
     reg.set stack_ptr, %10
+    atomic.add.i32 %0, %0, %0
     return
 
 .func sin_test 0
index a88779ef4c8e112ed54e9e97518da309976c8b1d..349576f6af11cbbb2cd979b25b5da1a33d1cb44d 100644 (file)
Binary files a/tests/wasm/out.wasm and b/tests/wasm/out.wasm differ
index b16a1147b6a9298bca970a0f45cf1c455254ffb2..7762ca70a14f66557e06671f436377435c56e74d 100644 (file)
@@ -15,11 +15,11 @@ g :: (x) => x + 1;
 
     foo();
 
-    if_test(10);
+    switch_test(10);
     while_test(10);
 }
 
-if_test :: (x: i32) {
+/*if_test :: (x: i32) {
     if !(x > 10) {
         f(10, 20);
     } elseif x > 5 {
@@ -27,6 +27,22 @@ if_test :: (x: i32) {
     } else {
         y := x * 2;
     }
+}*/
+
+switch_test :: (x: i32) {
+    switch x {
+        case 10 {
+            y := 0;
+        }
+        
+        case 20 {
+            z := x * 2;
+        }
+
+        case #default {
+            w := x + 2;
+        }
+    }
 }
 
 while_test :: (x: i32) {