missing instructions, but compilation is almost successful!
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 24 Jun 2022 15:53:54 +0000 (10:53 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 24 Jun 2022 15:53:54 +0000 (10:53 -0500)
include/vm.h
include/vm_codebuilder.h
src/vm/code_builder.c
src/vm/vm.c
src/wasm/module_parsing.c.incl
src/wasm_cli_test.c

index 0321395be9901481e9cbaa1f14029e5e0d5a4ea6..f777423ee04f5031c697002df67b4fb730a49b29 100644 (file)
@@ -240,15 +240,17 @@ struct ovm_instr_t {
 #define OVMI_SUB               0x02   // %r = %a - %b
 #define OVMI_MUL               0x03   // %r = %a * %b
 #define OVMI_DIV               0x04   // %r = %a / %b
-#define OVMI_REM               0x05   // %r = %a % %b
-
-#define OVMI_AND               0x06   // %r = %a & %b
-#define OVMI_OR                0x07   // %r = %a | %b
-#define OVMI_XOR               0x08   // %r = %a ^ %b
-#define OVMI_NOT               0x09   // %r = ~%a
-#define OVMI_SHL               0x0A   // %r = %a << %b
-#define OVMI_SHR               0x0B   // %r = %a >> %b
-#define OVMI_SAR               0x0C   // %r = %a >>> %b
+#define OVMI_DIV_S             0x05   // %r = %a / %b
+#define OVMI_REM               0x06   // %r = %a % %b
+#define OVMI_REM_S             0x07   // %r = %a % %b
+
+#define OVMI_AND               0x08   // %r = %a & %b
+#define OVMI_OR                0x09   // %r = %a | %b
+#define OVMI_XOR               0x0A   // %r = %a ^ %b
+#define OVMI_NOT               0x0B   // %r = ~%a           // This one might not be needed, as WASM doesn't provide it
+#define OVMI_SHL               0x0C   // %r = %a << %b
+#define OVMI_SHR               0x0D   // %r = %a >> %b
+#define OVMI_SAR               0x0E   // %r = %a >>> %b
 
 #define OVMI_IMM               0x10   // %r = i/l/f/d
 #define OVMI_MOV               0x10   // %r = %a
@@ -286,18 +288,40 @@ struct ovm_instr_t {
 #define OVMI_CLZ               0x50   // %r = clz(%a)
 #define OVMI_CTZ               0x51   // %r = ctr(%a)
 #define OVMI_POPCNT            0x52   // %r = popcnt(%a)
+#define OVMI_ROTL              0x53   // %r = rotl(%a, %b)
+#define OVMI_ROTR              0x54   // %r = rotr(%a, %b)
+
+// These instructions are only implemented for floats.
+#define OVMI_ABS               0x55   // %r = |%a|
+#define OVMI_NEG               0x56   // %r = -%a
+#define OVMI_CEIL              0x57   // %r = ceil(%a)
+#define OVMI_FLOOR             0x58   // %r = floor(%a)
+#define OVMI_TRUNC             0x59   // %r = trunc(%a)
+#define OVMI_NEAREST           0x5A   // %r = nearest(%a)
+#define OVMI_SQRT              0x5B   // %r = sqrt(%a)
+#define OVMI_MIN               0x5C   // %r = min(%a, %b)
+#define OVMI_MAX               0x5D   // %r = max(%a, %b)
+#define OVMI_COPYSIGN          0x5E   // %r = copysign(%a, %b)
 
 // For conversion operations, the "type" of the instruction is
 // destination type, the type in the name is the source type.
+//
+// There are a couple of cast operations that are not available,
+// such as unsigned conversion from 32-bit integers to floats.
 #define OVMI_CVT_I8            0x60   // %r = (t) %a
-#define OVMI_CVT_I16           0x61   // %r = (t) %a
-#define OVMI_CVT_I32           0x62   // %r = (t) %a
-#define OVMI_CVT_I64           0x63   // %r = (t) %a
-#define OVMI_CVT_F32           0x64   // %r = (t) %a
-#define OVMI_CVT_F64           0x65   // %r = (t) %a
-#define OVMI_EXTEND_I8         0x66   // %r = (t) %a (sign extension for integers)
-#define OVMI_EXTEND_I16        0x67   // %r = (t) %a (sign extension for integers)
-#define OVMI_EXTEND_I32        0x68   // %r = (t) %a (sign extension for integers)
+#define OVMI_CVT_I8_S          0x61   // %r = (t) %a (sign aware)
+#define OVMI_CVT_I16           0x62   // %r = (t) %a
+#define OVMI_CVT_I16_S         0x63   // %r = (t) %a (sign aware)
+#define OVMI_CVT_I32           0x64   // %r = (t) %a
+#define OVMI_CVT_I32_S         0x65   // %r = (t) %a (sign aware)
+#define OVMI_CVT_I64           0x66   // %r = (t) %a
+#define OVMI_CVT_I64_S         0x67   // %r = (t) %a (sign aware)
+#define OVMI_CVT_F32           0x68   // %r = (t) %a
+#define OVMI_CVT_F64           0x69   // %r = (t) %a
+#define OVMI_TRANSMUTE_I32     0x6A   // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_I64     0x6B   // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F32     0x6C   // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F64     0x6D   // %r = *(t *) &%a (reinterpret bytes)
 
 //
 // OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32) == instruction for adding i32s
index 93d18796f38da70c44bf5a78f98e39ee1ce1f59b..c3e52f90dc661416b7aa05993b3410fcf8ed1af5 100644 (file)
@@ -44,17 +44,19 @@ struct branch_patch_t {
 ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count, i32 local_count);
 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 instr_delta);
 void               ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 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 param_count);
-void               ovm_code_builder_add_indirect_call(ovm_code_builder_t *builder, i32 param_count);
+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);
 void               ovm_code_builder_drop_value(ovm_code_builder_t *builder);
 void               ovm_code_builder_add_local_get(ovm_code_builder_t *builder, i32 local_idx);
 void               ovm_code_builder_add_local_set(ovm_code_builder_t *builder, i32 local_idx);
 void               ovm_code_builder_add_register_get(ovm_code_builder_t *builder, i32 local_idx);
 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);
 
 #endif
