diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-28 18:32:56 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-06-28 18:38:43 +0300 |
commit | 2fc4f728643f78577c26e548619bc7db90a7c6ae (patch) | |
tree | 760d2ae310737b0ff39e37aa896d182f7df58c51 | |
parent | d65c2461d26bf485b88276984bbc33054d5bce20 (diff) | |
download | ejit-2fc4f728643f78577c26e548619bc7db90a7c6ae.tar.gz ejit-2fc4f728643f78577c26e548619bc7db90a7c6ae.zip |
implement enough for fibonacci
-rw-r--r-- | include/ejit/ejit.h | 3 | ||||
-rw-r--r-- | src/common.h | 5 | ||||
-rw-r--r-- | src/compile/compile.c | 34 | ||||
-rw-r--r-- | src/ejit.c | 17 | ||||
-rw-r--r-- | src/interp.c | 32 | ||||
-rw-r--r-- | src/vec.h | 17 |
6 files changed, 96 insertions, 12 deletions
diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index c816a29..17a6034 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -245,9 +245,11 @@ void ejit_stxi_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_gpr r1, lo void ejit_addr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2); void ejit_addr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2); +void ejit_addi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o); void ejit_subr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2); void ejit_subr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2); +void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o); void ejit_mulr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2); void ejit_mulr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2); @@ -263,6 +265,7 @@ void ejit_ltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struc struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1); struct ejit_reloc ejit_bnei(struct ejit_func *s, struct ejit_gpr r0, long o); struct ejit_reloc ejit_beqi(struct ejit_func *s, struct ejit_gpr r0, long o); +struct ejit_reloc ejit_bgti(struct ejit_func *s, struct ejit_gpr r0, long o); struct ejit_reloc ejit_jmp(struct ejit_func *s); void ejit_patch(struct ejit_func *s, struct ejit_reloc r, struct ejit_label l); diff --git a/src/common.h b/src/common.h index 8f42985..1f52f76 100644 --- a/src/common.h +++ b/src/common.h @@ -55,8 +55,12 @@ enum ejit_opcode { ADDR, ADDR_F, + ADDI, + SUBR, SUBR_F, + SUBI, + MULR, DIVR, NEGR, @@ -67,6 +71,7 @@ enum ejit_opcode { BLTR, BNEI, BEQI, + BGTI, JMP, PARAM, diff --git a/src/compile/compile.c b/src/compile/compile.c index ef3efcd..c07a46a 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -108,6 +108,14 @@ static void compile_addr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i putloc(f, j, i.r0, dst); } +static void compile_addi(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_addi(j, dst, src0, i.o); + putloc(f, j, i.r0, dst); +} + static void compile_subr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { jit_gpr_t dst = getreg(f, i.r0, 0); @@ -117,6 +125,14 @@ static void compile_subr(struct ejit_func *f, jit_state_t *j, struct ejit_insn i putloc(f, j, i.r0, dst); } +static void compile_subi(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_subi(j, dst, src0, i.o); + putloc(f, j, i.r0, dst); +} + static void compile_stxi64(struct ejit_func *f, jit_state_t *j, struct ejit_insn i) { jit_gpr_t r0 = getloc(f, j, i.r0, 0); @@ -194,6 +210,14 @@ static void compile_bnei(struct ejit_func *f, jit_state_t *j, struct ejit_insn i vect_append(struct reloc_helper, *relocs, &h); } +static void compile_bgti(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) +{ + jit_gpr_t r1 = getloc(f, j, i.r1, 0); + jit_reloc_t r = jit_bgti(j, r1, i.o); + struct reloc_helper h = {.r = r, .to = i.r0}; + vect_append(struct reloc_helper, *relocs, &h); +} + static void compile_jmp(struct ejit_func *f, jit_state_t *j, struct ejit_insn i, struct vec *relocs) { (void)(f); @@ -326,7 +350,9 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case MOVR: compile_movr(f, j, i); break; case MOVI: compile_movi(f, j, i); break; case ADDR: compile_addr(f, j, i); break; + case ADDI: compile_addi(f, j, i); break; case SUBR: compile_subr(f, j, i); break; + case SUBI: compile_subi(f, j, i); break; case STXI64: compile_stxi64(f, j, i); break; case LDXIU64: compile_ldxiu64(f, j, i); break; @@ -337,6 +363,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case BLTR: compile_bltr(f, j, i, &relocs); break; case BEQI: compile_beqi(f, j, i, &relocs); break; case BNEI: compile_bnei(f, j, i, &relocs); break; + case BGTI: compile_bgti(f, j, i, &relocs); break; case JMP: compile_jmp(f, j, i, &relocs); break; case ARG: { @@ -395,6 +422,13 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, break; } + case RET_I: { + jit_shrink_stack(j, stack); + jit_leave_jit_abi(j, gprs, fprs, frame); + jit_reti(j, i.o); + break; + } + case END: { /* 'void' return */ jit_shrink_stack(j, stack); @@ -199,6 +199,11 @@ void ejit_addr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, st emit_insn_r(s, ADDR_F, r0.f, r1.f, r2.f); } +void ejit_addi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o) +{ + emit_insn_i(s, ADDI, r0.r, r1.r, o); +} + 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); @@ -209,6 +214,11 @@ void ejit_subr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, st emit_insn_r(s, SUBR_F, r0.f, r1.f, r2.f); } +void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, long o) +{ + emit_insn_i(s, SUBI, r0.r, r1.r, o); +} + void ejit_mulr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1, struct ejit_gpr r2) { emit_insn_r(s, MULR, r0.r, r1.r, r2.r); @@ -268,6 +278,13 @@ struct ejit_reloc ejit_beqi(struct ejit_func *s, struct ejit_gpr r0, long o) return (struct ejit_reloc){.insn = addr}; } +struct ejit_reloc ejit_bgti(struct ejit_func *s, struct ejit_gpr r0, long o) +{ + size_t addr = vec_len(&s->insns); + emit_insn_i(s, BGTI, 0, r0.r, o); + return (struct ejit_reloc){.insn = addr}; +} + struct ejit_reloc ejit_jmp(struct ejit_func *s) { size_t addr = vec_len(&s->insns); diff --git a/src/interp.c b/src/interp.c index 9c3aea3..25f723a 100644 --- a/src/interp.c +++ b/src/interp.c @@ -2,7 +2,6 @@ #include "common.h" - union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], bool run, void ***labels_wb) { static void *labels[OPCODE_COUNT] = { @@ -12,8 +11,11 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a [ADDR] = &&ADDR, [ADDR_F] = &&ADDR_F, + [ADDI] = &&ADDI, + [SUBR] = &&SUBR, [SUBR_F] = &&SUBR_F, + [SUBI] = &&SUBI, [MULR] = &&MULR, [DIVR] = &&DIVR, @@ -27,6 +29,8 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a [BLTR] = &&BLTR, [BNEI] = &&BNEI, [BEQI] = &&BEQI, + [BGTI] = &&BGTI, + [JMP] = &&JMP, [RET] = &&RET, @@ -57,21 +61,19 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a return (union interp_ret){.r = 0}; } - /** @todo this can be optimized by for example using a common buffer - * 'stack' */ long *gpr = malloc(f->gpr * sizeof(long)); - long *fpr = malloc(f->fpr * sizeof(long)); + double *fpr = malloc(f->fpr * sizeof(double)); + struct vec call_args = vec_create(sizeof(struct ejit_arg)); struct ejit_insn *insns = f->insns.buf; - struct ejit_insn i; /* retval is kind of an unfortunate extra bit of state to keep track of, * but having call and return value separated is pretty convenient for * void calls so I guess I don't mind? */ long retval = 0; double retval_f = 0.; size_t pc = 0; -#define DO(x) x: { i = insns[pc]; +#define DO(x) x: { struct ejit_insn i = insns[pc]; (void)i; #define JUMP(a) goto *insns[pc = a].addr; #define DISPATCH() } goto *insns[++pc].addr; @@ -104,6 +106,10 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a fpr[i.r0] = fpr[i.r1] + fpr[i.r2]; DISPATCH(); + DO(ADDI); + gpr[i.r0] = gpr[i.r1] + i.o; + DISPATCH(); + DO(SUBR); gpr[i.r0] = gpr[i.r1] - gpr[i.r2]; DISPATCH(); @@ -112,6 +118,10 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a fpr[i.r0] = fpr[i.r1] - fpr[i.r2]; DISPATCH(); + DO(SUBI); + gpr[i.r0] = gpr[i.r1] - i.o; + DISPATCH(); + DO(MULR); gpr[i.r0] = gpr[i.r1] * gpr[i.r2]; DISPATCH(); @@ -156,6 +166,12 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a DISPATCH(); + DO(BGTI); + if (gpr[i.r1] > i.o) + JUMP(i.r0); + + DISPATCH(); + DO(JMP); JUMP(i.r0); DISPATCH(); @@ -237,14 +253,14 @@ union interp_ret ejit_interp(struct ejit_func *f, size_t argc, struct ejit_arg a #undef DO out_int: - vec_destroy(&call_args); free(gpr); free(fpr); + vec_destroy(&call_args); return (union interp_ret){.r = retval}; out_float: - vec_destroy(&call_args); free(gpr); free(fpr); + vec_destroy(&call_args); return (union interp_ret){.d = retval_f}; } @@ -33,11 +33,12 @@ struct vec { static inline struct vec vec_create(size_t ns) { + const size_t s = 8; return (struct vec) { .n = 0, - .s = 1, + .s = s, .ns = ns, - .buf = malloc(ns), + .buf = malloc(s * ns), }; } @@ -98,8 +99,16 @@ static inline void vec_reserve(struct vec *v, size_t n) return; v->n = n; - v->s = n; - v->buf = realloc(v->buf, v->s * v->ns); + if (v->s < v->n) { + v->s *= 2; + v->buf = realloc(v->buf, v->s * v->ns); + } +} + +static inline void vec_shrink(struct vec *v, size_t n) +{ + assert(v->n >= n); + v->n = n; } #endif /* VEC_H */ |