From 1b231e0a7db9ef24a8ab99a59a0aca358dfc67d4 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 1 Jul 2022 13:18:18 -0500 Subject: [PATCH] most test cases work!! --- build.sh | 2 +- include/vm_codebuilder.h | 1 + src/vm/code_builder.c | 16 ++++-- src/vm/vm.c | 89 ++++++++++++++++++++-------------- src/wasm/module.c | 1 + src/wasm/module_parsing.c.incl | 39 ++++++++------- 6 files changed, 90 insertions(+), 58 deletions(-) diff --git a/build.sh b/build.sh index 160e456..e4095d8 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ CC="gcc" WARNINGS='-Wimplicit -Wmisleading-indentation -Wparentheses -Wsequence-point -Wreturn-type -Wshift-negative-value -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-function -Wunused-label -Wmaybe-uninitialized -Wsign-compare -Wstrict-overflow -Wduplicated-branches -Wduplicated-cond -Wtrigraphs -Waddress -Wlogical-op' -FLAGS="-g3" +FLAGS="-O3" LIBS="-pthread" INCLUDES="-I include" TARGET="libonyx_embedder.so" diff --git a/include/vm_codebuilder.h b/include/vm_codebuilder.h index 9ea5817..5261fad 100644 --- a/include/vm_codebuilder.h +++ b/include/vm_codebuilder.h @@ -58,6 +58,7 @@ label_target_t ovm_code_builder_wasm_target_idx(ovm_code_builder_t *builder, 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_nop(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); diff --git a/src/vm/code_builder.c b/src/vm/code_builder.c index 07cb159..bcca172 100644 --- a/src/vm/code_builder.c +++ b/src/vm/code_builder.c @@ -1,7 +1,7 @@ #include "vm_codebuilder.h" -#define BUILDER_DEBUG +// #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)) @@ -80,6 +80,10 @@ void ovm_code_builder_pop_label_target(ovm_code_builder_t *builder) { target.instr = bh_arr_length(builder->program->code); } + // if (target.kind == label_kind_if) { + // target.instr += 1; + // } + fori (i, 0, bh_arr_length(builder->branch_patches)) { branch_patch_t patch = builder->branch_patches[i]; if (patch.label_idx != target.idx) continue; @@ -101,6 +105,13 @@ void ovm_code_builder_pop_label_target(ovm_code_builder_t *builder) { } } +void ovm_code_builder_add_nop(ovm_code_builder_t *builder) { + ovm_instr_t nop = {0}; + nop.full_instr = OVMI_NOP; + + ovm_program_add_instructions(builder->program, 1, &nop); +} + void ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr) { i32 right = POP_VALUE(builder); i32 left = POP_VALUE(builder); @@ -187,9 +198,8 @@ void ovm_code_builder_add_branch_table(ovm_code_builder_t *builder, i32 count, i // // Passing label indicies here is a little disingenuous, because that is not // what the data will have to be. But since it is already the correct length - // I am using it as a subsitute. + // I am using it as a substitute. int table_idx = ovm_program_register_static_ints(builder->program, count, label_indicies); - assert(table_idx > 0); ovm_instr_t instrs[5] = {0}; int tmp_register = NEXT_VALUE(builder); diff --git a/src/vm/vm.c b/src/vm/vm.c index b9c6f4b..0d1cbfd 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -624,9 +624,13 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr ovm_instr_t *code = program->code; bool release_mutex_at_end = false; + + ovm_value_t tmp_val; while (state->pc < bh_arr_length(program->code)) { - ovm_program_print_instructions(program, state->pc, 1); + // ovm_program_print_instructions(program, state->pc, 1); + tmp_val.type = OVM_TYPE_NONE; + tmp_val.u64 = 0; // // Incrementing the program counter here. @@ -648,9 +652,11 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #define OVM_OP(i, t, op, ctype) \ case OVM_TYPED_INSTR(i, t): \ - VAL(instr.r).type = t; \ - VAL(instr.r).ctype = VAL(instr.a).ctype op VAL(instr.b).ctype; \ - break; + assert(VAL(instr.a).type == t && VAL(instr.b).type == t); \ + tmp_val.type = t; \ + tmp_val.ctype = VAL(instr.a).ctype op VAL(instr.b).ctype; \ + VAL(instr.r) = tmp_val; \ + break; OVM_OP(OVMI_ADD, OVM_TYPE_I8 , +, i8) OVM_OP(OVMI_ADD, OVM_TYPE_I16, +, i16) @@ -731,9 +737,11 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #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; + assert(VAL(instr.a).type == t && VAL(instr.b).type == t); \ + tmp_val.type = t; \ + tmp_val.ctype = func( VAL(instr.a).ctype, VAL(instr.b).ctype ); \ + VAL(instr.r) = tmp_val; \ + break; OVM_OP(OVMI_ROTL, OVM_TYPE_I8 , __rolb, u8) OVM_OP(OVMI_ROTL, OVM_TYPE_I16, __rolw, u16) @@ -755,9 +763,11 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #define OVM_OP(i, t, op, ctype) \ case OVM_TYPED_INSTR(i, t): \ - VAL(instr.r).type = t; \ - VAL(instr.r).ctype = (ctype) op (VAL(instr.a).ctype); \ - break; + assert(VAL(instr.a).type == t); \ + tmp_val.type = t; \ + tmp_val.ctype = (ctype) op (VAL(instr.a).ctype); \ + VAL(instr.r) = tmp_val; \ + break; OVM_OP(OVMI_CLZ, OVM_TYPE_I8 , __builtin_clz, u8) OVM_OP(OVMI_CLZ, OVM_TYPE_I16, __builtin_clz, u16) @@ -794,9 +804,11 @@ 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) (VAL(instr.a).ctype op VAL(instr.b).ctype); \ - break; + assert(VAL(instr.a).type == t && VAL(instr.b).type == t); \ + tmp_val.type = OVM_TYPE_I32; \ + tmp_val.i32 = ((VAL(instr.a).ctype op VAL(instr.b).ctype)) ? 1 : 0; \ + VAL(instr.r) = tmp_val; \ + break; OVM_OP(OVMI_LT, OVM_TYPE_I8 , <, u8, u8) OVM_OP(OVMI_LT, OVM_TYPE_I16, <, u16, u16) @@ -873,6 +885,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #define OVM_IMM(t, dtype, stype) \ case OVM_TYPED_INSTR(OVMI_IMM, t): \ VAL(instr.r).type = t; \ + VAL(instr.r).u64 = 0; \ VAL(instr.r).dtype = instr.stype; \ break; @@ -892,8 +905,9 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #define OVM_LOAD(type_, stype) \ 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)[VAL(instr.a).u32 + instr.b]; \ + tmp_val.type = type_; \ + tmp_val.stype = * (stype *) &((u8 *) engine->memory)[VAL(instr.a).u32 + (u32) instr.b]; \ + VAL(instr.r) = tmp_val; \ break; \ } @@ -909,7 +923,7 @@ 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.r).type == OVM_TYPE_I32); \ - * (stype *) &((u8 *) engine->memory)[VAL(instr.r).u32 + instr.b] = VAL(instr.a).stype; \ + memcpy(&((u8 *) engine->memory)[VAL(instr.r).u32 + (u32) instr.b], &VAL(instr.a).stype, sizeof(stype)); \ break; OVM_STORE(OVM_TYPE_I8, i8) @@ -922,9 +936,9 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #undef OVM_STORE case OVMI_COPY: { - i32 dest = VAL(instr.r).i32; - i32 src = VAL(instr.a).i32; - i32 count = VAL(instr.b).i32; + u32 dest = VAL(instr.r).u32; + u32 src = VAL(instr.a).u32; + u32 count = VAL(instr.b).u32; u8 *base = engine->memory; memmove(&base[dest], &base[src], count); @@ -933,7 +947,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr case OVMI_FILL: { i32 dest = VAL(instr.r).i32; - i8 byte = VAL(instr.a).i8; + u8 byte = VAL(instr.a).u8; i32 count = VAL(instr.b).i32; u8 *base = engine->memory; @@ -952,8 +966,9 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr } case OVMI_IDX_ARR: { - VAL(instr.r).type = OVM_TYPE_I32; - VAL(instr.r).i32 = program->static_integers[program->static_data[instr.a].start_idx + VAL(instr.b).i32]; + tmp_val.type = OVM_TYPE_I32; + tmp_val.i32 = program->static_integers[program->static_data[instr.a].start_idx + VAL(instr.b).u32]; + VAL(instr.r) = tmp_val; break; } @@ -978,9 +993,9 @@ 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"); + // 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; @@ -992,11 +1007,11 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr if (func->kind == OVM_FUNC_INTERNAL) { \ ovm__func_setup_stack_frame(engine, state, program, fidx, instr.r); \ \ - assert(func->param_count == bh_arr_length(state->params)); \ + i32 extra_params = bh_arr_length(state->params) - func->param_count; \ fori (i, 0, func->param_count) { \ - VAL(i) = state->params[i]; \ + VAL(i) = state->params[i + extra_params]; \ } \ - bh_arr_set_length(state->params, 0); \ + bh_arr_fastdeleten(state->params, func->param_count); \ \ state->pc = func->start_instr; \ } else { \ @@ -1030,8 +1045,9 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #define CVT(stype, dtype, otype, ctype) \ - VAL(instr.r).type = otype; \ - VAL(instr.r).dtype = (ctype) VAL(instr.a).stype; \ + tmp_val.type = otype; \ + tmp_val.dtype = (ctype) VAL(instr.a).stype; \ + VAL(instr.r) = tmp_val; \ break case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I16): CVT(u8, u16, OVM_TYPE_I16, u16); @@ -1072,8 +1088,8 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr 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); + case OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32): CVT(f32, u32, OVM_TYPE_I32, u32); + case OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64): CVT(f32, u64, OVM_TYPE_I64, u64); case OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_F64): CVT(f32, f64, OVM_TYPE_F64, f64); case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32): CVT(f64, i32, OVM_TYPE_I32, u32); @@ -1083,8 +1099,9 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr #undef CVT #define CVT(stype, dtype, otype, ctype) \ - VAL(instr.r).type = otype; \ - VAL(instr.r).dtype = *(ctype *) &VAL(instr.a).stype; \ + tmp_val.type = otype; \ + tmp_val.dtype = *(ctype *) &VAL(instr.a).stype; \ + VAL(instr.r) = tmp_val; \ break case OVM_TYPED_INSTR(OVMI_TRANSMUTE_I32, OVM_TYPE_F32): CVT(u32, f32, OVM_TYPE_F32, f32); @@ -1097,9 +1114,9 @@ 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]; \ + ctype *addr = (ctype *) &((u8 *) engine->memory)[VAL(instr.r).u32]; \ \ - VAL(instr.r).i32 = 0; \ + VAL(instr.r).u64 = 0; \ VAL(instr.r).type = otype; \ VAL(instr.r).ctype = *addr; \ \ diff --git a/src/wasm/module.c b/src/wasm/module.c index 70c4848..07feb45 100644 --- a/src/wasm/module.c +++ b/src/wasm/module.c @@ -62,6 +62,7 @@ WASM_MODULE_INDEX(global, WASM_EXTERN_GLOBAL) wasm_module_t *wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) { wasm_module_t *module = bh_alloc(store->engine->store->arena_allocator, sizeof(*module)); + memset(module, 0, sizeof(*module)); module->store = store; bool success = module_build(module, binary); diff --git a/src/wasm/module_parsing.c.incl b/src/wasm/module_parsing.c.incl index 134bc20..5ed0321 100644 --- a/src/wasm/module_parsing.c.incl +++ b/src/wasm/module_parsing.c.incl @@ -271,8 +271,11 @@ static void parse_export_section(build_context *ctx) { case 0x01: export_type = wasm_tabletype_as_externtype(wasm_module_index_tabletype(ctx->module, idx)); break; case 0x02: export_type = wasm_memorytype_as_externtype(wasm_module_index_memorytype(ctx->module, idx)); break; case 0x03: export_type = wasm_globaltype_as_externtype(wasm_module_index_globaltype(ctx->module, idx)); break; + default: assert(0); } + assert(export_type); + wasm_exporttype_t *export = wasm_exporttype_new(&export_name, export_type); export->index = idx; ctx->module->exports.data[i] = export; @@ -508,9 +511,9 @@ static void parse_instruction(build_context *ctx) { // Therefore, this "peeks" at what the next label index will be, so it can // know what label to track for where to jump. It feels like there should be // a better way to do this. + ovm_code_builder_add_branch(&ctx->builder, ctx->builder.next_label_idx); ovm_code_builder_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); + ovm_code_builder_push_label_target(&ctx->builder, label_kind_block); break; } @@ -619,29 +622,30 @@ static void parse_instruction(build_context *ctx) { break; } -#define LOAD_CASE(num, type) \ +#define LOAD_CASE(num, type, convert, convert_op, convert_type) \ case num : { \ int alignment = uleb128_to_uint(ctx->binary.data, &ctx->offset); \ int offset = uleb128_to_uint(ctx->binary.data, &ctx->offset); \ ovm_code_builder_add_load(&ctx->builder, type, offset); \ + if (convert) ovm_code_builder_add_unop(&ctx->builder, OVM_TYPED_INSTR(convert_op, convert_type)); \ break; \ } - LOAD_CASE(0x28, OVM_TYPE_I32) - LOAD_CASE(0x29, OVM_TYPE_I64) - LOAD_CASE(0x2A, OVM_TYPE_F32) - LOAD_CASE(0x2B, OVM_TYPE_F64) + LOAD_CASE(0x28, OVM_TYPE_I32, false, 0, 0) + LOAD_CASE(0x29, OVM_TYPE_I64, false, 0, 0) + LOAD_CASE(0x2A, OVM_TYPE_F32, false, 0, 0) + LOAD_CASE(0x2B, OVM_TYPE_F64, false, 0, 0) - LOAD_CASE(0x2C, OVM_TYPE_I8) - LOAD_CASE(0x2D, OVM_TYPE_I8) - LOAD_CASE(0x2E, OVM_TYPE_I16) - LOAD_CASE(0x2F, OVM_TYPE_I16) - LOAD_CASE(0x30, OVM_TYPE_I8) - LOAD_CASE(0x31, OVM_TYPE_I8) - LOAD_CASE(0x32, OVM_TYPE_I16) - LOAD_CASE(0x33, OVM_TYPE_I16) - LOAD_CASE(0x34, OVM_TYPE_I32) - LOAD_CASE(0x35, OVM_TYPE_I32) + LOAD_CASE(0x2C, OVM_TYPE_I8, true, OVMI_CVT_I8_S, OVM_TYPE_I32) + LOAD_CASE(0x2D, OVM_TYPE_I8, true, OVMI_CVT_I8, OVM_TYPE_I32) + LOAD_CASE(0x2E, OVM_TYPE_I16, true, OVMI_CVT_I16_S, OVM_TYPE_I32) + LOAD_CASE(0x2F, OVM_TYPE_I16, true, OVMI_CVT_I16, OVM_TYPE_I32) + LOAD_CASE(0x30, OVM_TYPE_I8, true, OVMI_CVT_I8_S, OVM_TYPE_I64) + LOAD_CASE(0x31, OVM_TYPE_I8, true, OVMI_CVT_I8, OVM_TYPE_I64) + LOAD_CASE(0x32, OVM_TYPE_I16, true, OVMI_CVT_I16_S, OVM_TYPE_I64) + LOAD_CASE(0x33, OVM_TYPE_I16, true, OVMI_CVT_I16, OVM_TYPE_I64) + LOAD_CASE(0x34, OVM_TYPE_I32, true, OVMI_CVT_I32_S, OVM_TYPE_I64) + LOAD_CASE(0x35, OVM_TYPE_I32, true, OVMI_CVT_I32, OVM_TYPE_I64) #undef LOAD_CASE @@ -904,7 +908,6 @@ static void parse_code_section(build_context *ctx) { 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