From 4975ee6022dba75ad50a9f3f4046d7fc13c74bd7 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 24 Jun 2022 10:53:54 -0500 Subject: [PATCH] missing instructions, but compilation is almost successful! --- include/vm.h | 58 ++++++--- include/vm_codebuilder.h | 6 +- src/vm/code_builder.c | 204 ++++++++++++++++++++++++++++++- src/vm/vm.c | 213 +++++++++++++++++++++++++++++---- src/wasm/module_parsing.c.incl | 143 +++++++++++++++++++++- src/wasm_cli_test.c | 4 + 6 files changed, 584 insertions(+), 44 deletions(-) diff --git a/include/vm.h b/include/vm.h index 0321395..f777423 100644 --- a/include/vm.h +++ b/include/vm.h @@ -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 diff --git a/include/vm_codebuilder.h b/include/vm_codebuilder.h index 93d1879..c3e52f9 100644 --- a/include/vm_codebuilder.h +++ b/include/vm_codebuilder.h @@ -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 diff --git a/src/vm/code_builder.c b/src/vm/code_builder.c index f1f102b..467a35e 100644 --- a/src/vm/code_builder.c +++ b/src/vm/code_builder.c @@ -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, ¶m_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); +} + diff --git a/src/vm/vm.c b/src/vm/vm.c index fd7bd55..00eea16 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -1,6 +1,8 @@ #include "vm.h" #include +#include +#include // 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); diff --git a/src/wasm/module_parsing.c.incl b/src/wasm/module_parsing.c.incl index e885d5b..1447abb 100644 --- a/src/wasm/module_parsing.c.incl +++ b/src/wasm/module_parsing.c.incl @@ -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); } } diff --git a/src/wasm_cli_test.c b/src/wasm_cli_test.c index 029d362..91af7a0 100644 --- a/src/wasm_cli_test.c +++ b/src/wasm_cli_test.c @@ -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); } -- 2.25.1