index f1f102b6d692946caffa4ad1d605eea8ffd56048..467a35e2421b539eaaf77c653fa237a55f8cff73 100644 (file)
@@ -19,6 +19,7 @@ ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count,
 
     builder.next_label_idx = 0;
     builder.label_stack = NULL;
+    builder.branch_patches = NULL;
     bh_arr_new(bh_heap_allocator(), builder.label_stack, 32);
     bh_arr_new(bh_heap_allocator(), builder.branch_patches, 32);
 
@@ -47,7 +48,7 @@ void ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr) {
 }
 
 void ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *imm) {
-    ovm_instr_t imm_instr;
+    ovm_instr_t imm_instr = {0};
     imm_instr.full_instr = OVM_TYPED_INSTR(OVMI_IMM, ovm_type);
     imm_instr.r = NEXT_VALUE(builder);
 
@@ -65,3 +66,204 @@ void ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *i
     PUSH_VALUE(builder, imm_instr.r);
 }
 
+void ovm_code_builder_add_unop(ovm_code_builder_t *builder, u32 instr) {
+    i32 operand = POP_VALUE(builder);
+
+    ovm_instr_t unop = {0};
+    unop.full_instr = instr;
+    unop.r = NEXT_VALUE(builder);
+    unop.a = operand;
+
+    ovm_program_add_instructions(builder->program, 1, &unop);
+    PUSH_VALUE(builder, unop.r);
+}
+
+void ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 instr_delta) {
+
+}
+
+void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx) {
+
+}
+
+void ovm_code_builder_add_return(ovm_code_builder_t *builder) {
+    ovm_instr_t instr = {0};
+    instr.full_instr = OVMI_RETURN;
+
+    i32 values_on_stack = bh_arr_length(builder->execution_stack);
+    assert(values_on_stack == 0 || values_on_stack == 1);
+
+    if (values_on_stack == 1) {
+        instr.a = POP_VALUE(builder);
+    }
+
+    ovm_program_add_instructions(builder->program, 1, &instr);
+}
+
+static void ovm_code_builder_add_params(ovm_code_builder_t *builder, i32 param_count) {
+    fori (i, 0, param_count) {
+        ovm_instr_t param_instr = {0};
+        param_instr.full_instr = OVMI_PARAM;
+        param_instr.a = POP_VALUE(builder);
+
+        ovm_program_add_instructions(builder->program, 1, &param_instr);
+    }
+}
+
+void ovm_code_builder_add_call(ovm_code_builder_t *builder, i32 func_idx, i32 param_count, bool has_return_value) {
+    ovm_code_builder_add_params(builder, param_count);
+
+    ovm_instr_t call_instr = {0};
+    call_instr.full_instr = OVMI_CALL;
+    call_instr.a = func_idx;
+    call_instr.r = -1;
+
+    if (has_return_value) {
+        call_instr.r = NEXT_VALUE(builder);
+    }
+
+    ovm_program_add_instructions(builder->program, 1, &call_instr);
+
+    if (has_return_value) {
+        PUSH_VALUE(builder, call_instr.r);
+    }
+}
+
+void ovm_code_builder_add_indirect_call(ovm_code_builder_t *builder, i32 param_count, bool has_return_value) {
+    ovm_instr_t call_instr = {0};
+    call_instr.full_instr = OVMI_CALLI;
+    call_instr.a = POP_VALUE(builder);
+    call_instr.r = -1;
+
+    ovm_code_builder_add_params(builder, param_count);
+
+    if (has_return_value) {
+        call_instr.r = NEXT_VALUE(builder);
+    }
+
+    ovm_program_add_instructions(builder->program, 1, &call_instr);
+
+    if (has_return_value) {
+        PUSH_VALUE(builder, call_instr.r);
+    }
+}
+
+void ovm_code_builder_drop_value(ovm_code_builder_t *builder) {
+    POP_VALUE(builder);
+}
+
+void ovm_code_builder_add_local_get(ovm_code_builder_t *builder, i32 local_idx) {
+    ovm_instr_t instr = {0};
+    instr.full_instr = OVMI_MOV;
+    instr.r = NEXT_VALUE(builder);
+    instr.a = local_idx; // This makes the assumption that the params will be in
+                         // the lower "address space" of the value numbers. This
+                         // will be true for web assembly, because that's how it
+                         // it was spec'd; but in the future for other things,
+                         // this will be incorrect.
+
+    ovm_program_add_instructions(builder->program, 1, &instr);
+
+    PUSH_VALUE(builder, instr.r);
+}
+
+void ovm_code_builder_add_local_set(ovm_code_builder_t *builder, i32 local_idx) {
+    ovm_instr_t instr = {0};
+    instr.full_instr = OVMI_MOV;
+    instr.r = local_idx; // This makes the assumption that the params will be in
+                         // the lower "address space" of the value numbers. This
+                         // will be true for web assembly, because that's how it
+                         // it was spec'd; but in the future for other things,
+                         // this will be incorrect.
+    instr.a = POP_VALUE(builder);
+
+    ovm_program_add_instructions(builder->program, 1, &instr);
+}
+
+void ovm_code_builder_add_register_get(ovm_code_builder_t *builder, i32 reg_idx) {
+    ovm_instr_t instr = {0};
+    instr.full_instr = OVMI_REG_GET;
+    instr.r = NEXT_VALUE(builder);
+    instr.a = reg_idx;
+
+    ovm_program_add_instructions(builder->program, 1, &instr);
+
+    PUSH_VALUE(builder, instr.r);
+}
+
+void ovm_code_builder_add_register_set(ovm_code_builder_t *builder, i32 reg_idx) {
+    ovm_instr_t instr = {0};
+    instr.full_instr = OVMI_REG_SET;
+    instr.r = reg_idx;
+    instr.a = POP_VALUE(builder);
+
+    ovm_program_add_instructions(builder->program, 1, &instr);
+}
+
+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 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);
+
+    // 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);
+
+    // 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);
+}
+
+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};
+    instrs[2].b = 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 = POP_VALUE(builder);
+
+    // 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);
+}
+
index fd7bd5512b38bea99c77ca8b2fc6fe763181553f..00eea16a5e1cc35463b3695121e6316e4d449c59 100644 (file)
@@ -1,6 +1,8 @@
 #include "vm.h"
 
 #include <sys/mman.h>
