diff options
Diffstat (limited to 'src/compile/compile.c')
-rw-r--r-- | src/compile/compile.c | 35 |
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, |