From 8f44960246c39845df83464ea9b4bc59220265aa Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 25 Jun 2024 20:44:20 +0300 Subject: example compiles under jit --- src/compile/compile.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 1 deletion(-) (limited to 'src/compile') diff --git a/src/compile/compile.c b/src/compile/compile.c index 513e0e1..e651199 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -2,7 +2,190 @@ #include "../../deps/lightening/lightening/lightening.c" #include "../common.h" +static void *alloc_arena(size_t size) +{ + return mmap(NULL, size, + PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +} + +static void free_arena(void *arena, size_t size) +{ + munmap(arena, size); +} + +static size_t grploc_count(struct ejit_func *f) +{ + return f->gpr >= jit_v_num() ? 0 : f->gpr - jit_v_num(); +} + +static size_t frploc_count(struct ejit_func *f) +{ + return f->fpr >= jit_vf_num() ? 0 : f->fpr - jit_vf_num(); +} + +static size_t stack_size(struct ejit_func *f) +{ + return grploc_count(f) * sizeof(jit_uword_t) + + frploc_count(f) * sizeof(jit_float64_t); +} + +static jit_off_t stack_loc(struct ejit_func *f, size_t l) +{ + assert(l >= jit_v_num()); + return (l - jit_v_num()) * sizeof(jit_uword_t); +} + +static jit_off_t stack_loc_f(struct ejit_func *f, size_t l) +{ + assert(l >= jit_vf_num()); + return grploc_count(f) * sizeof(jit_uword_t) + + (l - jit_vf_num()) * sizeof(jit_float64_t); +} + +struct reloc_helper { + jit_reloc_t r; + size_t to; +}; + +static jit_gpr_t getloc(struct ejit_func *f, jit_state_t *j, size_t l, size_t i) +{ + if (l < jit_v_num()) + return jit_v(l); + + jit_ldxi(j, jit_r(i), JIT_SP, stack_loc(f, l)); + return jit_r(i); +} + +static jit_gpr_t getreg(struct ejit_func *f, size_t l, size_t i) +{ + if (l < jit_v_num()) + return jit_v(l); + + return jit_r(i); +} + +static void putloc(struct ejit_func *f, jit_state_t *j, size_t l, jit_gpr_t r) +{ + if (l < jit_v_num()) { + assert(jit_v(l).regno == r.regno); + return; + } + + jit_stxi(j, stack_loc(f, l), JIT_SP, r); +} + +static void compile_label(jit_state_t *j, size_t ii, struct vec *labels) +{ + vect_at(jit_addr_t, *labels, ii) = jit_address(j); +} + +static void compile_movi(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +{ + jit_gpr_t r = getreg(f, i.r0, 0); + jit_movi(j, r, i.o); + putloc(f, j, i.r0, r); +} + +static void compile_addr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) +{ + jit_gpr_t dst = getreg(f, i.r0, 0); + jit_gpr_t src0 = getloc(f, j, i.r1, 1); + jit_gpr_t src1 = getloc(f, j, i.r2, 2); + jit_addr(j, dst, src0, src1); + putloc(f, j, i.r0, dst); +} + +static void compile_bltr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) +{ + jit_gpr_t c0 = getloc(f, j, i.r0, 0); + jit_gpr_t c1 = getloc(f, j, i.r1, 1); + jit_reloc_t r = jit_bltr(j, c0, c1); + struct reloc_helper h = {.r = r, .to = i.o}; + vect_append(struct reloc_helper, *relocs, &h); +} + +static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, size_t size) +{ + jit_begin(j, arena, size); + size_t gprs = f->gpr >= jit_v_num() ? jit_v_num() : f->gpr; + size_t fprs = f->fpr >= jit_vf_num() ? jit_vf_num() : f->fpr; + size_t frame = jit_enter_jit_abi(j, gprs, fprs, 0); + + size_t stack = jit_align_stack(j, stack_size(f)); + + struct vec relocs = vec_create(sizeof(struct reloc_helper)); + struct vec labels = vec_create(sizeof(jit_addr_t)); + vec_reserve(&labels, vec_len(&f->insns)); + + foreach_vec(ii, f->insns) { + struct ejit_insn i = vect_at(struct ejit_insn, f->insns, ii); + switch (i.op) { + case MOVI: compile_movi(f, j, i); break; + case ADDR: compile_addr(f, j, i); break; + + case BLTR: compile_bltr(f, j, i, &relocs); break; + + case LABEL: compile_label(j, ii, &labels); break; + case RET: { + jit_gpr_t r = getloc(f, j, i.r0, 0); + /* R0 won't get overwritten by jit_leave_jit_abi */ + jit_movr(j, JIT_R0, r); + jit_shrink_stack(j, stack); + jit_leave_jit_abi(j, gprs, fprs, frame); + jit_retr(j, JIT_R0); + break; + } + + case START: continue; + case END: continue; + default: abort(); + } + } + + foreach_vec(ri, relocs) { + struct reloc_helper h = vect_at(struct reloc_helper, relocs, ri); + jit_addr_t a = vect_at(jit_addr_t, labels, h.to); + jit_reloc_t r = h.r; + + assert(a); + jit_patch_there(j, r, a); + } + + vec_destroy(&relocs); + vec_destroy(&labels); + + if (jit_end(j, &size)) + return 0; + + return size; +} + bool ejit_compile(struct ejit_func *f) { - return false; + if (!init_jit()) + return false; + + jit_state_t *j = jit_new_state(NULL, NULL); + assert(j); + + void *arena = NULL; + size_t size = 4096; + + while (1) { + arena = alloc_arena(size); + assert(arena); + + size_t required_size = compile_fn_body(f, j, arena, size); + if (required_size == 0) + break; + + free_arena(arena, size); + size = required_size + 4096; + } + + jit_destroy_state(j); + f->arena = arena; + f->size = size; + return true; } -- cgit v1.2.3