+#include <x86intrin.h>
+#include <math.h> // REMOVE THIS!!!  only needed for sqrt
 
 //
 // Store
@@ -282,6 +284,49 @@ static char *ovm_instr_name(i32 full_instr) {
         C(OVMI_BRI_Z)
         C(OVMI_BRI_NZ)
 
+        C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I64))
+
+        C(OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F32))
+
+        C(OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F64))
+        C(OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F64))
+
         C(OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I16))
         C(OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I32))
         C(OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I64))
@@ -456,6 +501,48 @@ ovm_value_t ovm_func_call(ovm_engine_t *engine, ovm_state_t *state, ovm_program_
     return bh_arr_pop(state->numbered_values);
 }
 
+static inline double __ovm_abs(double f) {
+    return f >= 0 ? f : -f;
+}
+
+static inline double __ovm_floor(double f) {
+    if (f < 0) {
+        return (double) (((long long) f) - 1);
+    } else {
+        return (double) (long long) f;
+    }
+}
+
+static inline double __ovm_ceil(double f) {
+    if (f - (long long) f == 0) {
+        return (double) (long long) f;
+    } else {
+        return __ovm_floor(f) + 1;
+    }
+}
+
+static inline double __ovm_trunc(double f) {
+    return (double) (long long) f;
+}
+
+static inline double __ovm_nearest(double f) {
+    if (f > 0 && f <= 0.5) {
+        return +0;
+    }
+
+    if (f >= -0.5 && f < 0) {
+        return -0;
+    }
+
+    if (f - __ovm_floor(f) < 0.5) return __ovm_floor(f);
+    else                          return __ovm_ceil(f);
+}
+
+static inline double __ovm_copysign(a, b) double a, b; {
+    if ((a > 0 && b > 0) || (a < 0 && b < 0)) return a;
+    return -a;
+}
+
 
 void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *program) {
     assert(engine);
@@ -544,10 +631,34 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
 
 #undef OVM_OP
 
+#define OVM_OP(i, t, func, ctype) \
+            case OVM_TYPED_INSTR(i, t): \
+                 VAL(instr.r).type = t; \
+                 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_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_MIN, OVM_TYPE_F32, bh_min, f32)
+            OVM_OP(OVMI_MAX, OVM_TYPE_F32, bh_max, f32)
+
+            OVM_OP(OVMI_MIN, OVM_TYPE_F64, bh_min, f64)
+            OVM_OP(OVMI_MAX, OVM_TYPE_F64, bh_max, f64)
+
+#undef OVM_OP
+
 #define OVM_OP(i, t, op, ctype) \
             case OVM_TYPED_INSTR(i, t): \
                  VAL(instr.r).type = t; \
