aboutsummaryrefslogtreecommitdiff
path: root/src/compile
diff options
context:
space:
mode:
Diffstat (limited to 'src/compile')
-rw-r--r--src/compile/compile.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/src/compile/compile.c b/src/compile/compile.c
index 60059d5..bfcb12d 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -2476,17 +2476,10 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
+ case EJIT_OP_ESCAPEI_I:
case EJIT_OP_ESCAPEI_L:
-#if __WORDSIZE == 64
- /* fallthrough */
-#else
- assert(0 && "trying to compile escapei_l on 32bit arch");
- break;
-#endif
-
- case EJIT_OP_ESCAPEI_D:
case EJIT_OP_ESCAPEI_F:
- case EJIT_OP_ESCAPEI_I: {
+ case EJIT_OP_ESCAPEI_D: {
save_caller_save_regs(f, j);
jit_operand_t args[2] = {
@@ -2550,15 +2543,25 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
assert(operands_len(&direct) <= 2);
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_ldxi(j, JIT_R1, r, offsetof(struct ejit_func, rtype));
+ jit_reloc_t rtype_reloc = jit_beqi(j, JIT_R1, f->rtype);
+ jit_calli_1(j, assert_helper,
+ jit_operand_imm(JIT_OPERAND_ABI_POINTER,
+ (jit_imm_t)"trying to tail call different rtype"));
+
+ jit_patch_here(j, rtype_reloc);
+
+ jit_ldxi(j, JIT_R1, r, offsetof(struct ejit_func, direct_call));
+ jit_reloc_t direct_reloc = jit_bnei(j, JIT_R1, 0); /* null */
jit_calli_1(j, assert_helper,
jit_operand_imm(JIT_OPERAND_ABI_POINTER,
(jit_imm_t)"trying to tail call interpreted function"));
- jit_patch_here(j, assert_reloc);
+ jit_patch_here(j, direct_reloc);
#endif
+
+ jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, 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)
@@ -2591,6 +2594,50 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
+ case EJIT_OP_CALLR_I:
+ case EJIT_OP_CALLR_L:
+ case EJIT_OP_CALLR_F:
+ case EJIT_OP_CALLR_D: {
+ save_caller_save_regs(f, j);
+
+ jit_gpr_t target = getgpr(f, i.r1, 0);
+
+ /* check if there's a direct call avaiable */
+ jit_ldxi(j, JIT_R1, target, offsetof(struct ejit_func, direct_call));
+ jit_reloc_t direct_reloc = jit_beqi(j, JIT_R0, 0);
+ /* we can do a jit -> jit call */
+ jit_callr(j, JIT_R1, operands_len(&direct), direct.buf);
+ jit_reloc_t out_reloc = jit_jmp(j);
+
+ jit_patch_here(j, direct_reloc);
+
+ /* we must do a jit -> bytecode call */
+ jit_operand_t args[3] = {
+ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R1),
+ jit_operand_imm(JIT_OPERAND_ABI_WORD, operands_len(&src) / 2),
+ /* compile_imm_call populate JIT_R0 with the
+ * argument stack address */
+ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0)
+ };
+ void *call = NULL;
+ switch (i.op) {
+ case EJIT_OP_CALLR_I: call = ejit_run_func_i; break;
+ case EJIT_OP_CALLR_L: call = ejit_run_func_l; break;
+ case EJIT_OP_CALLR_F: call = ejit_run_func_f; break;
+ case EJIT_OP_CALLR_D: call = ejit_run_func_d; break;
+ default: abort();
+ }
+
+ compile_imm_call(j, &src, &dst, call, 3, args);
+ jit_patch_here(j, out_reloc);
+ restore_caller_save_regs(f, j);
+
+ operands_reset(&src);
+ operands_reset(&dst);
+ operands_reset(&direct);
+ break;
+ }
+
case EJIT_OP_CALLI: {
save_caller_save_regs(f, j);