aboutsummaryrefslogtreecommitdiff
path: root/src/ejit.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-04-09 20:20:48 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2025-04-09 20:20:48 +0300
commit057131cb20fb1c46e90adecfb4a16eb62f100580 (patch)
tree82081321522eaef1b049cce1fb4627a75a6d6664 /src/ejit.c
parent6824dd4b1ee22184f0e600115db3998924ed39d6 (diff)
downloadejit-057131cb20fb1c46e90adecfb4a16eb62f100580.tar.gz
ejit-057131cb20fb1c46e90adecfb4a16eb62f100580.zip
add taili
Diffstat (limited to 'src/ejit.c')
-rw-r--r--src/ejit.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/ejit.c b/src/ejit.c
index 059d5d4..0701b90 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -456,12 +456,54 @@ void ejit_patch(struct ejit_func *f, struct ejit_reloc r, struct ejit_label l)
*insns_at(&f->insns, r.insn) = i;
}
+void ejit_taili(struct ejit_func *s, struct ejit_func *f,
+ size_t argc, const struct ejit_operand args[argc])
+{
+ assert(s->rtype == f->rtype);
+
+ s->max_args = argc > s->max_args ? argc : s->max_args;
+ check_operands(f, argc, args);
+
+ size_t gpr_args = 0, fpr_args = 0;
+ for (size_t i = 0; i < argc; ++i) {
+ switch (args[i].kind) {
+ case EJIT_OPERAND_GPR:
+ gpr_args++;
+ emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_FPR:
+ fpr_args++;
+ emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r));
+ break;
+
+ case EJIT_OPERAND_IMM:
+ gpr_args++;
+ emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r);
+ break;
+
+ case EJIT_OPERAND_FLT:
+ fpr_args++;
+ emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d);
+ break;
+
+ default: abort();
+ }
+ }
+
+ assert(gpr_args <= 2 && fpr_args == 0
+ && "only 2 gpr args and 0 fpr args supported in tail calls for now");
+ emit_insn_op(s, EJIT_OP_TAILI, f);
+}
+
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;
- /** @todo check that gpr_args <= 2 and fpr_args <= 3 (?) */
+ /* operands must match */
+ check_operands(s, argc, args);
+
size_t gpr_args = 0, fpr_args = 0;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {