static void parse_instruction(build_context *ctx) {
char instr_byte;
switch (instr_byte = CONSUME_BYTE(ctx)) {
- case 0x00: return;
- case 0x01: return;
+ case 0x00: break;
+ case 0x01: break;
case 0x02: {
// Currently, only "void" block types are valid.
assert(CONSUME_BYTE(ctx) == 0x40);
push_label_target(ctx, label_kind_block);
- parse_expression(ctx);
+ break;
+ }
+
+ case 0x03: {
+ // Currently, only "void" block types are valid.
+ assert(CONSUME_BYTE(ctx) == 0x40);
+ push_label_target(ctx, label_kind_loop);
+ break;
+ }
+
+ case 0x04: {
+ // Currently, only "void" block types are valid.
+ assert(CONSUME_BYTE(ctx) == 0x40);
+ push_label_target(ctx, label_kind_block);
+ // TODO: Ifs
+ break;
+ }
+
+ case 0x05: {
+ // TODO: If-elses
+ break;
+ }
+
+ case 0x0B: {
pop_label_target(ctx);
- return;
+ break;
+ }
+
+ case 0x0C: {
+ int label_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_branch(&ctx->builder, label_idx);
+ break;
}
+
+ case 0x0D: {
+ int label_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_cond_branch(&ctx->builder, label_idx);
+ break;
+ }
+
+ case 0x0E: assert(0); {
+ // TODO: Branch tables
+ break;
+ }
+
+ case 0x0F: {
+ ovm_code_builder_add_return(&ctx->builder);
+ break;
+ }
+
+ case 0x10: {
+ int func_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ int param_count = ctx->program->funcs[func_idx].param_count;
+ ovm_code_builder_add_call(&ctx->builder, param_count);
+ break;
+ }
+
+ case 0x11: {
+ int type_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ int table_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ assert(table_idx == 0);
+
+ int param_count = ctx->module->type_section.data[type_idx]->type.func.params.size;
+ ovm_code_builder_add_indirect_call(&ctx->builder, param_count);
+ break;
+ }
+
+ case 0x1A: {
+ ovm_code_builder_drop_value(&ctx->builder);
+ break;
+ }
+
+ case 0x1B: assert(0);
+
+ case 0x20: {
+ int local_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_local_get(&ctx->builder, local_idx);
+ break;
+ }
+
+ case 0x21: {
+ int local_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_local_set(&ctx->builder, local_idx);
+ break;
+ }
+
+ case 0x22: {
+ int local_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_local_set(&ctx->builder, local_idx);
+ ovm_code_builder_add_local_get(&ctx->builder, local_idx);
+ break;
+ }
+
+ case 0x23: {
+ int global_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_register_get(&ctx->builder, global_idx);
+ break;
+ }
+
+ case 0x24: {
+ int global_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_register_set(&ctx->builder, global_idx);
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ // ... More loading and storing instruction here ...
+
+ case 0x41: {
+ int value = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &value);
+ break;
+ }
+
+ case 0x42: {
+ long long value = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I64, &value);
+ break;
+ }
+
+ case 0x43: {
+ float value = * (f32 *) &ctx->binary.data[ctx->offset];
+ ctx->offset += 4;
+ ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_F32, &value);
+ break;
+ }
+
+ case 0x44: {
+ double value = * (f64 *) &ctx->binary.data[ctx->offset];
+ ctx->offset += 4;
+ ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_F64, &value);
+ 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 0x49: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LT, OVM_TYPE_I32)); break;
+ case 0x4A: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GT_S, OVM_TYPE_I32)); break;
+ case 0x4B: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GT, OVM_TYPE_I32)); break;
+ case 0x4C: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE_S, OVM_TYPE_I32)); break;
+ case 0x4D: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE, 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 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 0x54: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LT, OVM_TYPE_I64)); break;
+ case 0x55: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GT_S, OVM_TYPE_I64)); break;
+ case 0x56: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GT, OVM_TYPE_I64)); break;
+ case 0x57: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE_S, OVM_TYPE_I64)); break;
+ case 0x58: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE, OVM_TYPE_I64)); break;
+ case 0x59: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE_S, OVM_TYPE_I64)); break;
+ case 0x5A: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE, OVM_TYPE_I64)); break;
+
+ case 0x5B: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_F32)); break;
+ case 0x5C: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_F32)); break;
+ case 0x5D: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LT, OVM_TYPE_F32)); break;
+ case 0x5E: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GT, OVM_TYPE_F32)); break;
+ case 0x5F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE, OVM_TYPE_F32)); break;
+ case 0x60: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE, OVM_TYPE_F32)); break;
+
+ case 0x61: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_F64)); break;
+ case 0x62: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_F64)); break;
+ case 0x63: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LT, OVM_TYPE_F64)); break;
+ case 0x64: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GT, OVM_TYPE_F64)); break;
+ case 0x65: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE, OVM_TYPE_F64)); break;
+ case 0x66: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE, OVM_TYPE_F64)); break;
+
+
+ default: assert(("UNHANDLED INSTRUCTION", 0));
}
}
static void parse_expression(build_context *ctx) {
- while (PEEK_BYTE(ctx) != 0x0B) {
+ while (bh_arr_length(ctx->builder.label_stack) > 0) {
parse_instruction(ctx);
}
}