aboutsummaryrefslogtreecommitdiff
path: root/src/ejit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejit.c')
-rw-r--r--src/ejit.c79
1 files changed, 30 insertions, 49 deletions
diff --git a/src/ejit.c b/src/ejit.c
index 571a274..059d5d4 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -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])