diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-23 23:31:46 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-23 23:38:49 +0300 |
commit | 5a4da8bac457f0e70e690a572eba9cf754e69a37 (patch) | |
tree | 58e48f1b12722eadbc1b2587b690b30afac54140 /src/ejit.c | |
download | ejit-5a4da8bac457f0e70e690a572eba9cf754e69a37.tar.gz ejit-5a4da8bac457f0e70e690a572eba9cf754e69a37.zip |
initial interpeter testing
Diffstat (limited to 'src/ejit.c')
-rw-r--r-- | src/ejit.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/ejit.c b/src/ejit.c new file mode 100644 index 0000000..bd5a652 --- /dev/null +++ b/src/ejit.c @@ -0,0 +1,190 @@ +#include <assert.h> +#include <sys/mman.h> + +#include <ejit/ejit.h> + +#include "common.h" + +static void emit_insn_i(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, long o) +{ + struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .o = o}; + vec_append(&f->insns, &i); +} + +static void emit_insn_r(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, size_t r2) +{ + struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .r2 = r2}; + vec_append(&f->insns, &i); +} + +static void emit_insn_p(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, void *p) +{ + struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .p = p}; + vec_append(&f->insns, &i); +} + +static void emit_insn_f(struct ejit_func *f, enum ejit_opcode op, size_t r0, size_t r1, double d) +{ + struct ejit_insn i = {.op = op, .r0 = r0, .r1 = r1, .d = d}; + vec_append(&f->insns, &i); +} + +struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, const struct ejit_operand args[argc]) +{ + struct ejit_func *f = malloc(sizeof(struct ejit_func)); + assert(f); + + f->rtype = rtype; + + f->insns = vec_create(sizeof(struct ejit_insn)); + f->arena = NULL; + f->size = 0; + + emit_insn_i(f, START, 0, 0, 0); + + for (size_t i = 0; i < argc; ++i) { + switch (args[i].kind) { + case EJIT_OPERAND_GPR: emit_insn_i(f, PARAM, args[i].r, 0, i); break; + case EJIT_OPERAND_FPR: emit_insn_i(f, PARAM_F, args[i].r, 0, i); break; + default: abort(); + } + } + + return f; +} + +void ejit_compile_func(struct ejit_func *f, size_t gpr, size_t fpr) +{ + f->gpr = gpr; + f->fpr = fpr; + /** @todo try to implement JIT */ + /* otherwise, convert opcodes to address labels */ + + void **labels; + /* just get labels, don't actually run anything yet */ + ejit_interp(f, 0, NULL, false, &labels); + foreach_vec(ii, f->insns) { + struct ejit_insn i = vect_at(struct ejit_insn, f->insns, ii); + i.addr = labels[i.op]; + vect_at(struct ejit_insn, f->insns, ii) = i; + } +} + +void ejit_destroy_func(struct ejit_func *f) +{ + if (f->arena) + munmap(f->arena, f->size); + + vec_destroy(&f->insns); + free(f); +} + +struct ejit_label ejit_label(struct ejit_func *f) +{ + return (struct ejit_label){.addr = vec_len(&f->insns)}; +} + +void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l) +{ + struct ejit_insn i = vect_at(struct ejit_insn, f->insns, r.insn); + /** @todo some assert that checks the opcode? */ + i.o = l.addr; + vect_at(struct ejit_insn, f->insns, r.insn) = i; +} + +void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) +{ + for (size_t i = 0; i < argc; ++i) { + switch (args[i].kind) { + case EJIT_OPERAND_GPR: emit_insn_i(s, ARG, args[i].r, args[i].type, 0); break; + case EJIT_OPERAND_FPR: emit_insn_i(s, ARG_F, args[i].r, args[i].type, 0); break; + case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, 0, args[i].type, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, 0, args[i].type, args[i].d); break; + default: abort(); + } + } + + emit_insn_p(s, CALLI, 0, 0, f); +} + +void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc, const struct ejit_operand args[argc]) +{ + for (size_t i = 0; i < argc; ++i) { + switch (args[i].kind) { + case EJIT_OPERAND_GPR: emit_insn_i(s, ARG, args[i].r, 0, 0); break; + case EJIT_OPERAND_FPR: emit_insn_i(s, ARG_F, args[i].r, 0, 0); break; + case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, 0, 0, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, 0, 0, args[i].d); break; + default: abort(); + } + } + + emit_insn_p(s, ESCAPEI, 0, 0, f); +} + +void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, const struct ejit_operand args[argc]) +{ + for (size_t i = 0; i < argc; ++i) { + switch (args[i].kind) { + case EJIT_OPERAND_GPR: emit_insn_i(s, ARG, args[i].r, 0, 0); break; + case EJIT_OPERAND_FPR: emit_insn_i(s, ARG_F, args[i].r, 0, 0); break; + case EJIT_OPERAND_IMM: emit_insn_i(s, ARG_I, 0, 0, args[i].r); break; + case EJIT_OPERAND_FLT: emit_insn_f(s, ARG_FI, 0, 0, args[i].d); break; + default: abort(); + } + } + + emit_insn_p(s, ESCAPEI_F, 0, 0, f); +} + +void ejit_ret(struct ejit_func *s, struct ejit_gpr r0) +{ + emit_insn_r(s, RET, r0.r, 0, 0); +} + +void ejit_ret_f(struct ejit_func *s, struct ejit_fpr r0) +{ + emit_insn_r(s, RET_F, r0.f, 0, 0); +} + +void ejit_ret_i(struct ejit_func *s, long i) +{ + emit_insn_i(s, RET_I, 0, 0, i); +} + +void ejit_ret_fi(struct ejit_func *s, double f) +{ + emit_insn_f(s, RET_FI, 0, 0, f); +} + +void ejit_addr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +{ + emit_insn_r(s, ADDR, r0.r, r1.r, r2.r); +} + +void ejit_addr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +{ + emit_insn_r(s, ADDR_F, r0.f, r1.f, r2.f); +} + +void ejit_subr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) +{ + emit_insn_r(s, SUBR, r0.r, r1.r, r2.r); +} + +void ejit_subr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2) +{ + emit_insn_r(s, SUBR_F, r0.f, r1.f, r2.f); +} + +void ejit_movi(struct ejit_func *s, struct ejit_gpr r0, long o) +{ + emit_insn_i(s, MOVI, r0.r, 0, o); +} + +struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1) +{ + struct ejit_label label = ejit_label(s); + emit_insn_i(s, BLTR, r0.r, r1.r, 0); + return (struct ejit_reloc){.insn = label.addr}; +} |