diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-09 19:56:33 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-09 19:56:33 +0300 |
commit | 6824dd4b1ee22184f0e600115db3998924ed39d6 (patch) | |
tree | 0afbf35344313bdd17238b4fb570af0d094f758d /src/ejit.c | |
parent | 9e367e1824d62d3759cb19b7c9a433b67b96bd99 (diff) | |
download | ejit-6824dd4b1ee22184f0e600115db3998924ed39d6.tar.gz ejit-6824dd4b1ee22184f0e600115db3998924ed39d6.zip |
initial tail call stuff
Diffstat (limited to 'src/ejit.c')
-rw-r--r-- | src/ejit.c | 79 |
1 files changed, 30 insertions, 49 deletions
@@ -414,7 +414,7 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, void **labels; /* just get labels, don't actually run anything yet */ - ejit_run(f, 0, NULL, false, &labels); + ejit_run(f, 0, NULL, &labels); foreach_vec(ii, f->insns) { struct ejit_insn i = *insns_at(&f->insns, ii); @@ -456,67 +456,48 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l) *insns_at(&f->insns, r.insn) = i; } -void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc, +void ejit_tailr(struct ejit_func *s, struct ejit_gpr target, size_t argc, const struct ejit_operand args[argc]) { s->max_args = argc > s->max_args ? argc : s->max_args; - check_operands(f, argc, args); + /** @todo check that gpr_args <= 2 and fpr_args <= 3 (?) */ + size_t gpr_args = 0, fpr_args = 0; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } - - emit_insn_op(s, EJIT_OP_CALLI_I, f); -} - -void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]) -{ - s->use_64 = true; - s->max_args = argc > s->max_args ? argc : s->max_args; - check_operands(f, argc, args); + case EJIT_OPERAND_GPR: + gpr_args++; + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } + case EJIT_OPERAND_FPR: + fpr_args++; + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; - emit_insn_op(s, EJIT_OP_CALLI_L, f); -} + case EJIT_OPERAND_IMM: + gpr_args++; + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; -void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]) -{ - s->max_args = argc > s->max_args ? argc : s->max_args; - check_operands(f, argc, args); + case EJIT_OPERAND_FLT: + fpr_args++; + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; default: abort(); } } - emit_insn_op(s, EJIT_OP_CALLI_F, f); + assert(gpr_args <= 2 && fpr_args == 0 + && "only 2 gpr args and 0 fpr args supported in tail calls for now"); + emit_insn_oxr(s, EJIT_OP_TAILR, target); } -void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, +void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, const struct ejit_operand args[argc]) { + s->use_64 = f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64; s->max_args = argc > s->max_args ? argc : s->max_args; check_operands(f, argc, args); @@ -530,7 +511,7 @@ void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, } } - emit_insn_op(s, EJIT_OP_CALLI_D, f); + emit_insn_op(s, EJIT_OP_CALLI, f); } void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, @@ -1712,7 +1693,7 @@ long ejit_run_func_i(struct ejit_func *f, size_t argc, #endif ); - return ejit_run(f, argc, args, true, NULL).i; + return ejit_run(f, argc, args, NULL).i; } int64_t ejit_run_func_l(struct ejit_func *f, size_t argc, @@ -1720,21 +1701,21 @@ int64_t ejit_run_func_l(struct ejit_func *f, size_t argc, { check_args(f, argc, args); assert(f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64); - return ejit_run(f, argc, args, true, NULL).i; + return ejit_run(f, argc, args, NULL).i; } float ejit_run_func_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { check_args(f, argc, args); assert(f->rtype == EJIT_FLOAT); - return ejit_run(f, argc, args, true, NULL).f; + return ejit_run(f, argc, args, NULL).f; } double ejit_run_func_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) { check_args(f, argc, args); assert(f->rtype == EJIT_DOUBLE); - return ejit_run(f, argc, args, true, NULL).f; + return ejit_run(f, argc, args, NULL).f; } struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]) |