summaryrefslogtreecommitdiff
path: root/gnu/egcs/gcc/jump.c
diff options
context:
space:
mode:
authorHiroaki Etoh <etoh@cvs.openbsd.org>2004-01-22 05:12:06 +0000
committerHiroaki Etoh <etoh@cvs.openbsd.org>2004-01-22 05:12:06 +0000
commita8775dbd6239343dfbbb7230fb3ca01afa5403b4 (patch)
treed3eb5ce3242abf9a8c3c75f988c937e3fa1e0ca4 /gnu/egcs/gcc/jump.c
parentc36a2ee0746288226da0613af6633da315013b0e (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.c201
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. */