most test cases work!!
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 1 Jul 2022 18:18:18 +0000 (13:18 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 1 Jul 2022 18:18:18 +0000 (13:18 -0500)
build.sh
include/vm_codebuilder.h
src/vm/code_builder.c
src/vm/vm.c
src/wasm/module.c
src/wasm/module_parsing.c.incl

index 160e4565e3a07b4bdb49c758614569f3f8208fcd..e4095d852c2eba224e201e6293ee036675a9d936 100755 (executable)
--- 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"
index 9ea581741d47daf34b511d3e6575e8a3ada223b5..5261fadc021ba6ad62fe65955ad49e1e1d199d1c 100644 (file)
@@ -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);
index 07cb15989935f904afa05ad9b289b855ba336c25..bcca1722c5d9372b637b072068d24de898034967 100644 (file)
@@ -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);
index b9c6f4bb6877014b48936f7579d70dd58cc6b873..0d1cbfdee42c27df7f69681665fd7dbd71bf8052 100644 (file)
@@ -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; \
  \
index 70c4848800432fcd33746b5775ecb2d785e49213..07feb4528246b691eab09377f1e1953d940c34b4 100644 (file)
@@ -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); 
index 134bc20aa185c96c36909f01fa3ad50aed4a3121..5ed0321b862b2c12ac315e3ecb7afab8c879cb95 100644 (file)
@@ -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);