-                 VAL(instr.r).ctype = op VAL(instr.a).ctype; \
+                 VAL(instr.r).ctype = (ctype) op (VAL(instr.a).ctype); \
                  break;
             
             OVM_OP(OVMI_NOT, OVM_TYPE_I8 , ~, i8)
@@ -555,6 +666,37 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             OVM_OP(OVMI_NOT, OVM_TYPE_I32, ~, i32)
             OVM_OP(OVMI_NOT, OVM_TYPE_I64, ~, i64)
 
+            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_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_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_ABS,     OVM_TYPE_F32, __ovm_abs, f32);
+            OVM_OP(OVMI_NEG,     OVM_TYPE_F32, -, f32);
+            OVM_OP(OVMI_CEIL,    OVM_TYPE_F32, __ovm_ceil, f32);
+            OVM_OP(OVMI_FLOOR,   OVM_TYPE_F32, __ovm_floor, f32);
+            OVM_OP(OVMI_TRUNC,   OVM_TYPE_F32, __ovm_trunc, f32);
+            OVM_OP(OVMI_NEAREST, OVM_TYPE_F32, __ovm_nearest, f32);
+            OVM_OP(OVMI_SQRT,    OVM_TYPE_F32, sqrt, f32);  // TODO: REMOVE THE NEED FOR libm!!!
+
+            OVM_OP(OVMI_ABS,     OVM_TYPE_F64, __ovm_abs, f64);
+            OVM_OP(OVMI_NEG,     OVM_TYPE_F64, -, f64);
+            OVM_OP(OVMI_CEIL,    OVM_TYPE_F64, __ovm_ceil, f64);
+            OVM_OP(OVMI_FLOOR,   OVM_TYPE_F64, __ovm_floor, f64);
+            OVM_OP(OVMI_TRUNC,   OVM_TYPE_F64, __ovm_trunc, f64);
+            OVM_OP(OVMI_NEAREST, OVM_TYPE_F64, __ovm_nearest, f64);
+            OVM_OP(OVMI_SQRT,    OVM_TYPE_F64, sqrt, f64);  // TODO: REMOVE THE NEED FOR libm!!!
+
 #undef OVM_OP
 
 #define OVM_OP(i, t, op, ctype, cast_type) \
@@ -786,25 +928,43 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
     VAL(instr.r).dtype = (ctype) VAL(instr.a).stype; \
     break
 
