aboutsummaryrefslogtreecommitdiff
path: root/src/compile/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compile/compile.c')
-rw-r--r--src/compile/compile.c248
1 files changed, 208 insertions, 40 deletions
diff --git a/src/compile/compile.c b/src/compile/compile.c
index dac8dfd..38c368f 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -1927,7 +1927,7 @@ static void compile_trampoline(struct ejit_func *f, jit_state_t *j)
jit_leave_jit_abi(j, 0, 0, frame);
jit_ret(j); /* should just forward the return value */
- f->direct_call = jit_address(j);
+ f->direct_call = jit_address_to_function_pointer(jit_address(j));
jit_patch_here(j, r);
operands_destroy(&args);
@@ -1939,6 +1939,44 @@ static void compile_trampoline(struct ejit_func *f, jit_state_t *j)
}
}
+static void resolve_top_reloc(jit_state_t *j, struct relocs *relocs, struct addrs *addrs, size_t ii)
+{
+ assert(relocs_len(relocs) != 0);
+
+ struct reloc_helper h = *relocs_back(relocs);
+ if (h.to >= ii)
+ return;
+
+ jit_addr_t a = *addrs_at(addrs, h.to);
+ jit_reloc_t r = h.r;
+
+ assert(a);
+ jit_patch_there(j, r, a);
+ relocs_pop(relocs);
+}
+
+static void resolve_relocs(jit_state_t *j, struct relocs *relocs, struct addrs *addrs, size_t ii)
+{
+ foreach_vec(ri, *relocs) {
+ struct reloc_helper h = *relocs_at(relocs, ri);
+ if (h.to != ii)
+ continue;
+
+ jit_addr_t a = *addrs_at(addrs, ii);
+ jit_reloc_t r = h.r;
+
+ assert(a);
+ jit_patch_there(j, r, a);
+
+ /* 'shift' down */
+ if (ri != relocs_len(relocs) - 1)
+ *relocs_at(relocs, ri) = *relocs_back(relocs);
+
+ assert(relocs_len(relocs) != 0);
+ relocs_shrink(relocs, relocs_len(relocs) - 1);
+ }
+}
+
static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
size_t size)
{
@@ -1960,7 +1998,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
struct operands dst = operands_create();
struct operands direct = operands_create();
- struct relocs relocs = relocs_create(sizeof(struct reloc_helper));
+ struct relocs relocs = relocs_create();
struct addrs addrs = addrs_create();
addrs_reserve(&addrs, insns_len(&f->insns));
@@ -1972,6 +2010,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
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++;
}
}
@@ -2122,43 +2161,179 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
case EJIT_OP_GTR_F: compile_gtr_f(f, j, i); break;
case EJIT_OP_GTR_D: compile_gtr_d(f, j, i); break;
- case EJIT_OP_BMCI: compile_bmci(f, j, i, &relocs); break;
- case EJIT_OP_BMCR: compile_bmcr(f, j, i, &relocs); break;
+ case EJIT_OP_BMCI: {
+ compile_bmci(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BMCR: {
+ compile_bmcr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BMSI: {
+ compile_bmsi(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BMSR: {
+ compile_bmsr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQR: {
+ compile_beqr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQI: {
+ compile_beqi(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQR_F: {
+ compile_beqr_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BEQR_D: {
+ compile_beqr_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNER: {
+ compile_bner(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNEI: {
+ compile_bnei(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNER_F: {
+ compile_bner_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BNER_D: {
+ compile_bner_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BMSI: compile_bmsi(f, j, i, &relocs); break;
- case EJIT_OP_BMSR: compile_bmsr(f, j, i, &relocs); break;
+ case EJIT_OP_BGER: {
+ compile_bger(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BEQR: compile_beqr(f, j, i, &relocs); break;
- case EJIT_OP_BEQI: compile_beqi(f, j, i, &relocs); break;
- case EJIT_OP_BEQR_F: compile_beqr_f(f, j, i, &relocs); break;
- case EJIT_OP_BEQR_D: compile_beqr_d(f, j, i, &relocs); break;
+ case EJIT_OP_BGER_U: {
+ compile_bger_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGEI: {
+ compile_bgei(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGEI_U: {
+ compile_bgei_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BNER: compile_bner(f, j, i, &relocs); break;
- case EJIT_OP_BNEI: compile_bnei(f, j, i, &relocs); break;
- case EJIT_OP_BNER_F: compile_bner_f(f, j, i, &relocs); break;
- case EJIT_OP_BNER_D: compile_bner_d(f, j, i, &relocs); break;
+ case EJIT_OP_BGER_F: {
+ compile_bger_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BGER: compile_bger(f, j, i, &relocs); break;
- case EJIT_OP_BGER_U: compile_bger_u(f, j, i, &relocs); break;
- case EJIT_OP_BGEI: compile_bgei(f, j, i, &relocs); break;
- case EJIT_OP_BGEI_U: compile_bgei_u(f, j, i, &relocs); break;
- case EJIT_OP_BGER_F: compile_bger_f(f, j, i, &relocs); break;
- case EJIT_OP_BGER_D: compile_bger_d(f, j, i, &relocs); break;
+ case EJIT_OP_BGER_D: {
+ compile_bger_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BGTR: compile_bgtr(f, j, i, &relocs); break;
- case EJIT_OP_BGTR_U: compile_bgtr_u(f, j, i, &relocs); break;
- case EJIT_OP_BGTI: compile_bgti(f, j, i, &relocs); break;
- case EJIT_OP_BGTI_U: compile_bgti_u(f, j, i, &relocs); break;
- case EJIT_OP_BGTR_F: compile_bgtr_f(f, j, i, &relocs); break;
- case EJIT_OP_BGTR_D: compile_bgtr_d(f, j, i, &relocs); break;
+ case EJIT_OP_BGTR: {
+ compile_bgtr(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BLEI: compile_blei(f, j, i, &relocs); break;
- case EJIT_OP_BLEI_U: compile_blei_u(f, j, i, &relocs); break;
+ case EJIT_OP_BGTR_U: {
+ compile_bgtr_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_BLTI: compile_blti(f, j, i, &relocs); break;
- case EJIT_OP_BLTI_U: compile_blti_u(f, j, i, &relocs); break;
+ case EJIT_OP_BGTI: {
+ compile_bgti(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
- case EJIT_OP_JMP: compile_jmp(f, j, i, &relocs); break;
+ case EJIT_OP_BGTI_U: {
+ compile_bgti_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGTR_F: {
+ compile_bgtr_f(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BGTR_D: {
+ compile_bgtr_d(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BLEI: {
+ compile_blei(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BLEI_U: {
+ compile_blei_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BLTI: {
+ compile_blti(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_BLTI_U: {
+ compile_blti_u(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
+
+ case EJIT_OP_JMP: {
+ compile_jmp(f, j, i, &relocs);
+ resolve_top_reloc(j, &relocs, &addrs, ii);
+ break;
+ }
case EJIT_OP_ARG_I: {
jit_operand_t type = jit_operand_imm(JIT_OPERAND_ABI_WORD, i.r1);
@@ -2420,14 +2595,7 @@ calli:
}
}
- foreach_vec(ri, relocs) {
- struct reloc_helper h = *relocs_at(&relocs, ri);
- jit_addr_t a = *addrs_at(&addrs, h.to);
- jit_reloc_t r = h.r;
-
- assert(a);
- jit_patch_there(j, r, a);
- }
+ assert(relocs_len(&relocs) == 0);
operands_destroy(&src);
operands_destroy(&dst);
@@ -2435,7 +2603,7 @@ calli:
relocs_destroy(&relocs);
addrs_destroy(&addrs);
- if (jit_end(j, &size))
+ if ((f->extern_call = jit_end(j, &size)))
return 0;
return size;