diff options
author | Hiroaki Etoh <etoh@cvs.openbsd.org> | 2004-01-22 05:12:06 +0000 |
---|---|---|
committer | Hiroaki Etoh <etoh@cvs.openbsd.org> | 2004-01-22 05:12:06 +0000 |
commit | a8775dbd6239343dfbbb7230fb3ca01afa5403b4 (patch) | |
tree | d3eb5ce3242abf9a8c3c75f988c937e3fa1e0ca4 /gnu/egcs/gcc/jump.c | |
parent | c36a2ee0746288226da0613af6633da315013b0e (diff) |
to fix the issue "missing return at end of function and ProPolice", calculate_can_reach_end skips the NOTE_INSN_FUNCTION_END with _ssp_ label to the original NOTE_INSN_FUNCTION_END.
ok otto
Diffstat (limited to 'gnu/egcs/gcc/jump.c')
-rw-r--r-- | gnu/egcs/gcc/jump.c | 201 |
1 files changed, 143 insertions, 58 deletions
diff --git a/gnu/egcs/gcc/jump.c b/gnu/egcs/gcc/jump.c index 9b727fa32c8..bebe2f8af6f 100644 --- a/gnu/egcs/gcc/jump.c +++ b/gnu/egcs/gcc/jump.c @@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */ #include "real.h" #include "except.h" #include "toplev.h" +#include "protector.h" /* ??? Eventually must record somehow the labels used by jumps from nested functions. */ @@ -235,7 +236,12 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, mark_labels_only) if (!optimize) { - can_reach_end = calculate_can_reach_end (last_insn, 1, 0); + /* CAN_REACH_END is persistent for each function. Once set it should + not be cleared. This is especially true for the case where we + delete the NOTE_FUNCTION_END note. CAN_REACH_END is cleared by + the front-end before compiling each function. */ + if (calculate_can_reach_end (last_insn, 1, 0)) + can_reach_end = 1; /* Zero the "deleted" flag of all the "deleted" insns. */ for (insn = f; insn; insn = NEXT_INSN (insn)) @@ -366,19 +372,23 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, mark_labels_only) int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC; int len = XVECLEN (pat, diff_vec_p); rtx dispatch = prev_real_insn (insn); + rtx set; for (i = 0; i < len; i++) if (XEXP (XVECEXP (pat, diff_vec_p, i), 0) != XEXP (XVECEXP (pat, diff_vec_p, 0), 0)) break; + if (i == len && dispatch != 0 && GET_CODE (dispatch) == JUMP_INSN && JUMP_LABEL (dispatch) != 0 - /* Don't mess with a casesi insn. */ - && !(GET_CODE (PATTERN (dispatch)) == SET - && (GET_CODE (SET_SRC (PATTERN (dispatch))) - == IF_THEN_ELSE)) + /* Don't mess with a casesi insn. + XXX according to the comment before computed_jump_p(), + all casesi insns should be a parallel of the jump + and a USE of a LABEL_REF. */ + && ! ((set = single_set (dispatch)) != NULL + && (GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)) && next_real_insn (JUMP_LABEL (dispatch)) == insn) { redirect_tablejump (dispatch, @@ -2068,7 +2078,12 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, mark_labels_only) } #endif - can_reach_end = calculate_can_reach_end (last_insn, 0, 1); + /* CAN_REACH_END is persistent for each function. Once set it should + not be cleared. This is especially true for the case where we + delete the NOTE_FUNCTION_END note. CAN_REACH_END is cleared by + the front-end before compiling each function. */ + if (calculate_can_reach_end (last_insn, 0, 1)) + can_reach_end = 1; /* Show JUMP_CHAIN no longer valid. */ jump_chain = 0; @@ -2519,6 +2534,31 @@ calculate_can_reach_end (last, check_deleted, delete_final_note) return 1; } + /* If the NOTE_INSN_FUNCTION_END is generated by the stack protector, + skip to the label insn before protector's epilogue insns. */ + if (flag_propolice_protection + && insn != NULL_RTX + && GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END + && NOTE_SOURCE_FILE (insn) + && strcmp (NOTE_SOURCE_FILE (insn), SSP_DUMMY_FILE) == 0) + { + /* found ssp handler and skip to the first insn of ssp handler */ + int n_labels = 1; + + while (insn != NULL_RTX) + { + if (GET_CODE (insn) == CODE_LABEL && n_labels-- <= 0) + { + return calculate_can_reach_end (insn, check_deleted, + delete_final_note); + } + + insn = PREV_INSN (insn); + } + return 0; + } + return 0; } @@ -2538,7 +2578,7 @@ duplicate_loop_exit_test (loop_start) rtx loop_start; { rtx insn, set, reg, p, link; - rtx copy = 0; + rtx copy = 0, first_copy = 0; int num_insns = 0; rtx exitcode = NEXT_INSN (JUMP_LABEL (next_nonnote_insn (loop_start))); rtx lastexit; @@ -2651,19 +2691,20 @@ duplicate_loop_exit_test (loop_start) /* Now copy each insn. */ for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn)) - switch (GET_CODE (insn)) - { - case BARRIER: - copy = emit_barrier_before (loop_start); - break; - case NOTE: - /* Only copy line-number notes. */ - if (NOTE_LINE_NUMBER (insn) >= 0) - { - copy = emit_note_before (NOTE_LINE_NUMBER (insn), loop_start); - NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn); - } - break; + { + switch (GET_CODE (insn)) + { + case BARRIER: + copy = emit_barrier_before (loop_start); + break; + case NOTE: + /* Only copy line-number notes. */ + if (NOTE_LINE_NUMBER (insn) >= 0) + { + copy = emit_note_before (NOTE_LINE_NUMBER (insn), loop_start); + NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn); + } + break; case INSN: copy = emit_insn_before (copy_rtx (PATTERN (insn)), loop_start); @@ -2684,32 +2725,38 @@ duplicate_loop_exit_test (loop_start) replace_regs (REG_NOTES (copy), reg_map, max_reg, 1); break; - case JUMP_INSN: - copy = emit_jump_insn_before (copy_rtx (PATTERN (insn)), loop_start); - if (reg_map) - replace_regs (PATTERN (copy), reg_map, max_reg, 1); - mark_jump_label (PATTERN (copy), copy, 0); - if (REG_NOTES (insn)) - { - REG_NOTES (copy) = copy_rtx (REG_NOTES (insn)); - if (reg_map) - replace_regs (REG_NOTES (copy), reg_map, max_reg, 1); - } + case JUMP_INSN: + copy = emit_jump_insn_before (copy_rtx (PATTERN (insn)), loop_start); + if (reg_map) + replace_regs (PATTERN (copy), reg_map, max_reg, 1); + mark_jump_label (PATTERN (copy), copy, 0); + if (REG_NOTES (insn)) + { + REG_NOTES (copy) = copy_rtx (REG_NOTES (insn)); + if (reg_map) + replace_regs (REG_NOTES (copy), reg_map, max_reg, 1); + } - /* If this is a simple jump, add it to the jump chain. */ + /* If this is a simple jump, add it to the jump chain. */ - if (INSN_UID (copy) < max_jump_chain && JUMP_LABEL (copy) - && simplejump_p (copy)) - { - jump_chain[INSN_UID (copy)] - = jump_chain[INSN_UID (JUMP_LABEL (copy))]; - jump_chain[INSN_UID (JUMP_LABEL (copy))] = copy; - } - break; + if (INSN_UID (copy) < max_jump_chain && JUMP_LABEL (copy) + && simplejump_p (copy)) + { + jump_chain[INSN_UID (copy)] + = jump_chain[INSN_UID (JUMP_LABEL (copy))]; + jump_chain[INSN_UID (JUMP_LABEL (copy))] = copy; + } + break; - default: - abort (); - } + default: + abort (); + } + + /* Record the first insn we copied. We need it so that we can + scan the copied insns for new pseudo registers. */ + if (! first_copy) + first_copy = copy; + } /* Now clean up by emitting a jump to the end label and deleting the jump at the start of the loop. */ @@ -2717,6 +2764,14 @@ duplicate_loop_exit_test (loop_start) { copy = emit_jump_insn_before (gen_jump (get_label_after (insn)), loop_start); + + /* Record the first insn we copied. We need it so that we can + scan the copied insns for new pseudo registers. This may not + be strictly necessary since we should have copied at least one + insn above. But I am going to be safe. */ + if (! first_copy) + first_copy = copy; + mark_jump_label (PATTERN (copy), copy, 0); if (INSN_UID (copy) < max_jump_chain && INSN_UID (JUMP_LABEL (copy)) < max_jump_chain) @@ -2728,6 +2783,11 @@ duplicate_loop_exit_test (loop_start) emit_barrier_before (loop_start); } + /* Now scan from the first insn we copied to the last insn we copied + (copy) for new pseudo registers. Do this after the code to jump to + the end label since that might create a new pseudo too. */ + reg_scan_update (first_copy, copy, max_reg); + /* Mark the exit code as the virtual top of the converted loop. */ emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode); @@ -3151,8 +3211,17 @@ can_reverse_comparison_p (comparison, insn) ) { rtx prev = prev_nonnote_insn (insn); - rtx set = single_set (prev); + rtx set; + + /* If the comparison itself was a loop invariant, it could have been + hoisted out of the loop. If we proceed to unroll such a loop, then + we may not be able to find the comparison when copying the loop. + + Returning zero in that case is the safe thing to do. */ + if (prev == 0) + return 0; + set = single_set (prev); if (set == 0 || SET_DEST (set) != arg0) return 0; @@ -3979,20 +4048,36 @@ delete_insn (insn) and delete the label if it is now unused. */ if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn)) - if (--LABEL_NUSES (JUMP_LABEL (insn)) == 0) - { - /* This can delete NEXT or PREV, - either directly if NEXT is JUMP_LABEL (INSN), - or indirectly through more levels of jumps. */ - delete_insn (JUMP_LABEL (insn)); - /* I feel a little doubtful about this loop, - but I see no clean and sure alternative way - to find the first insn after INSN that is not now deleted. - I hope this works. */ - while (next && INSN_DELETED_P (next)) - next = NEXT_INSN (next); - return next; - } + { + rtx lab = JUMP_LABEL (insn), lab_next; + + if (--LABEL_NUSES (lab) == 0) + { + /* This can delete NEXT or PREV, + either directly if NEXT is JUMP_LABEL (INSN), + or indirectly through more levels of jumps. */ + delete_insn (lab); + + /* I feel a little doubtful about this loop, + but I see no clean and sure alternative way + to find the first insn after INSN that is not now deleted. + I hope this works. */ + while (next && INSN_DELETED_P (next)) + next = NEXT_INSN (next); + return next; + } + else if ((lab_next = next_nonnote_insn (lab)) != NULL + && GET_CODE (lab_next) == JUMP_INSN + && (GET_CODE (PATTERN (lab_next)) == ADDR_VEC + || GET_CODE (PATTERN (lab_next)) == ADDR_DIFF_VEC)) + { + /* If we're deleting the tablejump, delete the dispatch table. + We may not be able to kill the label immediately preceeding + just yet, as it might be referenced in code leading up to + the tablejump. */ + delete_insn (lab_next); + } + } /* Likewise if we're deleting a dispatch table. */ |