-            case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I16): CVT(i8, i16, OVM_TYPE_I16, u16);
-            case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I32): CVT(i8, i32, OVM_TYPE_I32, u32);
-            case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I64): CVT(i8, i64, OVM_TYPE_I64, u64);
-
-            case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I8):  CVT(i16, i8,  OVM_TYPE_I8, u8);
-            case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I32): CVT(i16, i32, OVM_TYPE_I32, u32);
-            case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I64): CVT(i16, i64, OVM_TYPE_I64, u64);
-
-            case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I8):  CVT(i32, i8,  OVM_TYPE_I8, u8);
-            case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I16): CVT(i32, i16, OVM_TYPE_I16, u16);
-            case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I64): CVT(i32, i64, OVM_TYPE_I64, u64);
-            case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F32): CVT(i32, f32, OVM_TYPE_F32, f32);
-            case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F64): CVT(i32, f64, OVM_TYPE_F64, f64);
-
-            case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I8):  CVT(i64, i8,  OVM_TYPE_I8, u8); 
-            case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I16): CVT(i64, i16, OVM_TYPE_I16, u16);
-            case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I32): CVT(i64, i32, OVM_TYPE_I32, u32);
-            case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F32): CVT(i64, f32, OVM_TYPE_F32, f32);
-            case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F64): CVT(i64, f64, OVM_TYPE_F64, f64);
+            case OVM_TYPED_INSTR(OVMI_CVT_I8,   OVM_TYPE_I16): CVT(u8, u16, OVM_TYPE_I16, u16);
+            case OVM_TYPED_INSTR(OVMI_CVT_I8,   OVM_TYPE_I32): CVT(u8, u32, OVM_TYPE_I32, u32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I8,   OVM_TYPE_I64): CVT(u8, u64, OVM_TYPE_I64, u64);
+            case OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I16): CVT(i8, i16, OVM_TYPE_I16, i16);
+            case OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I32): CVT(i8, i32, OVM_TYPE_I32, i32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I64): CVT(i8, i64, OVM_TYPE_I64, i64);
+
+            case OVM_TYPED_INSTR(OVMI_CVT_I16,   OVM_TYPE_I8):  CVT(u16, u8,  OVM_TYPE_I8, u8);
+            case OVM_TYPED_INSTR(OVMI_CVT_I16,   OVM_TYPE_I32): CVT(u16, u32, OVM_TYPE_I32, u32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I16,   OVM_TYPE_I64): CVT(u16, u64, OVM_TYPE_I64, u64);
+            case OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I8):  CVT(i16, i8,  OVM_TYPE_I8, i8);
+            case OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I32): CVT(i16, i32, OVM_TYPE_I32, i32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I64): CVT(i16, i64, OVM_TYPE_I64, i64);
+
+            case OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_I8):  CVT(u32, u8,  OVM_TYPE_I8,  u8);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_I16): CVT(u32, u16, OVM_TYPE_I16, u16);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_I64): CVT(u32, u64, OVM_TYPE_I64, u64);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I8):  CVT(i32, i8,  OVM_TYPE_I8,  i8);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I16): CVT(i32, i16, OVM_TYPE_I16, i16);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64): CVT(i32, i64, OVM_TYPE_I64, i64);
+
+            case OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_F32): CVT(u32, f32, OVM_TYPE_F32, f32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F32): CVT(i32, f32, OVM_TYPE_F32, f32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_F64): CVT(u32, f64, OVM_TYPE_F64, f64);
+            case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F64): CVT(i32, f64, OVM_TYPE_F64, f64);
+
+            case OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_I8):  CVT(u64, u8,  OVM_TYPE_I8,  u8);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_I16): CVT(u64, u16, OVM_TYPE_I16, u16);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_I32): CVT(u64, u32, OVM_TYPE_I32, u32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_I8):  CVT(i64, i8,  OVM_TYPE_I8,  i8);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_I16): CVT(i64, i16, OVM_TYPE_I16, i16);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_I32): CVT(i64, i32, OVM_TYPE_I32, i32);
+            
+            case OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_F32): CVT(u64, f32, OVM_TYPE_F32, f32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F32): CVT(i64, f32, OVM_TYPE_F32, f32);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_F64): CVT(u64, f64, OVM_TYPE_F64, f64);
+            case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F64): CVT(i64, f64, OVM_TYPE_F64, f64);
 
             case OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32): CVT(f32, i32, OVM_TYPE_I32, u32);
             case OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64): CVT(f32, f32, OVM_TYPE_I64, u64);
