starting work on easy code builder
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jun 2022 03:34:31 +0000 (22:34 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jun 2022 03:34:31 +0000 (22:34 -0500)
include/vm_codebuilder.h [new file with mode: 0644]
src/vm/code_builder.c [new file with mode: 0644]

diff --git a/include/vm_codebuilder.h b/include/vm_codebuilder.h
new file mode 100644 (file)
index 0000000..671e335
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _OVM_CODE_BUILDER_H
+#define _OVM_CODE_BUILDER_H
+
+#include "vm.h"
+
+typedef struct ovm_code_builder_t ovm_code_builder_t;
+
+//
+// A new code builder will be "made" for each function
+// being compiled.
+struct ovm_code_builder_t {
+    bh_arr(i32) execution_stack;
+
+    i32 param_count, local_count;
+
+    ovm_program_t *program;
+    i32 start_instr;
+};
+
+ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count, i32 local_count);
+void               ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr);
+void               ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *imm);
+
+
+#endif
diff --git a/src/vm/code_builder.c b/src/vm/code_builder.c
new file mode 100644 (file)
index 0000000..c64e368
--- /dev/null
@@ -0,0 +1,57 @@
+
+#include "vm_codebuilder.h"
+
+#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 : bh_arr_last((b)->execution_stack)) + 1)
+
+// #define POP_VALUE(b) bh_arr_pop((b)->execution_stack)
+
+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;
+    builder.local_count = local_count;
+    builder.start_instr = bh_arr_length(program->code);
+    builder.program = program;
+
+    builder.execution_stack = NULL;
+    bh_arr_new(bh_heap_allocator(), builder.execution_stack, 32);
+
+    return builder;
+}
+
+
+void ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr) {
+    i32 right  = POP_VALUE(builder);
+    i32 left   = POP_VALUE(builder);
+    i32 result = NEXT_VALUE(builder);
+
+    ovm_instr_t binop;
+    binop.full_instr = instr;
+    binop.r = result;
+    binop.a = left;
+    binop.b = right;
+
+    ovm_program_add_instructions(builder->program, 1, &binop);
+    PUSH_VALUE(builder, result);
+}
+
+void ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *imm) {
+    ovm_instr_t imm_instr;
+    imm_instr.full_instr = OVM_TYPED_INSTR(OVMI_IMM, ovm_type);
+    imm_instr.r = NEXT_VALUE(builder);
+
+    switch (ovm_type) {
+        case OVM_TYPE_I8:  imm_instr.i = (u32) *(u8 *) imm; break;
+        case OVM_TYPE_I16: imm_instr.i = (u32) *(u16 *) imm; break;
+        case OVM_TYPE_I32: imm_instr.i =       *(u32 *) imm; break;
+        case OVM_TYPE_I64: imm_instr.l =       *(u64 *) imm; break;
+        case OVM_TYPE_F32: imm_instr.f =       *(f32 *) imm; break;
+        case OVM_TYPE_F64: imm_instr.d =       *(f64 *) imm; break;
+        default: assert(("bad ovm type for add_imm", 0));
+    }
+
+    ovm_program_add_instructions(builder->program, 1, &imm_instr);
+    PUSH_VALUE(builder, imm_instr.r);
+}
+