void ovm_state_delete(ovm_state_t *state);
void ovm_state_link_external_funcs(ovm_program_t *program, ovm_state_t *state, ovm_linkable_func_t *funcs);
void ovm_state_register_external_func(ovm_state_t *state, i32 idx, void (*func)(void *, ovm_value_t *, ovm_value_t *), void *data);
+ovm_value_t ovm_state_register_get(ovm_state_t *state, i32 idx);
void ovm_state_register_set(ovm_state_t *state, i32 idx, ovm_value_t val);
//
#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)
+#define OVMI_CVT_F32_S 0x69 // %r = (t) %a (sign aware)
+#define OVMI_CVT_F64 0x6A // %r = (t) %a
+#define OVMI_CVT_F64_S 0x6B // %r = (t) %a (sign aware)
+#define OVMI_TRANSMUTE_I32 0x6C // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_I64 0x6D // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F32 0x6E // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F64 0x6F // %r = *(t *) &%a (reinterpret bytes)
#define OVMI_CMPXCHG 0x70 // %r = %r == %a ? %b : %r
new_entry.start_idx = bh_arr_length(program->static_integers);
new_entry.len = len;
- bh_arr_insert_end(program->static_integers, len);
fori (i, 0, (int) len) {
- program->static_integers[i + new_entry.start_idx] = data[i];
+ bh_arr_push(program->static_integers, data[i]);
}
bh_arr_push(program->static_data, new_entry);
bh_arr_free(state->params);
bh_arr_free(state->stack_frames);
bh_arr_free(state->registers);
+ bh_arr_free(state->external_funcs);
bh_free(store->heap_allocator, state);
}
bh_arr_set_at(state->external_funcs, idx, external_func);
}
+ovm_value_t ovm_state_register_get(ovm_state_t *state, i32 idx) {
+ assert(idx < bh_arr_length(state->registers));
+
+ return state->registers[idx];
+}
+
void ovm_state_register_set(ovm_state_t *state, i32 idx, ovm_value_t val) {
if (idx >= bh_arr_length(state->registers)) return;
bh_arr_insert_end(state->numbered_values, func->value_number_count);
}
+static inline ovm_stack_frame_t ovm__func_teardown_stack_frame(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *program) {
+ ovm_stack_frame_t frame = bh_arr_pop(state->stack_frames);
+ bh_arr_fastdeleten(state->numbered_values, frame.value_number_count);
+
+ state->value_number_offset = bh_arr_last(state->stack_frames).value_number_base;
+ return frame;
+}
+
ovm_value_t ovm_func_call(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *program, i32 func_idx, i32 param_count, ovm_value_t *params) {
ovm_func_t func = program->funcs[func_idx];
+ assert(func.value_number_count >= func.param_count);
switch (func.kind) {
case OVM_FUNC_INTERNAL: {
ovm_value_t result = {0};
ovm_external_func_t external_func = state->external_funcs[func.external_func_idx];
external_func.native_func(external_func.userdata, state->params, &result);
-
- bh_arr_pop(state->stack_frames);
- state->value_number_offset = bh_arr_last(state->stack_frames).value_number_base;
- bh_arr_fastdeleten(state->numbered_values, func.value_number_count);
bh_arr_fastdeleten(state->params, func.param_count);
+ ovm__func_teardown_stack_frame(engine, state, program);
return result;
}
assert(state);
assert(program);
-#define VAL(loc) (state->numbered_values[(u32) (loc + state->value_number_offset)])
+#define VAL(loc) state->numbered_values[(u32) (loc + state->value_number_offset)]
ovm_instr_t *code = program->code;
bool release_mutex_at_end = false;
}
case OVMI_REG_GET: {
- VAL(instr.r) = state->registers[instr.a];
+ VAL(instr.r) = ovm_state_register_get(state, instr.a);
break;
}
case OVMI_REG_SET: {
- state->registers[instr.r] = VAL(instr.a);
+ ovm_state_register_set(state, instr.r, VAL(instr.a));
break;
}
break;
case OVMI_RETURN: {
- ovm_stack_frame_t frame = bh_arr_pop(state->stack_frames);
-
ovm_value_t val = VAL(instr.a);
- bh_arr_fastdeleten(state->numbered_values, frame.value_number_count);
+ ovm_stack_frame_t frame = ovm__func_teardown_stack_frame(engine, state, program);
- if (bh_arr_length(state->stack_frames) == 0) {
- state->value_number_offset = 0;
+ if (frame.return_number_value >= 0) {
VAL(frame.return_number_value) = val;
- return;
}
- state->value_number_offset = bh_arr_last(state->stack_frames).value_number_base;
- if (frame.return_number_value >= 0) {
- VAL(frame.return_number_value) = val;
+ if (bh_arr_length(state->stack_frames) == 0) {
+ return;
}
ovm_func_t *new_func = bh_arr_last(state->stack_frames).func;
external_func.native_func(external_func.userdata, state->params + extra_params, &result); \
bh_arr_fastdeleten(state->params, func->param_count); \
\
- ovm_stack_frame_t frame = bh_arr_pop(state->stack_frames); \
- bh_arr_fastdeleten(state->numbered_values, frame.value_number_count); \
- state->value_number_offset = bh_arr_last(state->stack_frames).value_number_base; \
+ ovm__func_teardown_stack_frame(engine, state, program); \
\
if (instr.r >= 0) { \
VAL(instr.r) = result; \
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, 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);
- case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64): CVT(f64, i64, OVM_TYPE_I64, u64);
- case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32): CVT(f64, f32, OVM_TYPE_F32, f32);
+ 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_F32_S, OVM_TYPE_I32): CVT(f32, i32, OVM_TYPE_I32, i32);
+ case OVM_TYPED_INSTR(OVMI_CVT_F32_S, OVM_TYPE_I64): CVT(f32, i64, OVM_TYPE_I64, i64);
+ case OVM_TYPED_INSTR(OVMI_CVT_F32_S, OVM_TYPE_F64): CVT(f32, f64, OVM_TYPE_F64, f64);
+
+ case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32): CVT(f64, u32, OVM_TYPE_I32, u32);
+ case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64): CVT(f64, u64, OVM_TYPE_I64, u64);
+ case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32): CVT(f64, f32, OVM_TYPE_F32, f32);
+ case OVM_TYPED_INSTR(OVMI_CVT_F64_S, OVM_TYPE_I32): CVT(f64, i32, OVM_TYPE_I32, i32);
+ case OVM_TYPED_INSTR(OVMI_CVT_F64_S, OVM_TYPE_I64): CVT(f64, i64, OVM_TYPE_I64, i64);
+ case OVM_TYPED_INSTR(OVMI_CVT_F64_S, OVM_TYPE_F32): CVT(f64, f32, OVM_TYPE_F32, f32);
#undef CVT
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 0xA8: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32_S, 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 0xAA: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64_S, 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 0xAE: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32_S, 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 0xB0: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64_S, 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;