@@ -815,6 +975,19 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32): CVT(f64, f32, OVM_TYPE_F32, f32);
 
 #undef CVT
+
+#define CVT(stype, dtype, otype, ctype) \
+    VAL(instr.r).type = otype; \
+    VAL(instr.r).dtype = *(ctype *) &VAL(instr.a).stype; \
+    break
+
+            case OVM_TYPED_INSTR(OVMI_TRANSMUTE_I32, OVM_TYPE_F32): CVT(u32, f32, OVM_TYPE_F32, f32);
+            case OVM_TYPED_INSTR(OVMI_TRANSMUTE_I64, OVM_TYPE_F64): CVT(u64, f64, OVM_TYPE_F64, f64);
+            case OVM_TYPED_INSTR(OVMI_TRANSMUTE_F32, OVM_TYPE_I32): CVT(f32, u32, OVM_TYPE_I32, u32);
+            case OVM_TYPED_INSTR(OVMI_TRANSMUTE_F64, OVM_TYPE_I64): CVT(f64, u64, OVM_TYPE_I64, u64);
+
+#undef CVT
+
             default:
                 printf("ERROR:\n");
                 ovm_program_print_instructions(program, state->pc - 1, 1);
index e885d5bdf27737321200df2f44629fad1e291a60..1447abbb9c5cc309bed9cf3167e2b8be216c4bab 100644 (file)
@@ -370,7 +370,7 @@ static void pop_label_target(build_context *ctx) {
 static void parse_expression(build_context *ctx);
 
 static void parse_instruction(build_context *ctx) {
-    char instr_byte;
+    unsigned char instr_byte;
     switch (instr_byte = CONSUME_BYTE(ctx)) {
         case 0x00: break;
         case 0x01: break;
@@ -431,7 +431,10 @@ static void parse_instruction(build_context *ctx) {
         case 0x10: {
             int func_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
             int param_count = ctx->program->funcs[func_idx].param_count;
-            ovm_code_builder_add_call(&ctx->builder, param_count);
+
+            wasm_functype_t *functype = ctx->module->functypes.data[func_idx];
+
+            ovm_code_builder_add_call(&ctx->builder, func_idx, param_count, functype->type.func.results.size != 0);
             break;
         }
 
@@ -440,8 +443,10 @@ static void parse_instruction(build_context *ctx) {
             int table_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
             assert(table_idx == 0);
 
-            int param_count = ctx->module->type_section.data[type_idx]->type.func.params.size;
-            ovm_code_builder_add_indirect_call(&ctx->builder, param_count);
+            wasm_functype_t *functype = ctx->module->type_section.data[type_idx];
+            int param_count = functype->type.func.params.size;
+            printf("indirect call with %d params.\n", param_count);
+            ovm_code_builder_add_indirect_call(&ctx->builder, param_count, functype->type.func.results.size != 0);
             break;
         }
 
@@ -513,6 +518,34 @@ static void parse_instruction(build_context *ctx) {
 
         // ... More loading and storing instruction here ...
 
+        case 0x36: {
+            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, OVM_TYPE_I32, offset);
+            break;
+        }
+
+        case 0x37: {
+            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, OVM_TYPE_I64, offset);
+            break;
+        }
+
+        case 0x38: {
+            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, OVM_TYPE_F32, offset);
+            break;
+        }
+
+        case 0x39: {
+            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, OVM_TYPE_F64, offset);
+            break;
+        }
+
         case 0x41: {
             int value = uleb128_to_uint(ctx->binary.data, &ctx->offset);
             ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &value);
@@ -575,6 +608,104 @@ static void parse_instruction(build_context *ctx) {
         case 0x65: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE, OVM_TYPE_F64)); break;
         case 0x66: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE, OVM_TYPE_F64)); break;
 
