#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 NEXT_VALUE(b) (bh_arr_length((b)->execution_stack) == 0 ? \
- (b)->param_count + (b)->local_count : \
- ((b)->highest_value_number = bh_max((b)->highest_value_number, bh_arr_last((b)->execution_stack)), \
- bh_arr_last((b)->execution_stack) + 1))
-
// #define POP_VALUE(b) bh_arr_pop((b)->execution_stack)
+static inline int NEXT_VALUE(ovm_code_builder_t *b) {
+ 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;
+}
+
ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count, i32 local_count) {
ovm_code_builder_t builder;
builder.param_count = param_count;
ovm_program_add_instructions(builder->program, 3, instrs);
}
+void ovm_code_builder_add_memory_copy(ovm_code_builder_t *builder) {
+ ovm_instr_t instr = {0};
+ instr.full_instr = OVMI_COPY;
+ instr.b = POP_VALUE(builder);
+ instr.a = POP_VALUE(builder);
+ instr.r = POP_VALUE(builder);
+
+ ovm_program_add_instructions(builder->program, 1, &instr);
+}
+
+void ovm_code_builder_add_memory_fill(ovm_code_builder_t *builder) {
+ ovm_instr_t instr = {0};
+ instr.full_instr = OVMI_FILL;
+ instr.b = POP_VALUE(builder);
+ instr.a = POP_VALUE(builder);
+ instr.r = POP_VALUE(builder);
+
+ ovm_program_add_instructions(builder->program, 1, &instr);
+}
C(OVM_TYPED_INSTR(OVMI_XOR, OVM_TYPE_I32))
C(OVM_TYPED_INSTR(OVMI_XOR, OVM_TYPE_I64))
- C(OVM_TYPED_INSTR(OVMI_NOT, OVM_TYPE_I8))
- C(OVM_TYPED_INSTR(OVMI_NOT, OVM_TYPE_I16))
- C(OVM_TYPED_INSTR(OVMI_NOT, OVM_TYPE_I32))
- C(OVM_TYPED_INSTR(OVMI_NOT, OVM_TYPE_I64))
-
C(OVM_TYPED_INSTR(OVMI_SHL, OVM_TYPE_I8))
C(OVM_TYPED_INSTR(OVMI_SHL, OVM_TYPE_I16))
C(OVM_TYPED_INSTR(OVMI_SHL, OVM_TYPE_I32))
// is the start of a function, but for now, it'll do. -brendanfh 06/13/2022
bh_arr_each(ovm_func_t, func, program->funcs) {
if (i == func->start_instr && func->kind == OVM_FUNC_INTERNAL) {
- printf("\n[%d]%s:\n", func->id, func->name);
+ printf("\n[%d] %s values=%d:\n", func->id, func->name, func->value_number_count);
}
}
VAL(instr.r).type = t; \
VAL(instr.r).ctype = (ctype) op (VAL(instr.a).ctype); \
break;
-
- OVM_OP(OVMI_NOT, OVM_TYPE_I8 , ~, i8)
- OVM_OP(OVMI_NOT, OVM_TYPE_I16, ~, i16)
- OVM_OP(OVMI_NOT, OVM_TYPE_I32, ~, i32)
- OVM_OP(OVMI_NOT, OVM_TYPE_I64, ~, i64)
OVM_OP(OVMI_CLZ, OVM_TYPE_I8 , __builtin_clz, i8)
OVM_OP(OVMI_CLZ, OVM_TYPE_I16, __builtin_clz, i16)
static void parse_expression(build_context *ctx);
+static void parse_fc_instruction(build_context *ctx) {
+ int instr_num = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+
+ switch (instr_num) {
+ case 0: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32)); break;
+ case 1: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32)); break;
+ case 2: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32)); break;
+ case 3: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32)); break;
+ case 4: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64)); break;
+ case 5: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64)); break;
+ case 6: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64)); break;
+ case 7: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64)); break;
+
+ case 8: {
+ int dataidx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ assert(CONSUME_BYTE(ctx) == 0x00);
+
+ ovm_code_builder_drop_value(&ctx->builder);
+ ovm_code_builder_drop_value(&ctx->builder);
+ ovm_code_builder_drop_value(&ctx->builder);
+
+ // TODO: MEMORY INIT INSTRUCTION
+ break;
+ }
+
+ case 10: {
+ assert(CONSUME_BYTE(ctx) == 0x00);
+ assert(CONSUME_BYTE(ctx) == 0x00);
+
+ ovm_code_builder_add_memory_copy(&ctx->builder);
+ break;
+ }
+
+ case 11: {
+ assert(CONSUME_BYTE(ctx) == 0x00);
+
+ ovm_code_builder_add_memory_fill(&ctx->builder);
+ break;
+ }
+
+ default: assert(("UNHANDLED FC INSTRUCTION", 0));
+ }
+}
+
static void parse_instruction(build_context *ctx) {
- unsigned char instr_byte;
- switch (instr_byte = CONSUME_BYTE(ctx)) {
+ unsigned char instr_byte = CONSUME_BYTE(ctx);
+ switch (instr_byte) {
case 0x00: break;
case 0x01: break;
case 0x02: {
break;
}
- case 0x28: {
- 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, OVM_TYPE_I32, offset);
- break;
+#define LOAD_CASE(num, 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); \
+ break; \
}
- case 0x29: {
- 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, OVM_TYPE_I64, offset);
- 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)
- case 0x2A: {
- 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, OVM_TYPE_F32, offset);
- break;
- }
+ 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)
- case 0x2B: {
- 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, OVM_TYPE_F64, offset);
- break;
+#undef LOAD_CASE
+
+#define STORE_CASE(num, 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_store(&ctx->builder, type, offset); \
+ break; \
}
- // ... More loading and storing instruction here ...
+ STORE_CASE(0x36, OVM_TYPE_I32);
+ STORE_CASE(0x37, OVM_TYPE_I64);
+ STORE_CASE(0x38, OVM_TYPE_F32);
+ STORE_CASE(0x39, OVM_TYPE_F64);
- case 0x36: {
- 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, OVM_TYPE_I32, offset);
- break;
- }
+ STORE_CASE(0x3A, OVM_TYPE_I8);
+ STORE_CASE(0x3B, OVM_TYPE_I16);
+ STORE_CASE(0x3C, OVM_TYPE_I8);
+ STORE_CASE(0x3D, OVM_TYPE_I16);
+ STORE_CASE(0x3E, OVM_TYPE_I32);
- case 0x37: {
- 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, OVM_TYPE_I64, offset);
- break;
- }
+#undef STORE_CASE
- case 0x38: {
- 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, OVM_TYPE_F32, offset);
- break;
+ case 0x3F: {
+ assert(CONSUME_BYTE(ctx) == 0x00);
+
+ int memory_size = 65536;
+ ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &memory_size);
}
- case 0x39: {
- 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, OVM_TYPE_F64, offset);
+ case 0x40: {
+ assert(CONSUME_BYTE(ctx) == 0x00);
break;
}
break;
}
+ case 0x45: {
+ 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;
case 0x4E: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE_S, OVM_TYPE_I32)); break;
case 0x4F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE, OVM_TYPE_I32)); break;
+ case 0x50: {
+ 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;
+ }
case 0x51: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I64)); break;
case 0x52: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_I64)); break;
case 0x53: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LT_S, OVM_TYPE_I64)); break;
case 0xC3: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I64)); break;
case 0xC4: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64)); break;
+ case 0xFC: parse_fc_instruction(ctx); break;
+
default: assert(("UNHANDLED INSTRUCTION", 0));
}
}
ovm_code_builder_add_return(&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);
+ ovm_program_register_func(ctx->program, func_name, ctx->builder.start_instr, ctx->builder.param_count, ctx->builder.highest_value_number + 1);
ovm_code_builder_free(&ctx->builder);
}
}