From 6824dd4b1ee22184f0e600115db3998924ed39d6 Mon Sep 17 00:00:00 2001
From: Kimplul <kimi.h.kuparinen@gmail.com>
Date: Wed, 9 Apr 2025 19:56:33 +0300
Subject: initial tail call stuff

---
 src/interp.c | 58 ++++++++++++++++++++++++++--------------------------------
 1 file changed, 26 insertions(+), 32 deletions(-)

(limited to 'src/interp.c')

diff --git a/src/interp.c b/src/interp.c
index 6ef414d..132ba4a 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -5,7 +5,7 @@
 /* this is the body of a given ejit_interp function, it assumes there's an
  * external int64_t retval and double retval_f into which it places the value to
  * be returned. Included from src/interp.c */
-union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg params[paramc], bool run, void ***labels_wb)
+union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg params[paramc], void ***labels_wb)
 {
 	static void *labels[EJIT_OPCODE_COUNT] = {
 		[EJIT_OP_MOVI] = &&MOVI,
@@ -213,10 +213,9 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
 		[EJIT_OP_PARAM] = &&PARAM,
 		[EJIT_OP_PARAM_F] = &&PARAM_F,
 
-		[EJIT_OP_CALLI_I] = &&CALLI_I,
-		[EJIT_OP_CALLI_L] = &&CALLI_L,
-		[EJIT_OP_CALLI_F] = &&CALLI_F,
-		[EJIT_OP_CALLI_D] = &&CALLI_D,
+		[EJIT_OP_CALLI] = &&CALLI,
+		[EJIT_OP_TAILR] = &&TAILR,
+
 		[EJIT_OP_ESCAPEI_I] = &&ESCAPEI_I,
 		[EJIT_OP_ESCAPEI_F] = &&ESCAPEI_F,
 		[EJIT_OP_ESCAPEI_L] = &&ESCAPEI_L,
@@ -226,13 +225,12 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
 		[EJIT_OP_END] = &&END,
 	};
 
-	if (!run) {
+	if (labels_wb) {
 		*labels_wb = labels;
 		return (union interp_ret){.i = 0};
 	}
 
 	assert(f->size && "trying to run a function that hasn't been compiled");
-
 	if (f->extern_call) {
 		if (f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64)
 			return (union interp_ret){
@@ -254,8 +252,8 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
 		};
 	}
 
-	int64_t retval = 0; double retval_f = 0.0;
-
+top:
+	union interp_ret retval = {.i = 0};
 	union fpr {
 		double d;
 		float f;
@@ -994,15 +992,15 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
 	DISPATCH();
 
 	DO(RETVAL);
-	gpr[i.r0] = retval;
+	gpr[i.r0] = retval.i;
 	DISPATCH();
 
 	DO(RETVAL_F);
-	fpr[i.r0].f = retval_f;
+	fpr[i.r0].f = retval.f;
 	DISPATCH();
 
 	DO(RETVAL_D);
-	fpr[i.r0].d = retval_f;
+	fpr[i.r0].d = retval.f;
 	DISPATCH();
 
 	DO(PARAM);
@@ -1058,51 +1056,47 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
 	args[argc++] = a;
 	DISPATCH();
 
-	DO(CALLI_I);
-	struct ejit_func *f = i.p;
-	retval = ejit_run(f, argc, args, true, NULL).i;
-	argc = 0;
-	DISPATCH();
+	DO(TAILR);
+	f = (struct ejit_func *)gpr[i.r1];
 
-	DO(CALLI_L);
-	struct ejit_func *f = i.p;
-	retval = ejit_run(f, argc, args, true, NULL).i;
-	argc = 0;
-	DISPATCH();
+	/** @todo we could potentially just interpret the func as a fallback
+	 * instead of aborting here, but this is good enough for now */
+	assert(!f->direct_call && "trying to interpret compiled fun");
 
-	DO(CALLI_F);
-	struct ejit_func *f = i.p;
-	retval_f = ejit_run(f, argc, args, true, NULL).f;
-	argc = 0;
+	paramc = argc;
+	for (size_t i = 0; i < argc; ++i)
+		params[i] = args[i];
+
+	goto top;
 	DISPATCH();
 
-	DO(CALLI_D);
+	DO(CALLI);
 	struct ejit_func *f = i.p;
-	retval_f = ejit_run(f, argc, args, true, NULL).f;
+	retval = ejit_run(f, argc, args, NULL);
 	argc = 0;
 	DISPATCH();
 
 	DO(ESCAPEI_I);
 	ejit_escape_i_t f = i.p;
-	retval = f(argc, args);
+	retval.i = f(argc, args);
 	argc = 0;
 	DISPATCH();
 
 	DO(ESCAPEI_L);
 	ejit_escape_l_t f = i.p;
-	retval = f(argc, args);
+	retval.i = f(argc, args);
 	argc = 0;
 	DISPATCH();
 
 	DO(ESCAPEI_F);
 	ejit_escape_f_t f = i.p;
-	retval_f = f(argc, args);
+	retval.f = f(argc, args);
 	argc = 0;
 	DISPATCH();
 
 	DO(ESCAPEI_D);
 	ejit_escape_d_t f = i.p;
-	retval_f = f(argc, args);
+	retval.f = f(argc, args);
 	argc = 0;
 	DISPATCH();
 
-- 
cgit v1.2.3