diff options
Diffstat (limited to 'src/compile/compile.c')
-rw-r--r-- | src/compile/compile.c | 244 |
1 files changed, 206 insertions, 38 deletions
diff --git a/src/compile/compile.c b/src/compile/compile.c index 3b5399a..38c368f 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -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); |