diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-09 20:20:48 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-09 20:20:48 +0300 |
commit | 057131cb20fb1c46e90adecfb4a16eb62f100580 (patch) | |
tree | 82081321522eaef1b049cce1fb4627a75a6d6664 /src/ejit.c | |
parent | 6824dd4b1ee22184f0e600115db3998924ed39d6 (diff) | |
download | ejit-057131cb20fb1c46e90adecfb4a16eb62f100580.tar.gz ejit-057131cb20fb1c46e90adecfb4a16eb62f100580.zip |
add taili
Diffstat (limited to 'src/ejit.c')
-rw-r--r-- | src/ejit.c | 44 |
1 files changed, 43 insertions, 1 deletions
@@ -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) { |