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