From 0c6f675c8a026826b2482db9f978d422ef1f5328 Mon Sep 17 00:00:00 2001 From: pcpa Date: Fri, 24 Oct 2014 14:31:41 -0200 Subject: [PATCH] Properly handle jit_tramp and function descriptors * lib/jit_ia64.c, lib/jit_ppc.c: Correct handling of function descriptor when first prolog is a jit_tramp prolog. The test case was using the same jit_context_t, so was not triggering this condition. * lib/jit_ppc-cpu.c: Properly handle jump displacements that do not fit on 24 powerpc. This required changing from previous "mtlr reg, blr" to "mtctr reg, bctr" to properly handle the logic to "hide" function descriptors, but that would also be required as the proper jit_jmpr when/if implementing optimizations to leaf functions (was working with blr because it is saved/reloaded in prolog/epilog). --- ChangeLog | 15 +++++++++++++ lib/jit_ia64.c | 16 +++++++++---- lib/jit_ppc-cpu.c | 57 ++++++++++++++++++++++++++++++++++++++++++++--- lib/jit_ppc.c | 20 ++++++++++++----- 4 files changed, 95 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 85804e673..25583956f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2014-10-24 Paulo Andrade + + * lib/jit_ia64.c, lib/jit_ppc.c: Correct handling of function + descriptor when first prolog is a jit_tramp prolog. The + test case was using the same jit_context_t, so was not + triggering this condition. + + * lib/jit_ppc-cpu.c: Properly handle jump displacements that + do not fit on 24 powerpc. This required changing from previous + "mtlr reg, blr" to "mtctr reg, bctr" to properly handle + the logic to "hide" function descriptors, but that would + also be required as the proper jit_jmpr when/if implementing + optimizations to leaf functions (was working with blr because + it is saved/reloaded in prolog/epilog). + 2014-10-21 Paulo Andrade * include/lightning.h, lib/lightning.c: Add three predicates diff --git a/lib/jit_ia64.c b/lib/jit_ia64.c index f35f396dc..e3c655449 100644 --- a/lib/jit_ia64.c +++ b/lib/jit_ia64.c @@ -762,10 +762,18 @@ _emit_code(jit_state_t *_jit) undo.patch_offset = 0; undo.prolog_offset = 0; - /* code may start with a jump so add an initial function descriptor */ - word = _jit->pc.w + 16; - il(word); /* addr */ - il(0); /* gp */ + for (node = _jitc->head; node; node = node->next) + if (node->code != jit_code_label && + node->code != jit_code_note && + node->code != jit_code_name) + break; + if (node && (node->code != jit_code_prolog || + !(_jitc->functions.ptr + node->w.w)->assume_frame)) { + /* code may start with a jump so add an initial function descriptor */ + word = _jit->pc.w + 16; + il(word); /* addr */ + il(0); /* gp */ + } #define case_rr(name, type) \ case jit_code_##name##r##type: \ name##r##type(rn(node->u.w), rn(node->v.w)); \ diff --git a/lib/jit_ppc-cpu.c b/lib/jit_ppc-cpu.c index 2f65d36b5..18f40968f 100644 --- a/lib/jit_ppc-cpu.c +++ b/lib/jit_ppc-cpu.c @@ -2985,8 +2985,13 @@ _stxi_l(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1) static void _jmpr(jit_state_t *_jit, jit_int32_t r0) { +#if 0 MTLR(r0); BLR(); +#else + MTCTR(r0); + BCTR(); +#endif } /* pc relative jump */ @@ -2995,11 +3000,16 @@ _jmpi(jit_state_t *_jit, jit_word_t i0) { jit_int32_t reg; jit_word_t w, d; - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); w = _jit->pc.w; d = (i0 - w) & ~3; - B(d); - jit_unget_reg(reg); + if (can_sign_extend_jump_p(d)) + B(d); + else { + reg = jit_get_reg(jit_class_gpr|jit_class_nospill); + w = movi_p(rn(reg), i0); + jmpr(rn(reg)); + jit_unget_reg(reg); + } return (w); } @@ -3237,6 +3247,47 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) u.i[0] = (u.i[0] & ~0x3fffffd) | (d & 0x3fffffe); break; case 15: /* LI */ +#if __WORDSIZE == 32 +# define MTCTR_OFF 2 +# define BCTR_OFF 3 +#else +# define MTCTR_OFF 6 +# define BCTR_OFF 7 +#endif + /* movi reg label; jmpr reg */ + if (_jitc->jump && +#if 0 + /* check for MLTR(reg) */ + (u.i[MTCTR_OFF] >> 26) == 31 && + ((u.i[MTCTR_OFF] >> 16) & 0x3ff) == 8 && + ((u.i[MTCTR_OFF] >> 1) & 0x3ff) == 467 && + /* check for BLR */ + u.i[BCTR_OFF] == 0x4e800020) { +#else + /* check for MTCTR(reg) */ + (u.i[MTCTR_OFF] >> 26) == 31 && + ((u.i[MTCTR_OFF] >> 16) & 0x3ff) == 9 && + ((u.i[MTCTR_OFF] >> 1) & 0x3ff) == 467 && + /* check for BCTR */ + u.i[BCTR_OFF] == 0x4e800420) { +#endif + /* zero is used for toc and env, so, quick check + * if this is a "jmpi main" like initial jit + * instruction */ + if (((long *)label)[1] == 0 && ((long *)label)[2] == 0) { + for (d = 0; d < _jitc->prolog.offset; d++) { + /* not so pretty, but hides powerpc + * specific abi intrinsics and/or + * implementation from user */ + if (_jitc->prolog.ptr[d] == label) { + label += sizeof(void*) * 3; + break; + } + } + } + } +#undef BCTR_OFF +#undef MTCTR_OFF #if __WORDSIZE == 32 assert(!(u.i[0] & 0x1f0000)); u.i[0] = (u.i[0] & ~0xffff) | ((label >> 16) & 0xffff); diff --git a/lib/jit_ppc.c b/lib/jit_ppc.c index cbc5ddaab..8ef61198f 100644 --- a/lib/jit_ppc.c +++ b/lib/jit_ppc.c @@ -778,11 +778,19 @@ _emit_code(jit_state_t *_jit) #if __powerpc__ undo.prolog_offset = 0; - /* code may start with a jump so add an initial function descriptor */ - word = _jit->pc.w + sizeof(void*) * 3; - iw(word); /* addr */ - iw(0); /* toc */ - iw(0); /* env */ + for (node = _jitc->head; node; node = node->next) + if (node->code != jit_code_label && + node->code != jit_code_note && + node->code != jit_code_name) + break; + if (node && (node->code != jit_code_prolog || + !(_jitc->functions.ptr + node->w.w)->assume_frame)) { + /* code may start with a jump so add an initial function descriptor */ + word = _jit->pc.w + sizeof(void*) * 3; + iw(word); /* addr */ + iw(0); /* toc */ + iw(0); /* env */ + } #endif #define case_rr(name, type) \ @@ -1262,7 +1270,7 @@ _emit_code(jit_state_t *_jit) } } else - jmpi(node->u.w); + (void)jmpi_p(node->u.w); break; case jit_code_callr: callr(rn(node->u.w));