aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common.h43
-rw-r--r--src/compile/compile.c182
-rw-r--r--src/ejit.c248
-rw-r--r--src/interp.c (renamed from src/interp.inc)201
-rw-r--r--src/vec.h4
5 files changed, 514 insertions, 164 deletions
diff --git a/src/common.h b/src/common.h
index df150c1..b845e1c 100644
--- a/src/common.h
+++ b/src/common.h
@@ -204,11 +204,15 @@ enum ejit_opcode {
ARG_F,
ARG_FI,
- ESCAPEI,
+ ESCAPEI_I,
+ ESCAPEI_L,
ESCAPEI_F,
+ ESCAPEI_D,
- CALLI,
+ CALLI_I,
+ CALLI_L,
CALLI_F,
+ CALLI_D,
RETR,
RETI,
@@ -248,6 +252,9 @@ struct ejit_insn {
#define VEC_NAME insns
#include "vec.h"
+#define VEC_TYPE enum ejit_type
+#define VEC_NAME types
+#include "vec.h"
struct fpr_stat {
struct ejit_fpr f;
@@ -268,6 +275,7 @@ struct gpr_stat {
#include "vec.h"
struct ejit_func {
+ struct types sign;
struct insns insns;
struct labels labels;
enum ejit_type rtype;
@@ -289,27 +297,16 @@ struct interp_state {
struct args args;
};
-int64_t ejit_interp(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc],
- struct interp_state *state, bool run,
- void ***labels_wb);
-
-double ejit_interp_f(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc],
- struct interp_state *state, bool run,
- void ***labels_wb);
-
-int64_t ejit_run_interp(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc],
- struct interp_state *state,
- bool run,
- void ***labels_wb);
-
-double ejit_run_interp_f(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc],
- struct interp_state *state,
- bool run,
- void ***labels_wb);
+union interp_ret {
+ int64_t i;
+ double f;
+};
+
+union interp_ret ejit_run(struct ejit_func *f, size_t argc,
+ struct ejit_arg args[argc],
+ struct interp_state *state,
+ bool run,
+ void ***labels_wb);
bool ejit_compile(struct ejit_func *f, bool use_64);
diff --git a/src/compile/compile.c b/src/compile/compile.c
index c9c7652..e741a0f 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -650,8 +650,15 @@ static void compile_sti32(struct ejit_func *f, jit_state_t *j,
static void compile_sti64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getloc(f, j, i.r0, 0);
jit_sti_l(j, i.p, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile sti64 on 32bit arch");
+#endif
}
static void compile_stif(struct ejit_func *f, jit_state_t *j,
@@ -695,9 +702,16 @@ static void compile_stxi32(struct ejit_func *f, jit_state_t *j,
static void compile_stxi64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getloc(f, j, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_stxi_l(j, i.o, r1, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile stxi64 on 32bit arch");
+#endif
}
static void compile_stxif(struct ejit_func *f, jit_state_t *j,
@@ -746,10 +760,17 @@ static void compile_stxr32(struct ejit_func *f, jit_state_t *j,
static void compile_stxr64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getloc(f, j, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_gpr_t r2 = getloc(f, j, i.r2, 2);
jit_stxr_l(j, r2, r1, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile stxr64 on 32bit arch");
+#endif
}
static void compile_stxrf(struct ejit_func *f, jit_state_t *j,
@@ -789,17 +810,31 @@ static void compile_ldiu16(struct ejit_func *f, jit_state_t *j,
static void compile_ldiu32(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_ldi_ui(j, r0, i.p);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldiu32 on 32bit arch");
+#endif
}
static void compile_ldiu64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_ldi_l(j, r0, i.p);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldiu64 on 32bit arch");
+#endif
}
static void compile_ldif(struct ejit_func *f, jit_state_t *j,
@@ -845,9 +880,16 @@ static void compile_ldi32(struct ejit_func *f, jit_state_t *j,
static void compile_ldi64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_ldi_l(j, r0, i.p);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldi64 on 32bit arch");
+#endif
}
static void compile_ldxiu8(struct ejit_func *f, jit_state_t *j,
@@ -871,19 +913,33 @@ static void compile_ldxiu16(struct ejit_func *f, jit_state_t *j,
static void compile_ldxiu32(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_ldxi_ui(j, r0, r1, i.o);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldxiu32 on 32bit arch");
+#endif
}
static void compile_ldxiu64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_ldxi_l(j, r0, r1, i.o);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldxiu64 on 32bit arch");
+#endif
}
static void compile_ldxif(struct ejit_func *f, jit_state_t *j,
@@ -934,10 +990,17 @@ static void compile_ldxi32(struct ejit_func *f, jit_state_t *j,
static void compile_ldxi64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_ldxi_l(j, r0, r1, i.o);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldxi64 on 32bit arch");
+#endif
}
static void compile_ldxru8(struct ejit_func *f, jit_state_t *j,
@@ -963,21 +1026,35 @@ static void compile_ldxru16(struct ejit_func *f, jit_state_t *j,
static void compile_ldxru32(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_gpr_t r2 = getloc(f, j, i.r2, 2);
jit_ldxr_ui(j, r0, r1, r2);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldxru32 on 32bit arch");
+#endif
}
static void compile_ldxru64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_gpr_t r2 = getloc(f, j, i.r2, 2);
jit_ldxr_l(j, r0, r1, r2);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldxru64 on 32bit arch");
+#endif
}
static void compile_ldxr8(struct ejit_func *f, jit_state_t *j,
@@ -1013,11 +1090,18 @@ static void compile_ldxr32(struct ejit_func *f, jit_state_t *j,
static void compile_ldxr64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_gpr_t r2 = getloc(f, j, i.r2, 2);
jit_ldxr_l(j, r0, r1, r2);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile ldxr64 on 32bit arch");
+#endif
}
static void compile_ldxrf(struct ejit_func *f, jit_state_t *j,
@@ -1097,10 +1181,17 @@ static void compile_extr16(struct ejit_func *f, jit_state_t *j,
static void compile_extr32(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_extr_i(j, r0, r1);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile extr32 on 32bit arch");
+#endif
}
static void compile_extru8(struct ejit_func *f, jit_state_t *j,
@@ -1124,10 +1215,17 @@ static void compile_extru16(struct ejit_func *f, jit_state_t *j,
static void compile_extru32(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_gpr_t r1 = getloc(f, j, i.r1, 1);
jit_extr_ui(j, r0, r1);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile extru32 on 32bit arch");
+#endif
}
static void compile_extrf(struct ejit_func *f, jit_state_t *j,
@@ -1151,10 +1249,17 @@ static void compile_extrd(struct ejit_func *f, jit_state_t *j,
static void compile_truncr_d_64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_fpr_t r1 = getloc_d(f, j, i.r1, 1);
jit_truncr_d_l(j, r0, r1);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile truncr_d_64 on 32bit arch");
+#endif
}
static void compile_truncr_d_32(struct ejit_func *f, jit_state_t *j,
@@ -1174,10 +1279,17 @@ static void compile_truncr_d_32(struct ejit_func *f, jit_state_t *j,
static void compile_truncr_f_64(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
+#if __WORDSIZE == 64
jit_gpr_t r0 = getgpr(f, i.r0, 0);
jit_fpr_t r1 = getloc_f(f, j, i.r1, 1);
jit_truncr_f_l(j, r0, r1);
putloc(f, j, i.r0, r0);
+#else
+ (void)f;
+ (void)j;
+ (void)i;
+ assert(0 && "trying to compile truncr_f_64 on 32bit arch");
+#endif
}
static void compile_truncr_f_32(struct ejit_func *f, jit_state_t *j,
@@ -1645,9 +1757,7 @@ static void compile_retval_f(struct ejit_func *f, jit_state_t *j,
struct ejit_insn i)
{
jit_fpr_t r0 = getfpr(f, i.r0, 0);
- jit_retval_d(j, r0);
- /* convert double to float */
- jit_extr_d_f(j, r0, r0);
+ jit_retval_f(j, r0);
putloc_f(f, j, i.r0, r0);
}
@@ -1734,6 +1844,8 @@ static void compile_imm_call(jit_state_t *j, struct operands *src, struct operan
/* note, do not fix up destination! */
/* remember to move all operands */
jit_move_operands(j, dst->buf, src->buf, movec * 2);
+
+ jit_movr(j, JIT_R0, JIT_SP);
jit_calli(j, addr, argc, args);
jit_shrink_stack(j, fixup);
@@ -1814,6 +1926,8 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
struct addrs addrs = addrs_create();
addrs_reserve(&addrs, insns_len(&f->insns));
+ void *call = NULL;
+
size_t label = 0;
foreach_vec(ii, f->insns) {
/* if we've hit a label, add it to our vector of label addresses */
@@ -2072,32 +2186,27 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
- case ESCAPEI: {
- save_caller_save_regs(f, j);
-
- jit_operand_t args[2] = {
- jit_operand_imm(JIT_OPERAND_ABI_WORD,
- operands_len(&src) / 2),
- jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP)
- };
- compile_imm_call(j, &src, &dst, (void *)i.o, 2, args);
- restore_caller_save_regs(f, j);
-
- operands_reset(&src);
- operands_reset(&dst);
- operands_reset(&direct);
- break;
- }
+ case ESCAPEI_L:
+#if __WORDSIZE == 64
+ /* fallthrough */
+#else
+ assert(0 && "trying to compile escapei_l on 32bit arch");
+ break;
+#endif
- case ESCAPEI_F: {
+ case ESCAPEI_D:
+ case ESCAPEI_F:
+ case ESCAPEI_I: {
save_caller_save_regs(f, j);
jit_operand_t args[2] = {
jit_operand_imm(JIT_OPERAND_ABI_WORD,
operands_len(&src) / 2),
- jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP)
+ /* compile_imm_call populates JIT_R0 with the
+ * argument stack address */
+ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0)
};
- compile_imm_call(j, &src, &dst, (void *)i.o, 2, args);
+ compile_imm_call(j, &src, &dst, (void *)(uintptr_t)i.o, 2, args);
restore_caller_save_regs(f, j);
operands_reset(&src);
@@ -2106,10 +2215,21 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
break;
}
- case CALLI: {
+ case CALLI_L:
+#if __WORDSIZE == 64
+ call = ejit_run_func_l; goto calli;
+#else
+ assert(0 && "trying to compile calli_l on 32bit arch");
+ break;
+#endif
+
+ case CALLI_F: { call = ejit_run_func_f; goto calli; }
+ case CALLI_D: { call = ejit_run_func_d; goto calli; }
+ case CALLI_I: { call = ejit_run_func_i; goto calli;
+calli:
save_caller_save_regs(f, j);
- struct ejit_func *f = (struct ejit_func *)i.o;
+ struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o;
if (f && f->direct_call) {
jit_calli(j, f->direct_call, operands_len(&direct), direct.buf);
restore_caller_save_regs(f, j);
@@ -2124,9 +2244,11 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
jit_operand_imm(JIT_OPERAND_ABI_POINTER, i.o),
jit_operand_imm(JIT_OPERAND_ABI_WORD,
operands_len(&src) / 2),
- jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_SP)
+ /* compile_imm_call populates JIT_R0 with the
+ * argument stack address */
+ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0)
};
- compile_imm_call(j, &src, &dst, ejit_run_func, 3, args);
+ compile_imm_call(j, &src, &dst, call, 3, args);
restore_caller_save_regs(f, j);
operands_reset(&src);
@@ -2151,8 +2273,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
case RETR_F: {
jit_fpr_t r = getloc_f(f, j, i.r1, 0);
- /* convert float to double so the return types match */
- jit_extr_f_d(j, JIT_F0, r);
+ jit_movr_f(j, JIT_F0, r);
jit_shrink_stack(j, stack);
jit_leave_jit_abi(j, gprs, fprs, frame);
jit_retr_f(j, JIT_F0);
@@ -2319,7 +2440,10 @@ bool ejit_compile(struct ejit_func *f, bool use_64)
while (1) {
arena = alloc_arena(size);
- assert(arena);
+ if (arena == (void *)(-1)) {
+ jit_destroy_state(j);
+ return false;
+ }
size_t required_size = compile_fn_body(f, j, arena, size);
if (required_size == 0)
diff --git a/src/ejit.c b/src/ejit.c
index b0a0d51..660d476 100644
--- a/src/ejit.c
+++ b/src/ejit.c
@@ -1,4 +1,3 @@
-#include <math.h>
#include <assert.h>
#include <sys/mman.h>
@@ -6,6 +5,22 @@
#include "common.h"
+static void check_operands(struct ejit_func *f, size_t argc, const struct ejit_operand args[argc])
+{
+ assert(argc == types_len(&f->sign));
+ for (size_t i = 0; i < types_len(&f->sign); ++i) {
+ assert(args[i].type == *types_at(&f->sign, i));
+ }
+}
+
+static void check_args(struct ejit_func *f, size_t argc, const struct ejit_arg args[argc])
+{
+ assert(argc == types_len(&f->sign));
+ for (size_t i = 0; i < types_len(&f->sign); ++i) {
+ assert(args[i].type == *types_at(&f->sign, i));
+ }
+}
+
static struct gpr_stat zero_gpr_stat()
{
return (struct gpr_stat){
@@ -314,6 +329,7 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc,
f->rtype = rtype;
+ f->sign = types_create();
f->insns = insns_create();
f->labels = labels_create();
f->gpr = gpr_stats_create();
@@ -325,6 +341,8 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc,
f->use_64 = false;
for (size_t i = 0; i < argc; ++i) {
+ types_append(&f->sign, args[i].type);
+
switch (args[i].kind) {
case EJIT_OPERAND_GPR: {
assert(ejit_int_type(args[i].type));
@@ -373,10 +391,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 */
- if (ejit_float_type(f->rtype))
- ejit_run_interp_f(f, 0, NULL, NULL, false, &labels);
- else
- ejit_run_interp(f, 0, NULL, NULL, false, &labels);
+ ejit_run(f, 0, NULL, NULL, false, &labels);
foreach_vec(ii, f->insns) {
struct ejit_insn i = *insns_at(&f->insns, ii);
@@ -395,6 +410,7 @@ void ejit_destroy_func(struct ejit_func *f)
if (f->arena)
munmap(f->arena, f->size);
+ types_destroy(&f->sign);
insns_destroy(&f->insns);
labels_destroy(&f->labels);
gpr_stats_destroy(&f->gpr);
@@ -417,9 +433,82 @@ 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(struct ejit_func *s, struct ejit_func *f, size_t argc,
+void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc,
+ const struct ejit_operand args[argc])
+{
+ check_operands(f, argc, args);
+
+ for (size_t i = 0; i < argc; ++i) {
+ switch (args[i].kind) {
+ case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
+ case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
+ case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ default: abort();
+ }
+ }
+
+ emit_insn_op(s, 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;
+ check_operands(f, argc, args);
+
+ for (size_t i = 0; i < argc; ++i) {
+ switch (args[i].kind) {
+ case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
+ case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
+ case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ default: abort();
+ }
+ }
+
+ emit_insn_op(s, CALLI_L, f);
+}
+
+void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc,
const struct ejit_operand args[argc])
{
+ check_operands(f, argc, args);
+
+ for (size_t i = 0; i < argc; ++i) {
+ switch (args[i].kind) {
+ case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
+ case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
+ case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ default: abort();
+ }
+ }
+
+ emit_insn_op(s, CALLI_F, f);
+}
+
+void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc,
+ const struct ejit_operand args[argc])
+{
+ check_operands(f, argc, args);
+
+ for (size_t i = 0; i < argc; ++i) {
+ switch (args[i].kind) {
+ case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
+ case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
+ case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ default: abort();
+ }
+ }
+
+ emit_insn_op(s, CALLI_D, f);
+}
+
+void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc,
+ const struct ejit_operand args[argc])
+{
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
@@ -430,12 +519,13 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc,
}
}
- emit_insn_op(s, CALLI, f);
+ emit_insn_op(s, ESCAPEI_I, f);
}
-void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc,
+void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc,
const struct ejit_operand args[argc])
{
+ s->use_64 = true;
for (size_t i = 0; i < argc; ++i) {
switch (args[i].kind) {
case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
@@ -446,7 +536,7 @@ void ejit_escapei(struct ejit_func *s, ejit_escape_t f, size_t argc,
}
}
- emit_insn_op(s, ESCAPEI, f);
+ emit_insn_op(s, ESCAPEI_L, f);
}
void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc,
@@ -465,6 +555,22 @@ void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc,
emit_insn_op(s, ESCAPEI_F, f);
}
+void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc,
+ const struct ejit_operand args[argc])
+{
+ for (size_t i = 0; i < argc; ++i) {
+ switch (args[i].kind) {
+ case EJIT_OPERAND_GPR: emit_insn_ar(s, ARG, i, args[i].type, EJIT_GPR(args[i].r)); break;
+ case EJIT_OPERAND_FPR: emit_insn_af(s, ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break;
+ case EJIT_OPERAND_IMM: emit_insn_ai(s, ARG_I, i, args[i].type, args[i].r); break;
+ case EJIT_OPERAND_FLT: emit_insn_ad(s, ARG_FI, i, args[i].type, args[i].d); break;
+ default: abort();
+ }
+ }
+
+ emit_insn_op(s, ESCAPEI_D, f);
+}
+
void ejit_retval(struct ejit_func *s, struct ejit_gpr r0)
{
emit_insn_or(s, RETVAL, r0);
@@ -617,11 +723,13 @@ void ejit_ldi_u16(struct ejit_func *s, struct ejit_gpr r0, void *p)
void ejit_ldi_u32(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
+ s->use_64 = true;
emit_insn_orp(s, LDIU32, r0, p);
}
void ejit_ldi_u64(struct ejit_func *s, struct ejit_gpr r0, void *p)
{
+ s->use_64 = true;
emit_insn_orp(s, LDIU64, r0, p);
}
@@ -802,6 +910,7 @@ void ejit_extr_16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
void ejit_extr_32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
+ s->use_64 = true;
emit_insn_orr(s, EXTR32, r0, r1);
}
@@ -817,6 +926,7 @@ void ejit_extr_u16(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
void ejit_extr_u32(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1)
{
+ s->use_64 = true;
emit_insn_orr(s, EXTRU32, r0, r1);
}
@@ -883,7 +993,7 @@ void ejit_subr_d(struct ejit_func *s, struct ejit_fpr f0, struct ejit_fpr f1,
}
void ejit_subi(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1,
- long o)
+ int64_t o)
{
emit_insn_orri(s, SUBI, r0, r1, o);
}
@@ -1541,71 +1651,105 @@ static void destroy_interp_state(struct interp_state state)
args_destroy(&state.args);
}
-int64_t ejit_run_interp(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc],
- struct interp_state *state,
- bool run,
- void ***labels_wb)
+long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
{
- if (run) {
- assert(f->size && "trying to run a function that hasn't been compiled");
- assert(f->rtype == EJIT_VOID || ejit_int_type(f->rtype));
- if (f->arena)
- return ((ejit_escape_t)f->arena)(argc, args);
- }
+ check_args(f, argc, args);
+ assert((f->rtype == EJIT_VOID || ejit_int_type(f->rtype))
+#if __WORDSIZE != 64
+ && f->rtype != EJIT_INT64 && f->rtype != EJIT_UINT64
+#endif
+ );
- int64_t retval = 0; double retval_f = 0.0;
-#include "interp.inc"
- return retval;
+ return ejit_run(f, argc, args, ctx, true, NULL).i;
}
-double ejit_run_interp_f(struct ejit_func *f, size_t argc,
- struct ejit_arg args[argc],
- struct interp_state *state,
- bool run,
- void ***labels_wb)
+long ejit_run_func_i(struct ejit_func *f, size_t argc,
+ struct ejit_arg args[argc])
{
- if (run) {
- assert(f->size && "trying to run a function that hasn't been compiled");
- /* void functions should use ejit_run_interp */
- assert(ejit_float_type(f->rtype));
- if (f->arena)
- return ((ejit_escape_f_t)f->arena)(argc, args);
- }
+ struct interp_state state = create_interp_state();
+ long r = ejit_run_func_ctx_i(f, argc, args, &state);
+ destroy_interp_state(state);
+ return r;
+}
- int64_t retval = 0; double retval_f = 0.0;
-#include "interp.inc"
- return retval_f;
+int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+{
+ check_args(f, argc, args);
+ assert(f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64);
+ return ejit_run(f, argc, args, ctx, true, NULL).i;
}
-int64_t ejit_run_func(struct ejit_func *f, size_t argc,
+int64_t ejit_run_func_l(struct ejit_func *f, size_t argc,
struct ejit_arg args[argc])
{
- assert(f->size && "trying to run a function that hasn't been compiled");
- assert(f->rtype == EJIT_VOID || ejit_int_type(f->rtype));
- if (f->arena)
- return (int64_t)((ejit_escape_t)f->arena)(argc, args);
-
struct interp_state state = create_interp_state();
- long r = ejit_run_interp(f, argc, args, &state, true, NULL);
+ int64_t r = ejit_run_func_ctx_l(f, argc, args, &state);
destroy_interp_state(state);
return r;
}
-double ejit_run_func_f(struct ejit_func *f, size_t argc,
+float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+{
+ check_args(f, argc, args);
+ assert(f->rtype == EJIT_FLOAT);
+ return ejit_run(f, argc, args, ctx, true, NULL).f;
+}
+
+float ejit_run_func_f(struct ejit_func *f, size_t argc,
struct ejit_arg args[argc])
{
- assert(f->size && "trying to run a function that hasn't been compiled");
- assert(ejit_float_type(f->rtype));
- if (f->arena)
- return ((ejit_escape_f_t)f->arena)(argc, args);
+ struct interp_state state = create_interp_state();
+ float r = ejit_run_func_ctx_f(f, argc, args, &state);
+ destroy_interp_state(state);
+ return r;
+}
+
+double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx)
+{
+ check_args(f, argc, args);
+ assert(f->rtype == EJIT_DOUBLE);
+ return ejit_run(f, argc, args, ctx, true, NULL).f;
+}
+double ejit_run_func_d(struct ejit_func *f, size_t argc,
+ struct ejit_arg args[argc])
+{
struct interp_state state = create_interp_state();
- double r = ejit_run_interp_f(f, argc, args, &state, true, NULL);
+ double r = ejit_run_func_ctx_d(f, argc, args, &state);
destroy_interp_state(state);
return r;
}
+struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc])
+{
+ switch (f->rtype) {
+ case EJIT_DOUBLE:
+ return (struct ejit_arg){
+ .d = ejit_run_func_d(f, argc, args),
+ .type = EJIT_DOUBLE
+ };
+
+ case EJIT_FLOAT:
+ return (struct ejit_arg){
+ .f = ejit_run_func_f(f, argc, args),
+ .type = EJIT_FLOAT
+ };
+
+ case EJIT_UINT64:
+ case EJIT_INT64:
+ return (struct ejit_arg){
+ .i64 = ejit_run_func_l(f, argc, args),
+ .type = f->rtype
+ };
+
+ default:
+ return (struct ejit_arg){
+ .i64 = ejit_run_func_i(f, argc, args),
+ .type = f->rtype
+ };
+ }
+}
+
size_t ejit_get_prio(struct ejit_func *s)
{
return s->prio;
diff --git a/src/interp.inc b/src/interp.c
index a88bec8..f8ba927 100644
--- a/src/interp.inc
+++ b/src/interp.c
@@ -1,6 +1,11 @@
+#include <math.h>
+#include <stdio.h>
+#include "common.h"
+
/* this is the body of a given ejit_interp function, it assumes there's an
* external int64_t retval and double retval_f into which it places the value to
* be returned. Included from src/interp.c */
+union interp_ret ejit_run(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *state, bool run, void ***labels_wb)
{
static void *labels[OPCODE_COUNT] = {
[MOVI] = &&MOVI,
@@ -199,10 +204,14 @@
[PARAM] = &&PARAM,
[PARAM_F] = &&PARAM_F,
- [CALLI] = &&CALLI,
+ [CALLI_I] = &&CALLI_I,
+ [CALLI_L] = &&CALLI_L,
[CALLI_F] = &&CALLI_F,
- [ESCAPEI] = &&ESCAPEI,
+ [CALLI_D] = &&CALLI_D,
+ [ESCAPEI_I] = &&ESCAPEI_I,
[ESCAPEI_F] = &&ESCAPEI_F,
+ [ESCAPEI_L] = &&ESCAPEI_L,
+ [ESCAPEI_D] = &&ESCAPEI_D,
[START] = &&START,
[END] = &&END,
@@ -213,6 +222,31 @@
goto zero_out;
}
+ assert(f->size && "trying to run a function that hasn't been compiled");
+
+ if (f->arena) {
+ if (f->rtype == EJIT_INT64 || f->rtype == EJIT_UINT64)
+ return (union interp_ret){
+ .i = ((ejit_escape_l_t)f->arena)(argc, args)
+ };
+
+ if (f->rtype == EJIT_DOUBLE)
+ return (union interp_ret){
+ .f = ((ejit_escape_d_t)f->arena)(argc, args)
+ };
+
+ if (f->rtype == EJIT_FLOAT)
+ return (union interp_ret){
+ .f = ((ejit_escape_f_t)f->arena)(argc, args)
+ };
+
+ return (union interp_ret){
+ .i = ((ejit_escape_i_t)f->arena)(argc, args)
+ };
+ }
+
+ int64_t retval = 0; double retval_f = 0.0;
+
size_t prev_gprs = gprs_len(&state->gprs);
size_t prev_fprs = fprs_len(&state->fprs);
size_t prev_argc = args_len(&state->args);
@@ -224,7 +258,7 @@
double d;
float f;
};
- long *gpr = ((long *)state->gprs.buf) + prev_gprs;
+ int64_t *gpr = ((int64_t *)state->gprs.buf) + prev_gprs;
union fpr *fpr = ((union fpr *)state->fprs.buf) + prev_fprs;
struct ejit_insn *insns = f->insns.buf;
@@ -244,7 +278,7 @@
DISPATCH();
DO(END);
- goto out;
+ goto zero_out;
DISPATCH();
DO(MOVI);
@@ -530,62 +564,62 @@
DISPATCH();
DO(STXI8);
- int8_t *addr = (int8_t *)(gpr[i.r1] + i.o);
+ int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + i.o);
*addr = gpr[i.r0];
DISPATCH();
DO(STXI16);
- int16_t *addr = (int16_t *)(gpr[i.r1] + i.o);
+ int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + i.o);
*addr = gpr[i.r0];
DISPATCH();
DO(STXI32);
- int32_t *addr = (int32_t *)(gpr[i.r1] + i.o);
+ int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + i.o);
*addr = gpr[i.r0];
DISPATCH();
DO(STXI64);
- int64_t *addr = (int64_t *)(gpr[i.r1] + i.o);
+ int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + i.o);
*addr = gpr[i.r0];
DISPATCH();
DO(STXIF);
- float *addr = (float *)(gpr[i.r1] + i.o);
+ float *addr = (float *)(uintptr_t)(gpr[i.r1] + i.o);
*addr = fpr[i.r0].f;
DISPATCH();
DO(STXID);
- double *addr = (double *)(gpr[i.r1] + i.o);
+ double *addr = (double *)(uintptr_t)(gpr[i.r1] + i.o);
*addr = fpr[i.r0].d;
DISPATCH();
DO(STXR8);
- int8_t *addr = (int8_t *)(gpr[i.r1] + gpr[i.r2]);
+ int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
*addr = gpr[i.r0];
DISPATCH();
DO(STXR16);
- int16_t *addr = (int16_t *)(gpr[i.r1] + gpr[i.r2]);
+ int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
*addr = gpr[i.r0];
DISPATCH();
DO(STXR32);
- int32_t *addr = (int32_t *)(gpr[i.r1] + gpr[i.r2]);
+ int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
*addr = gpr[i.r0];
DISPATCH();
DO(STXR64);
- int64_t *addr = (int64_t *)(gpr[i.r1] + gpr[i.r2]);
+ int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
*addr = gpr[i.r0];
DISPATCH();
DO(STXRF);
- float *addr = (float *)(gpr[i.r1] + gpr[i.r2]);
+ float *addr = (float *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
*addr = fpr[i.r0].f;
DISPATCH();
DO(STXRD);
- double *addr = (double *)(gpr[i.r1] + gpr[i.r2]);
+ double *addr = (double *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
*addr = fpr[i.r0].d;
DISPATCH();
@@ -640,102 +674,102 @@
DISPATCH();
DO(LDXI8);
- int8_t *addr = (int8_t *)(gpr[i.r1] + i.o);
+ int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXI16);
- int16_t *addr = (int16_t *)(gpr[i.r1] + i.o);
+ int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXI32);
- int32_t *addr = (int32_t *)(gpr[i.r1] + i.o);
+ int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXI64);
- int64_t *addr = (int64_t *)(gpr[i.r1] + i.o);
+ int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXIU8);
- uint8_t *addr = (uint8_t *)(gpr[i.r1] + i.o);
+ uint8_t *addr = (uint8_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXIU16);
- uint16_t *addr = (uint16_t *)(gpr[i.r1] + i.o);
+ uint16_t *addr = (uint16_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXIU32);
- uint32_t *addr = (uint32_t *)(gpr[i.r1] + i.o);
+ uint32_t *addr = (uint32_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXIU64);
- uint64_t *addr = (uint64_t *)(gpr[i.r1] + i.o);
+ uint64_t *addr = (uint64_t *)(uintptr_t)(gpr[i.r1] + i.o);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXIF);
- float *addr = (float *)(gpr[i.r1] + i.o);
+ float *addr = (float *)(uintptr_t)(gpr[i.r1] + i.o);
fpr[i.r0].f = *addr;
DISPATCH();
DO(LDXID);
- double *addr = (double *)(gpr[i.r1] + i.o);
+ double *addr = (double *)(uintptr_t)(gpr[i.r1] + i.o);
fpr[i.r0].d = *addr;
DISPATCH();
DO(LDXR8);
- int8_t *addr = (int8_t *)(gpr[i.r1] + gpr[i.r2]);
+ int8_t *addr = (int8_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXR16);
- int16_t *addr = (int16_t *)(gpr[i.r1] + gpr[i.r2]);
+ int16_t *addr = (int16_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXR32);
- int32_t *addr = (int32_t *)(gpr[i.r1] + gpr[i.r2]);
+ int32_t *addr = (int32_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXR64);
- int64_t *addr = (int64_t *)(gpr[i.r1] + gpr[i.r2]);
+ int64_t *addr = (int64_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXRU8);
- uint8_t *addr = (uint8_t *)(gpr[i.r1] + gpr[i.r2]);
+ uint8_t *addr = (uint8_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXRU16);
- uint16_t *addr = (uint16_t *)(gpr[i.r1] + gpr[i.r2]);
+ uint16_t *addr = (uint16_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXRU32);
- uint32_t *addr = (uint32_t *)(gpr[i.r1] + gpr[i.r2]);
+ uint32_t *addr = (uint32_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXRU64);
- uint64_t *addr = (uint64_t *)(gpr[i.r1] + gpr[i.r2]);
+ uint64_t *addr = (uint64_t *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
gpr[i.r0] = *addr;
DISPATCH();
DO(LDXRF);
- float *addr = (float *)(gpr[i.r1] + gpr[i.r2]);
+ float *addr = (float *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
fpr[i.r0].f = *addr;
DISPATCH();
DO(LDXRD);
- double *addr = (double *)(gpr[i.r1] + gpr[i.r2]);
+ double *addr = (double *)(uintptr_t)(gpr[i.r1] + gpr[i.r2]);
fpr[i.r0].d = *addr;
DISPATCH();
@@ -985,37 +1019,68 @@
args_append(&state->args, a);
DISPATCH();
- DO(CALLI);
+ DO(CALLI_I);
+ struct ejit_func *f = i.p;
+ size_t argc = args_len(&state->args) - prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
+
+ retval = ejit_run(f, argc, args, state, true, NULL).i;
+
+ gpr = state->gprs.buf + prev_gprs;
+ fpr = (union fpr *)state->fprs.buf + prev_fprs;
+ args_shrink(&state->args, prev_argc);
+ DISPATCH();
+
+ DO(CALLI_L);
struct ejit_func *f = i.p;
size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) +
- prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
- retval = ejit_run_interp(f, argc, args, state, true, NULL);
+ retval = ejit_run(f, argc, args, state, true, NULL).i;
- gpr = ((long *)state->gprs.buf) + prev_gprs;
- fpr = ((union fpr *)state->fprs.buf) + prev_fprs;
+ gpr = state->gprs.buf + prev_gprs;
+ fpr = (union fpr *)state->fprs.buf + prev_fprs;
args_shrink(&state->args, prev_argc);
DISPATCH();
DO(CALLI_F);
struct ejit_func *f = i.p;
size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) +
- prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
- retval_f = ejit_run_interp_f(f, argc, args, state, true, NULL);
+ retval_f = ejit_run(f, argc, args, state, true, NULL).f;
- gpr = ((long *)state->gprs.buf) + prev_gprs;
- fpr = ((union fpr *)state->fprs.buf) + prev_fprs;
+ gpr = state->gprs.buf + prev_gprs;
+ fpr = (union fpr *)state->fprs.buf + prev_fprs;
args_shrink(&state->args, prev_argc);
DISPATCH();
- DO(ESCAPEI);
- ejit_escape_t f = i.p;
+ DO(CALLI_D);
+ struct ejit_func *f = i.p;
size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) +
- prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
+
+ retval_f = ejit_run(f, argc, args, state, true, NULL).f;
+
+ gpr = state->gprs.buf + prev_gprs;
+ fpr = (union fpr *)state->fprs.buf + prev_fprs;
+ args_shrink(&state->args, prev_argc);
+ DISPATCH();
+
+ DO(ESCAPEI_I);
+ ejit_escape_i_t f = i.p;
+ size_t argc = args_len(&state->args) - prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
+
+ retval = f(argc, args);
+
+ args_shrink(&state->args, prev_argc);
+ DISPATCH();
+
+ DO(ESCAPEI_L);
+ ejit_escape_l_t f = i.p;
+ size_t argc = args_len(&state->args) - prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
retval = f(argc, args);
@@ -1025,8 +1090,17 @@
DO(ESCAPEI_F);
ejit_escape_f_t f = i.p;
size_t argc = args_len(&state->args) - prev_argc;
- struct ejit_arg *args = ((struct ejit_arg *)state->args.buf) +
- prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
+
+ retval_f = f(argc, args);
+
+ args_shrink(&state->args, prev_argc);
+ DISPATCH();
+
+ DO(ESCAPEI_D);
+ ejit_escape_d_t f = i.p;
+ size_t argc = args_len(&state->args) - prev_argc;
+ struct ejit_arg *args = state->args.buf + prev_argc;
retval_f = f(argc, args);
@@ -1037,41 +1111,48 @@
* symmetry */
DO(RETR);
retval = gpr[i.r1];
- goto out;
+ goto out_int;
DISPATCH();
DO(RETI);
retval = i.o;
- goto out;
+ goto out_int;
DISPATCH();
DO(RETR_F);
retval_f = fpr[i.r1].f;
- goto out;
+ goto out_float;
DISPATCH();
DO(RETR_D);
retval_f = fpr[i.r1].d;
- goto out;
+ goto out_float;
DISPATCH();
DO(RETI_F);
retval_f = i.f;
- goto out;
+ goto out_float;
DISPATCH();
DO(RETI_D);
retval_f = i.d;
- goto out;
+ goto out_float;
DISPATCH();
#undef DISPATCH
#undef JUMP
#undef DO
-out:
+out_float:
+ gprs_shrink(&state->gprs, prev_gprs);
+ fprs_shrink(&state->fprs, prev_fprs);
+ return (union interp_ret){.f = retval_f};
+
+out_int:
gprs_shrink(&state->gprs, prev_gprs);
fprs_shrink(&state->fprs, prev_fprs);
+ return (union interp_ret){.i = retval};
zero_out:
+ return (union interp_ret){.i = 0};
}
diff --git a/src/vec.h b/src/vec.h
index f982bac..f5a6fd9 100644
--- a/src/vec.h
+++ b/src/vec.h
@@ -73,6 +73,7 @@ static inline void VEC(append)(struct VEC_STRUCT *v, VEC_TYPE n)
if (v->n >= v->s) {
v->s *= 2;
v->buf = realloc(v->buf, v->s * sizeof(VEC_TYPE));
+ assert(v->buf);
}
v->buf[v->n - 1] = n;
@@ -99,6 +100,9 @@ static inline void VEC(reserve)(struct VEC_STRUCT *v, size_t n)
return;
v->n = n;
+ if (v->s >= v->n)
+ return;
+
while (v->s < v->n)
v->s *= 2;