From 89965887cca021f771f8c30af2f0f2f23b3e15db Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Tue, 8 Nov 2022 09:36:32 +0000 Subject: [PATCH] Implement return_to on mips, ppc, riscv --- sljit_src/sljitNativeARM_32.c | 4 +- sljit_src/sljitNativeARM_64.c | 4 +- sljit_src/sljitNativeARM_T2_32.c | 4 +- sljit_src/sljitNativeMIPS_32.c | 2 +- sljit_src/sljitNativeMIPS_64.c | 2 +- sljit_src/sljitNativeMIPS_common.c | 45 ++++++++++++++-- sljit_src/sljitNativePPC_common.c | 55 ++++++++++++++----- sljit_src/sljitNativeRISCV_common.c | 42 ++++++++++++--- sljit_src/sljitNativeS390X.c | 4 +- sljit_src/sljitNativeX86_32.c | 4 +- sljit_src/sljitNativeX86_64.c | 4 +- test_src/sljitTest.c | 82 ++++++++++++++++------------- 12 files changed, 176 insertions(+), 76 deletions(-) diff --git a/sljit_src/sljitNativeARM_32.c b/sljit_src/sljitNativeARM_32.c index 3cd2ee69..eddbd47e 100644 --- a/sljit_src/sljitNativeARM_32.c +++ b/sljit_src/sljitNativeARM_32.c @@ -1402,7 +1402,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; srcw = 0; - } else if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); src = TMP_REG1; srcw = 0; @@ -2924,7 +2924,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi src = TMP_REG1; } - if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); src = TMP_REG1; } diff --git a/sljit_src/sljitNativeARM_64.c b/sljit_src/sljitNativeARM_64.c index 4866e33a..fccc1fa8 100644 --- a/sljit_src/sljitNativeARM_64.c +++ b/sljit_src/sljitNativeARM_64.c @@ -1244,7 +1244,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; srcw = 0; - } else if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); src = TMP_REG1; srcw = 0; @@ -1969,7 +1969,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); src = TMP_REG1; } diff --git a/sljit_src/sljitNativeARM_T2_32.c b/sljit_src/sljitNativeARM_T2_32.c index f77cad01..422545ea 100644 --- a/sljit_src/sljitNativeARM_T2_32.c +++ b/sljit_src/sljitNativeARM_T2_32.c @@ -1520,7 +1520,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; srcw = 0; - } else if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src))); src = TMP_REG1; srcw = 0; @@ -2492,7 +2492,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi src = TMP_REG1; } - if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src))); src = TMP_REG1; } diff --git a/sljit_src/sljitNativeMIPS_32.c b/sljit_src/sljitNativeMIPS_32.c index ca9dbd0a..e6853c98 100644 --- a/sljit_src/sljitNativeMIPS_32.c +++ b/sljit_src/sljitNativeMIPS_32.c @@ -267,7 +267,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if ((type & 0xff) == SLJIT_CALL_REG_ARG) { if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); src = PIC_ADDR_REG; srcw = 0; diff --git a/sljit_src/sljitNativeMIPS_64.c b/sljit_src/sljitNativeMIPS_64.c index 443bade8..d2a5924f 100644 --- a/sljit_src/sljitNativeMIPS_64.c +++ b/sljit_src/sljitNativeMIPS_64.c @@ -282,7 +282,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if ((type & 0xff) == SLJIT_CALL_REG_ARG) { if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); src = PIC_ADDR_REG; srcw = 0; diff --git a/sljit_src/sljitNativeMIPS_common.c b/sljit_src/sljitNativeMIPS_common.c index 6aa5c986..193047df 100644 --- a/sljit_src/sljitNativeMIPS_common.c +++ b/sljit_src/sljitNativeMIPS_common.c @@ -1007,12 +1007,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr) { sljit_s32 local_size, i, tmp, offset; + sljit_s32 load_return_addr = (frame_size == 0); sljit_s32 scratches = compiler->scratches; sljit_s32 saveds = compiler->saveds; sljit_s32 fsaveds = compiler->fsaveds; sljit_s32 fscratches = compiler->fscratches; sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options); + SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0); + frame_size &= ~0xf; + local_size = compiler->local_size; tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1); @@ -1043,7 +1047,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit SLJIT_ASSERT(local_size >= frame_size); offset = local_size - SSIZE_OF(sw); - if (frame_size == 0) + if (load_return_addr) FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG)); tmp = SLJIT_S0 - saveds; @@ -1095,6 +1099,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler return push_inst(compiler, ins, UNMOVABLE_INS); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); + src = PIC_ADDR_REG; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); + src = PIC_ADDR_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1, &ins)); + + if (!(src & SLJIT_IMM)) { + FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); + return push_inst(compiler, ins, UNMOVABLE_INS); + } + + if (ins != NOP) + FAIL_IF(push_inst(compiler, ins, MOVABLE_INS)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -2848,7 +2885,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); @@ -2860,8 +2896,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi jump->flags |= IS_MOVABLE; src = TMP_REG2; - } - else if (src & SLJIT_MEM) { + } else if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw)); src = TMP_REG2; } @@ -2881,6 +2917,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi compiler->size += 6; #endif } + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return SLJIT_SUCCESS; } diff --git a/sljit_src/sljitNativePPC_common.c b/sljit_src/sljitNativePPC_common.c index 49e3f570..2507a443 100644 --- a/sljit_src/sljitNativePPC_common.c +++ b/sljit_src/sljitNativePPC_common.c @@ -720,6 +720,9 @@ ALT_FORM5 0x010000 */ #define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET) +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) @@ -855,7 +858,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp return SLJIT_SUCCESS; } -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 i, tmp, base, offset; sljit_s32 local_size = compiler->local_size; @@ -873,7 +876,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) } offset = local_size; - FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET))); + if (!is_return_to) + FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET))); tmp = SLJIT_FS0 - compiler->fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { @@ -902,7 +906,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset))); } - push_inst(compiler, MTLR | S(0)); + if (!is_return_to) + push_inst(compiler, MTLR | S(0)); if (local_size > 0) return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size)); @@ -911,17 +916,40 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base)); } +#undef STACK_STORE +#undef STACK_LOAD + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) { CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); return push_inst(compiler, BLR); } -#undef STACK_STORE -#undef STACK_LOAD +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); + src = TMP_CALL_REG; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); + src = TMP_CALL_REG; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} /* --------------------------------------------------------------------- */ /* Operators */ @@ -2194,7 +2222,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile #endif if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } @@ -2209,7 +2237,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) @@ -2236,9 +2263,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); src_r = TMP_CALL_REG; - } - else { - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); + } else { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); src_r = TMP_CALL_REG; } @@ -2257,17 +2284,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); src = TMP_CALL_REG; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); src = TMP_CALL_REG; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP; } diff --git a/sljit_src/sljitNativeRISCV_common.c b/sljit_src/sljitNativeRISCV_common.c index 0e075b46..5ee4eeb3 100644 --- a/sljit_src/sljitNativeRISCV_common.c +++ b/sljit_src/sljitNativeRISCV_common.c @@ -592,6 +592,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) #define STACK_MAX_DISTANCE (-SIMM_MIN) +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw); + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) @@ -714,7 +716,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp #define STACK_MAX_DISTANCE (-SIMM_MIN - 16) -static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) { sljit_s32 i, tmp, offset; sljit_s32 local_size = compiler->local_size; @@ -734,7 +736,8 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler) SLJIT_ASSERT(local_size > 0); offset = local_size - SSIZE_OF(sw); - FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset))); + if (!is_return_to) + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset))); tmp = SLJIT_S0 - compiler->saveds; for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) { @@ -774,10 +777,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ @@ -2201,7 +2227,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); if (type & SLJIT_CALL_RETURN) { - PTR_FAIL_IF(emit_stack_frame_release(compiler)); + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); } @@ -2318,10 +2344,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (!(src & SLJIT_IMM)) { if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); src = TMP_REG1; } @@ -2353,20 +2379,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi SLJIT_UNUSED_ARG(arg_types); CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); src = TMP_REG1; } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0))); src = TMP_REG1; } - FAIL_IF(emit_stack_frame_release(compiler)); + FAIL_IF(emit_stack_frame_release(compiler, 0)); type = SLJIT_JUMP; } diff --git a/sljit_src/sljitNativeS390X.c b/sljit_src/sljitNativeS390X.c index 082c1080..1743513a 100644 --- a/sljit_src/sljitNativeS390X.c +++ b/sljit_src/sljitNativeS390X.c @@ -1853,7 +1853,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */)); src = TMP_REG2; srcw = 0; - } else if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src)))); src = TMP_REG2; srcw = 0; @@ -3270,7 +3270,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src)))); src = TMP_REG2; srcw = 0; diff --git a/sljit_src/sljitNativeX86_32.c b/sljit_src/sljitNativeX86_32.c index d67b8cdb..9c3738dc 100644 --- a/sljit_src/sljitNativeX86_32.c +++ b/sljit_src/sljitNativeX86_32.c @@ -603,7 +603,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c CHECK_ERROR(); CHECK(check_sljit_emit_return_to(compiler, src, srcw)); - if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= SLJIT_S0)) { + if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(src, srcw, (void)0); @@ -1057,7 +1057,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if ((type & 0xff) == SLJIT_CALL_REG_ARG) { FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types)); - if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= SLJIT_S0)) { + if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(src, srcw, (void)0); diff --git a/sljit_src/sljitNativeX86_64.c b/sljit_src/sljitNativeX86_64.c index 114986e0..5dc29826 100644 --- a/sljit_src/sljitNativeX86_64.c +++ b/sljit_src/sljitNativeX86_64.c @@ -678,7 +678,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c compiler->mode32 = 0; - if ((src & SLJIT_MEM) || (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) { + if ((src & SLJIT_MEM) || (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) { ADJUST_LOCAL_OFFSET(src, srcw); EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); @@ -843,7 +843,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi } if (type & SLJIT_CALL_RETURN) { - if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); src = TMP_REG2; } diff --git a/test_src/sljitTest.c b/test_src/sljitTest.c index 2cf3022a..3e436813 100644 --- a/test_src/sljitTest.c +++ b/test_src/sljitTest.c @@ -9510,49 +9510,59 @@ static void test82(void) /* Next test. */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); + for (i = 0; i < 3; i++) { + compiler = sljit_create_compiler(NULL, NULL); + FAILED(!compiler, "cannot create compiler\n"); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, 1, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 6032); - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(W, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - label = sljit_emit_label(compiler); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_RETURN_REG, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S0, 0); - sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); - sljit_emit_return_void(compiler); + sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, 1, 0, 0, 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 6032); + jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(W, W)); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); + label = sljit_emit_label(compiler); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf); + /* buf[0] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_RETURN_REG, 0); + /* buf[2] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S0, 0); + sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); + sljit_emit_return_void(compiler); - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS1(VOID, W_R), 2, 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), SLJIT_MAX_LOCAL_SIZE - sizeof(sljit_sw), SLJIT_IMM, -1); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -3890); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 7145); - sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw)); + sljit_set_label(jump, sljit_emit_label(compiler)); + sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS1(VOID, W_R), 2, i == 1 ? 2 : 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0); + /* buf[1] */ + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); + if (i == 2) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0); + else + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_MEM1(SLJIT_S0), 0); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), SLJIT_MAX_LOCAL_SIZE - sizeof(sljit_sw), SLJIT_IMM, -1); + if (i != 0) + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -3890); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 7145); + if (i == 2) + sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw)); + else + sljit_emit_return_to(compiler, SLJIT_S(i), 0); - code.code = sljit_generate_code(compiler); - CHECK(compiler); + code.code = sljit_generate_code(compiler); + CHECK(compiler); - buf[0] = (sljit_sw)sljit_get_label_addr(label); - buf[1] = 0; - buf[2] = 0; + buf[0] = (sljit_sw)sljit_get_label_addr(label); + buf[1] = 0; + buf[2] = 0; - sljit_free_compiler(compiler); + sljit_free_compiler(compiler); - code.func1((sljit_sw)buf); - FAILED(buf[0] != 7145, "test82 case 3 failed\n"); - FAILED(buf[1] != 6032, "test82 case 4 failed\n"); - FAILED(buf[2] != -3890, "test82 case 5 failed\n"); + code.func1((sljit_sw)buf); + FAILED(buf[0] != 7145, "test82 case 3 failed\n"); + FAILED(buf[1] != 6032, "test82 case 4 failed\n"); + if (i != 0) + FAILED(buf[2] != -3890, "test82 case 5 failed\n"); - sljit_free_code(code.code, NULL); + sljit_free_code(code.code, NULL); + } /* Next test. */