aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-06-28 18:32:56 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-06-28 18:38:43 +0300
commit2fc4f728643f78577c26e548619bc7db90a7c6ae (patch)
tree760d2ae310737b0ff39e37aa896d182f7df58c51
parentd65c2461d26bf485b88276984bbc33054d5bce20 (diff)
downloadejit-2fc4f728643f78577c26e548619bc7db90a7c6ae.tar.gz
ejit-2fc4f728643f78577c26e548619bc7db90a7c6ae.zip
implement enough for fibonacci
-rw-r--r--include/ejit/ejit.h3
-rw-r--r--src/common.h5
-rw-r--r--src/compile/compile.c34
-rw-r--r--src/ejit.c17
-rw-r--r--src/interp.c32
-rw-r--r--src/vec.h17
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);
diff --git a/src/ejit.c b/src/ejit.c
index 2040865..1fcae9d 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -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};
}
diff --git a/src/vec.h b/src/vec.h
index e998e27..7e6b5be 100644
--- a/src/vec.h
+++ b/src/vec.h
@@ -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 */