aboutsummaryrefslogtreecommitdiff
path: root/src/compile/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compile/compile.c')
-rw-r--r--src/compile/compile.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/compile/compile.c b/src/compile/compile.c
index 54d79f2..60059d5 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -2505,6 +2505,40 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
+ case EJIT_OP_TAILI: {
+ /* a bit of copy-paste between this and the next func,
+ * hmm */
+ assert(operands_len(&direct) <= 2);
+ struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o;
+ assert(f->direct_call);
+
+ jit_operand_t regs[2] = {
+ jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R1),
+ jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R2)
+ };
+ jit_move_operands(j, regs, direct.buf, operands_len(&direct));
+
+ int frame_size = j->frame_size;
+ jit_shrink_stack(j, stack);
+ jit_leave_jit_abi(j, gprs, fprs, frame);
+
+ /* now move args into place */
+ jit_operand_t args[2] = {};
+ foreach_vec(oi, direct) {
+ args[oi] = *operands_at(&direct, oi);
+ }
+
+ jit_locate_args(j, operands_len(&direct), args);
+ jit_move_operands(j, args, regs, operands_len(&direct));
+ jit_jmpi(j, f->direct_call);
+ j->frame_size = frame_size;
+
+ operands_reset(&src);
+ operands_reset(&dst);
+ operands_reset(&direct);
+ break;
+ }
+
case EJIT_OP_TAILR: {
/* this is admittedly a slightly roundabout way of
* implementing tail calls and is arguably not the most
@@ -2518,6 +2552,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
jit_gpr_t r = getloc(f, j, i.r1, 0);
jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, direct_call));
#if defined(DEBUG)
+ /** @todo other checks? */
jit_reloc_t assert_reloc = jit_bnei(j, JIT_R0, 0); /* null */
jit_calli_1(j, assert_helper,
jit_operand_imm(JIT_OPERAND_ABI_POINTER,