+        case 0x67: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I32)); break;
+        case 0x68: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I32)); break;
+        case 0x69: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I32)); break;
+        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 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;
+        case 0x74: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHL, OVM_TYPE_I32)); break;
+        case 0x75: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SAR, OVM_TYPE_I32)); break;
+        case 0x76: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHR, OVM_TYPE_I32)); break;
+        case 0x77: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I32)); break;
+        case 0x78: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I32)); break;
+
+        case 0x79: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I64)); break;
+        case 0x7A: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I64)); break;
+        case 0x7B: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I64)); break;
+        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 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;
+        case 0x86: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHL, OVM_TYPE_I64)); break;
+        case 0x87: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SAR, OVM_TYPE_I64)); break;
+        case 0x88: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHR, OVM_TYPE_I64)); break;
+        case 0x89: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I64)); break;
+        case 0x8A: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I64)); break;
+
+        case 0x8B: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F32)); break;
+        case 0x8C: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F32)); break;
+        case 0x8D: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F32)); break;
+        case 0x8E: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F32)); break;
+        case 0x8F: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F32)); break;
+        case 0x90: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F32)); break;
+        case 0x91: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F32)); break;
+        case 0x92: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_F32)); break;
+        case 0x93: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_F32)); break;
+        case 0x94: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_F32)); break;
+        case 0x95: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_F32)); break;
+        case 0x96: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F32)); break;
+        case 0x97: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F32)); break;
+        case 0x98: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F32)); break;
+
+        case 0x99: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F64)); break;
+        case 0x9A: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F64)); break;
+        case 0x9B: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F64)); break;
+        case 0x9C: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F64)); break;
+        case 0x9D: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F64)); break;
+        case 0x9E: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F64)); break;
+        case 0x9F: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F64)); break;
+        case 0xA0: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_F64)); break;
+        case 0xA1: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_F64)); break;
+        case 0xA2: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_F64)); break;
+        case 0xA3: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_F64)); break;
+        case 0xA4: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F64)); break;
+        case 0xA5: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F64)); break;
+        case 0xA6: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F64)); break;
+
+        case 0xA7: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_I32)); break;
+        case 0xA8: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32,   OVM_TYPE_I32)); break;
+        case 0xA9: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32,   OVM_TYPE_I32)); break;
+        case 0xAA: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64,   OVM_TYPE_I32)); break;
+        case 0xAB: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64,   OVM_TYPE_I32)); break;
+        case 0xAC: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64)); break;
+        case 0xAD: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_I64)); break;
+        case 0xAE: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32,   OVM_TYPE_I64)); break;
+        case 0xAF: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32,   OVM_TYPE_I64)); break;
+        case 0xB0: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64,   OVM_TYPE_I64)); break;
+        case 0xB1: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64,   OVM_TYPE_I64)); break;
+        case 0xB2: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F32)); break;
+        case 0xB3: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_F32)); break;
+        case 0xB4: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F32)); break;
+        case 0xB5: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_F32)); break;
+        case 0xB6: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64,   OVM_TYPE_F32)); break;
+        case 0xB7: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F64)); break;
+        case 0xB8: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32,   OVM_TYPE_F64)); break;
+        case 0xB9: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F64)); break;
+        case 0xBA: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64,   OVM_TYPE_F64)); break;
+        case 0xBB: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32,   OVM_TYPE_F64)); break;
+        case 0xBC: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_F32, OVM_TYPE_I32)); break;
+        case 0xBD: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_F64, OVM_TYPE_I64)); break;
+        case 0xBE: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_I32, OVM_TYPE_F32)); break;
+        case 0xBF: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_I64, OVM_TYPE_F64)); break;
+        case 0xC0: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I32)); break;
+        case 0xC1: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I32)); break;
+        case 0xC2: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I64)); break;
+        case 0xC3: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I64)); break;
+        case 0xC4: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64)); break;
 
         default: assert(("UNHANDLED INSTRUCTION", 0));
     }
@@ -606,7 +737,11 @@ static void parse_code_section(build_context *ctx) {
         
         // Set up a lot of stuff...
         ctx->builder = ovm_code_builder_new(ctx->program, 0, total_locals);
+        push_label_target(ctx, label_kind_func);
+
         parse_expression(ctx);
+
+        ovm_code_builder_add_return(&ctx->builder);
         ovm_code_builder_free(&ctx->builder);
     }
 }
index 029d362ddc2e7e870e20ab983fa14d608fcf00a1..91af7a0cfd374a3e571c9691cc5236976522d60e 100644 (file)
@@ -1,5 +1,7 @@
 #include "bh.h"
 #include "wasm.h"
+#include "onyx_wasm.h"
+#include "vm.h"
 
 
 int main(int argc, char *argv[]) {
@@ -41,5 +43,7 @@ int main(int argc, char *argv[]) {
         const wasm_name_t *export_name = wasm_exporttype_name(exports.data[i]);
         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, 100);
 }