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.
#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)
#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)
#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)
#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)
#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;
#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; \
}
#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)
#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);
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;
}
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;
}
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;
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 { \
#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);
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);
#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);
#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; \
\
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;
// 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;
}
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
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);