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 /src | |
| parent | d65c2461d26bf485b88276984bbc33054d5bce20 (diff) | |
| download | ejit-2fc4f728643f78577c26e548619bc7db90a7c6ae.tar.gz ejit-2fc4f728643f78577c26e548619bc7db90a7c6ae.zip  | |
implement enough for fibonacci
Diffstat (limited to 'src')
| -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 | 
5 files changed, 93 insertions, 12 deletions
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 */  | 
