aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------deps/conts0
-rw-r--r--scripts/makefile10
-rw-r--r--src/compile/compile.c107
-rw-r--r--src/interp.c14
-rw-r--r--tests/makefile5
-rw-r--r--tests/z_double_label.c38
6 files changed, 127 insertions, 47 deletions
diff --git a/deps/conts b/deps/conts
-Subproject 5a4cb1b5a8ba258a23a62feab1e66cc7d0eba3b
+Subproject 4670112f63966ac6d4c1d1894341b67fee931a3
diff --git a/scripts/makefile b/scripts/makefile
index 6e3b972..39ac062 100644
--- a/scripts/makefile
+++ b/scripts/makefile
@@ -6,12 +6,8 @@ OPTFLAGS != [ "$(RELEASE)" != "0" ] \
LTO ?= 0
LTOFLAGS != [ "$(LTO)" != "0" ] \
- && echo "-flto=auto"
-
-DEBUG ?= 1
-DEBUGFLAGS != [ "$(DEBUG)" != "0" ] \
- && echo "-DDEBUG=1" \
- || echo "-DNDEBUG=1"
+ && echo "-flto=auto" \
+ || echo
DEPFLAGS = -MT $@ -MMD -MP -MF $@.d
LINTFLAGS := -fsyntax-only
@@ -43,7 +39,7 @@ OBFLAGS := -g
WARNFLAGS := -Wall -Wextra
COMPILE_FLAGS := $(CFLAGS) $(WARNFLAGS) $(OPTFLAGS) $(LTOFLAGS) \
- $(OBFLAGS) $(DEBUGFLAGS)
+ $(OBFLAGS)
INCLUDE_FLAGS := -I include -I deps/conts/include
diff --git a/src/compile/compile.c b/src/compile/compile.c
index 8e0e250..7965f93 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -47,7 +47,7 @@ static void *alloc_arena(size_t size, bool im_scawed)
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
-static void assert_helper(const char *msg)
+static inline void assert_helper(const char *msg)
{
assert(false && msg);
}
@@ -1974,6 +1974,10 @@ static void resolve_top_reloc(jit_state_t *j, struct relocs *relocs, struct addr
assert(a);
jit_patch_there(j, r, a);
relocs_pop(relocs);
+
+ /* hope this turns into a tailcall */
+ if (relocs_len(relocs))
+ resolve_top_reloc(j, relocs, addrs, ii);
}
static void resolve_relocs(jit_state_t *j, struct relocs *relocs, struct addrs *addrs, size_t ii)
@@ -2066,12 +2070,11 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
size_t label = 0;
for (size_t ii = 0; ii < insns_len(&f->insns); ++ii) {
/* if we've hit a label, add it to our vector of label addresses */
- if (label < labels_len(&f->labels)) {
- if (*labels_at(&f->labels, label) == ii) {
- compile_label(j, ii, &addrs);
- resolve_relocs(j, &relocs, &addrs, ii);
- label++;
- }
+ while (label < labels_len(&f->labels)
+ && *labels_at(&f->labels, label) == ii) {
+ compile_label(j, ii, &addrs);
+ resolve_relocs(j, &relocs, &addrs, ii);
+ label++;
}
struct ejit_insn i = *insns_at(&f->insns, ii);
@@ -2668,13 +2671,12 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
case EJIT_OP_CALLI: {
save_caller_save_regs(f, j);
-
- struct ejit_func *f = (struct ejit_func *)i.p;
+ struct ejit_func *t = (struct ejit_func *)i.p;
#if __WORDSIZE != 64
- assert(f->rtype != EJIT_INT64 && f->rtype != EJIT_UINT64);
+ assert(t->rtype != EJIT_INT64 && t->rtype != EJIT_UINT64);
#endif
- if (f && f->direct_call) {
- jit_calli(j, f->direct_call, operands_len(&direct), direct.buf);
+ if (t && t->direct_call) {
+ jit_calli(j, t->direct_call, operands_len(&direct), direct.buf);
restore_caller_save_regs(f, j);
operands_reset(&src);
@@ -2693,7 +2695,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
};
void *call = NULL;
- switch (f->rtype) {
+ switch (t->rtype) {
case EJIT_INT64:
case EJIT_UINT64: call = checked_run_l; break;
case EJIT_FLOAT: call = checked_run_f; break;
@@ -2865,7 +2867,27 @@ static int barrier_sort(struct barrier_tuple *a, struct barrier_tuple *b)
if (a->start > b->start)
return 1;
- return a->end - b->end;
+ if (a->end < b->end)
+ return -1;
+
+ return 1;
+}
+
+/* sort gprs in order of starting address */
+static int gpr_start_sort(struct gpr_stat *a, struct gpr_stat *b)
+{
+ if (a->start < b->start)
+ return -1;
+
+ return 1;
+}
+
+static int fpr_start_sort(struct fpr_stat *a, struct fpr_stat *b)
+{
+ if (a->start < b->start)
+ return -1;
+
+ return 1;
}
/* slightly more parameters than I would like but I guess it's fine */
@@ -2977,7 +2999,15 @@ static void assign_gprs(struct ejit_func *f)
if (gpr_stats_len(&f->gpr) <= physgpr_count())
return linear_gpr_alloc(f);
- struct alive alive = alive_create(gpr_stats_len(&f->gpr));
+ /* create temporary buffer to sort */
+ struct gpr_stats gprs = gpr_stats_create(gpr_stats_len(&f->gpr));
+ foreach(gpr_stats, g, &f->gpr) {
+ gpr_stats_append(&gprs, *g);
+ }
+
+ gpr_stats_sort(&gprs, gpr_start_sort);
+
+ struct alive alive = alive_create(gpr_stats_len(&gprs));
/* special oneshot register class */
struct alive_slot a = {.r = -1, .cost = 0, .idx = 0};
@@ -2987,8 +3017,10 @@ static void assign_gprs(struct ejit_func *f)
* dealing with. Since register start addresses grow upward, we can
* fairly easily keep track of which barrier a register cannot cross */
size_t bi = 0;
- for (size_t gi = 0; gi < gpr_stats_len(&f->gpr); ++gi) {
- struct gpr_stat *gpr = gpr_stats_at(&f->gpr, gi);
+ for (size_t gi = 0; gi < gpr_stats_len(&gprs); ++gi) {
+ struct gpr_stat *gpr = gpr_stats_at(&gprs, gi);
+ if (gpr->prio == 0)
+ continue;
extend_gpr_lifetime(gpr, &f->barriers, bi);
if (bi < barriers_len(&f->barriers)) {
@@ -2999,7 +3031,7 @@ static void assign_gprs(struct ejit_func *f)
calculate_alive(&alive, gi,
gpr->prio, gpr->start, gpr->end, &gpr->rno,
- &f->gpr, gpr_dead);
+ &gprs, gpr_dead);
}
/* sort so that the highest spill cost register classes are at the front and
@@ -3013,13 +3045,18 @@ static void assign_gprs(struct ejit_func *f)
}
/* remap locations */
- for (size_t i = 0; i < gpr_stats_len(&f->gpr); ++i) {
- struct gpr_stat *gpr = gpr_stats_at(&f->gpr, i);
+ for (size_t i = 0; i < gpr_stats_len(&gprs); ++i) {
+ struct gpr_stat *gpr = gpr_stats_at(&gprs, i);
+ if (gpr->prio == 0)
+ continue;
+
struct alive_slot *a = alive_at(&alive, gpr->rno);
- gpr->rno = a->remap;
+ struct gpr_stat *orig = gpr_stats_at(&f->gpr, gpr->r.r);
+ orig->rno = a->remap;
}
alive_destroy(&alive);
+ gpr_stats_destroy(&gprs);
}
static int fpr_dead(void *regs, size_t idx, size_t start)
@@ -3041,6 +3078,13 @@ static void assign_fprs(struct ejit_func *f)
if (fpr_stats_len(&f->fpr) <= physfpr_count())
return linear_fpr_alloc(f);
+ struct fpr_stats fprs = fpr_stats_create(fpr_stats_len(&f->fpr));
+ foreach(fpr_stats, r, &f->fpr) {
+ fpr_stats_append(&fprs, *r);
+ }
+
+ fpr_stats_sort(&fprs, fpr_start_sort);
+
struct alive alive = alive_create(fpr_stats_len(&f->fpr));
/* special oneshot register class */
@@ -3048,8 +3092,10 @@ static void assign_fprs(struct ejit_func *f)
alive_append(&alive, a);
size_t bi = 0;
- for (size_t fi = 0; fi < fpr_stats_len(&f->fpr); ++fi) {
- struct fpr_stat *fpr = fpr_stats_at(&f->fpr, fi);
+ for (size_t fi = 0; fi < fpr_stats_len(&fprs); ++fi) {
+ struct fpr_stat *fpr = fpr_stats_at(&fprs, fi);
+ if (fpr->prio == 0)
+ continue;
extend_fpr_lifetime(fpr, &f->barriers, bi);
if (bi < barriers_len(&f->barriers)) {
@@ -3060,7 +3106,7 @@ static void assign_fprs(struct ejit_func *f)
calculate_alive(&alive, fi,
fpr->prio, fpr->start, fpr->end, &fpr->fno,
- &f->fpr, fpr_dead);
+ &fprs, fpr_dead);
}
/* sort so that the highest spill cost register classes are at the front and
@@ -3074,13 +3120,18 @@ static void assign_fprs(struct ejit_func *f)
}
/* remap locations */
- for (size_t i = 0; i < fpr_stats_len(&f->fpr); ++i) {
- struct fpr_stat *fpr = fpr_stats_at(&f->fpr, i);
+ for (size_t i = 0; i < fpr_stats_len(&fprs); ++i) {
+ struct fpr_stat *fpr = fpr_stats_at(&fprs, i);
+ if (fpr->prio == 0)
+ continue;
+
struct alive_slot *a = alive_at(&alive, fpr->fno);
- fpr->fno = a->remap;
+ struct fpr_stat *orig = fpr_stats_at(&f->fpr, fpr->f.f);
+ orig->fno = a->remap;
}
alive_destroy(&alive);
+ fpr_stats_destroy(&fprs);
}
static size_t align_up(size_t a, size_t n)
@@ -3102,7 +3153,7 @@ bool ejit_compile(struct ejit_func *f, bool use_64, bool im_scawed)
if (!init_jit())
return false;
- /* sort barriers so they can be used to extend register life times in
+ /* sort barriers so they can be used to extend register lifetimes in
* loops */
barriers_sort(&f->barriers, barrier_sort);
assign_gprs(f);
diff --git a/src/interp.c b/src/interp.c
index 894be30..7fdd4b1 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -258,7 +258,7 @@ union interp_ret ejit_run(struct ejit_func *f, size_t paramc, struct ejit_arg pa
};
}
-top:
+top:;
union interp_ret retval = {.i = 0};
union fpr {
double d;
@@ -1019,7 +1019,7 @@ top:
case EJIT_UINT16: gpr[i.r2] = params[i.r0].u16; break;
case EJIT_UINT32: gpr[i.r2] = params[i.r0].u32; break;
case EJIT_UINT64: gpr[i.r2] = params[i.r0].u64; break;
- case EJIT_POINTER: gpr[i.r2] = (int64_t)params[i.r0].p; break;
+ case EJIT_POINTER: gpr[i.r2] = (int64_t)(intptr_t)params[i.r0].p; break;
default: abort();
}
DISPATCH();
@@ -1075,7 +1075,7 @@ top:
DISPATCH();
DO(TAILR);
- f = (struct ejit_func *)gpr[i.r1];
+ f = (struct ejit_func *)(intptr_t)gpr[i.r1];
/** @todo we could potentially just interpret the func as a fallback
* instead of aborting here, but this is good enough for now */
@@ -1089,22 +1089,22 @@ top:
DISPATCH();
DO(CALLR_I);
- retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ retval = ejit_run((struct ejit_func *)(intptr_t)gpr[i.r1], argc, args, NULL);
argc = 0;
DISPATCH();
DO(CALLR_L);
- retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ retval = ejit_run((struct ejit_func *)(intptr_t)gpr[i.r1], argc, args, NULL);
argc = 0;
DISPATCH();
DO(CALLR_F);
- retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ retval = ejit_run((struct ejit_func *)(intptr_t)gpr[i.r1], argc, args, NULL);
argc = 0;
DISPATCH();
DO(CALLR_D);
- retval = ejit_run((struct ejit_func *)gpr[i.r1], argc, args, NULL);
+ retval = ejit_run((struct ejit_func *)(intptr_t)gpr[i.r1], argc, args, NULL);
argc = 0;
DISPATCH();
diff --git a/tests/makefile b/tests/makefile
index 53115de..2328d0e 100644
--- a/tests/makefile
+++ b/tests/makefile
@@ -19,11 +19,6 @@ LTO ?= 0
LTOFLAGS != [ "$(LTO)" != "0" ] \
&& echo "-flto=auto"
-DEBUG ?= 1
-DEBUGFLAGS != [ "$(DEBUG)" != "0" ] \
- && echo "-DDEBUG=1" \
- || echo "-DNDEBUG=1"
-
OBFLAGS := -g
WARNFLAGS := -Wall -Wextra
INCLUDE_FLAGS := -I include
diff --git a/tests/z_double_label.c b/tests/z_double_label.c
new file mode 100644
index 0000000..4817d8c
--- /dev/null
+++ b/tests/z_double_label.c
@@ -0,0 +1,38 @@
+#include <ejit/ejit.h>
+#include <assert.h>
+#include "do_jit.h"
+
+int main(int argc, char *argv[])
+{
+ (void)argv;
+ bool do_jit = argc > 1;
+ struct ejit_func *f = ejit_create_func(EJIT_INT32, 0, NULL);
+ ejit_movi(f, EJIT_GPR(0), 0);
+
+ struct ejit_reloc l1 = ejit_jmp(f);
+ struct ejit_label mid = ejit_label(f);
+ struct ejit_reloc l2 = ejit_jmp(f);
+
+ /* patch relocs to same address with two separate labels. */
+ ejit_patch(f, l1, ejit_label(f));
+ ejit_patch(f, l2, ejit_label(f));
+
+ /* we came from the first jump, jump to the end */
+ struct ejit_reloc end = ejit_beqi(f, EJIT_GPR(0), 1);
+
+ /* set r0 to 1 to indicate that we've done the first jump */
+ ejit_movi(f, EJIT_GPR(0), 1);
+
+ /* jump in between the two jumps */
+ ejit_patch(f, ejit_jmp(f), mid);
+
+ ejit_patch(f, end, ejit_label(f));
+ ejit_reti(f, 0);
+
+
+ ejit_select_compile_func(f, 1, 0, false, do_jit, true);
+
+ assert(ejit_run_func_i(f, 0, NULL) == 0);
+
+ ejit_destroy_func(f);
+}