diff options
author | Richard Henderson <rth@redhat.com> | 2011-08-25 11:57:48 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2011-08-25 11:57:48 -0700 |
commit | 42aa5124f7a7173d1972668378a9531949f92599 (patch) | |
tree | ba68cdf5cb12fb41f9051ea44e08934bd8482ab0 /gcc/expr.c | |
parent | 0ab71f306cd6148c0c9f93418a86763ee2cd4b72 (diff) | |
download | gcc-42aa5124f7a7173d1972668378a9531949f92599.zip gcc-42aa5124f7a7173d1972668378a9531949f92599.tar.gz gcc-42aa5124f7a7173d1972668378a9531949f92599.tar.bz2 |
re PR debug/50132 (ICE: in maybe_record_trace_start, at dwarf2cfi.c:2234 with -fno-asynchronous-unwind-tables and long double)
PR 50132
PR 49864
* cfgcleanup.c (old_insns_match_p): Don't allow cross-jump for
non-constant stack adjutment.
* expr.c (find_args_size_adjust): Break out from ...
(fixup_args_size_notes): ... here.
* rtl.h (find_args_size_adjust): Declare.
From-SVN: r178084
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 236 |
1 files changed, 128 insertions, 108 deletions
@@ -3548,131 +3548,151 @@ mem_autoinc_base (rtx mem) verified, via immediate operand or auto-inc. If the adjustment cannot be trivially extracted, the return value is INT_MIN. */ -int -fixup_args_size_notes (rtx prev, rtx last, int end_args_size) +HOST_WIDE_INT +find_args_size_adjust (rtx insn) { - int args_size = end_args_size; - bool saw_unknown = false; - rtx insn; + rtx dest, set, pat; + int i; - for (insn = last; insn != prev; insn = PREV_INSN (insn)) - { - rtx dest, set, pat; - HOST_WIDE_INT this_delta = 0; - int i; + pat = PATTERN (insn); + set = NULL; - if (!NONDEBUG_INSN_P (insn)) - continue; - pat = PATTERN (insn); - set = NULL; + /* Look for a call_pop pattern. */ + if (CALL_P (insn)) + { + /* We have to allow non-call_pop patterns for the case + of emit_single_push_insn of a TLS address. */ + if (GET_CODE (pat) != PARALLEL) + return 0; - /* Look for a call_pop pattern. */ - if (CALL_P (insn)) + /* All call_pop have a stack pointer adjust in the parallel. + The call itself is always first, and the stack adjust is + usually last, so search from the end. */ + for (i = XVECLEN (pat, 0) - 1; i > 0; --i) { - /* We have to allow non-call_pop patterns for the case - of emit_single_push_insn of a TLS address. */ - if (GET_CODE (pat) != PARALLEL) - continue; - - /* All call_pop have a stack pointer adjust in the parallel. - The call itself is always first, and the stack adjust is - usually last, so search from the end. */ - for (i = XVECLEN (pat, 0) - 1; i > 0; --i) - { - set = XVECEXP (pat, 0, i); - if (GET_CODE (set) != SET) - continue; - dest = SET_DEST (set); - if (dest == stack_pointer_rtx) - break; - } - /* We'd better have found the stack pointer adjust. */ - if (i == 0) + set = XVECEXP (pat, 0, i); + if (GET_CODE (set) != SET) continue; - /* Fall through to process the extracted SET and DEST - as if it was a standalone insn. */ + dest = SET_DEST (set); + if (dest == stack_pointer_rtx) + break; } - else if (GET_CODE (pat) == SET) - set = pat; - else if ((set = single_set (insn)) != NULL) - ; - else if (GET_CODE (pat) == PARALLEL) + /* We'd better have found the stack pointer adjust. */ + if (i == 0) + return 0; + /* Fall through to process the extracted SET and DEST + as if it was a standalone insn. */ + } + else if (GET_CODE (pat) == SET) + set = pat; + else if ((set = single_set (insn)) != NULL) + ; + else if (GET_CODE (pat) == PARALLEL) + { + /* ??? Some older ports use a parallel with a stack adjust + and a store for a PUSH_ROUNDING pattern, rather than a + PRE/POST_MODIFY rtx. Don't force them to update yet... */ + /* ??? See h8300 and m68k, pushqi1. */ + for (i = XVECLEN (pat, 0) - 1; i >= 0; --i) { - /* ??? Some older ports use a parallel with a stack adjust - and a store for a PUSH_ROUNDING pattern, rather than a - PRE/POST_MODIFY rtx. Don't force them to update yet... */ - /* ??? See h8300 and m68k, pushqi1. */ - for (i = XVECLEN (pat, 0) - 1; i >= 0; --i) - { - set = XVECEXP (pat, 0, i); - if (GET_CODE (set) != SET) - continue; - dest = SET_DEST (set); - if (dest == stack_pointer_rtx) - break; - - /* We do not expect an auto-inc of the sp in the parallel. */ - gcc_checking_assert (mem_autoinc_base (dest) - != stack_pointer_rtx); - gcc_checking_assert (mem_autoinc_base (SET_SRC (set)) - != stack_pointer_rtx); - } - if (i < 0) + set = XVECEXP (pat, 0, i); + if (GET_CODE (set) != SET) continue; + dest = SET_DEST (set); + if (dest == stack_pointer_rtx) + break; + + /* We do not expect an auto-inc of the sp in the parallel. */ + gcc_checking_assert (mem_autoinc_base (dest) != stack_pointer_rtx); + gcc_checking_assert (mem_autoinc_base (SET_SRC (set)) + != stack_pointer_rtx); } + if (i < 0) + return 0; + } + else + return 0; + + dest = SET_DEST (set); + + /* Look for direct modifications of the stack pointer. */ + if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM) + { + /* Look for a trivial adjustment, otherwise assume nothing. */ + /* Note that the SPU restore_stack_block pattern refers to + the stack pointer in V4SImode. Consider that non-trivial. */ + if (SCALAR_INT_MODE_P (GET_MODE (dest)) + && GET_CODE (SET_SRC (set)) == PLUS + && XEXP (SET_SRC (set), 0) == stack_pointer_rtx + && CONST_INT_P (XEXP (SET_SRC (set), 1))) + return INTVAL (XEXP (SET_SRC (set), 1)); + /* ??? Reload can generate no-op moves, which will be cleaned + up later. Recognize it and continue searching. */ + else if (rtx_equal_p (dest, SET_SRC (set))) + return 0; else - continue; - dest = SET_DEST (set); - - /* Look for direct modifications of the stack pointer. */ - if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM) - { - gcc_assert (!saw_unknown); - /* Look for a trivial adjustment, otherwise assume nothing. */ - /* Note that the SPU restore_stack_block pattern refers to - the stack pointer in V4SImode. Consider that non-trivial. */ - if (SCALAR_INT_MODE_P (GET_MODE (dest)) - && GET_CODE (SET_SRC (set)) == PLUS - && XEXP (SET_SRC (set), 0) == stack_pointer_rtx - && CONST_INT_P (XEXP (SET_SRC (set), 1))) - this_delta = INTVAL (XEXP (SET_SRC (set), 1)); - /* ??? Reload can generate no-op moves, which will be cleaned - up later. Recognize it and continue searching. */ - else if (rtx_equal_p (dest, SET_SRC (set))) - this_delta = 0; - else - saw_unknown = true; - } + return HOST_WIDE_INT_MIN; + } + else + { + rtx mem, addr; + /* Otherwise only think about autoinc patterns. */ - else if (mem_autoinc_base (dest) == stack_pointer_rtx) + if (mem_autoinc_base (dest) == stack_pointer_rtx) { - rtx addr = XEXP (dest, 0); - gcc_assert (!saw_unknown); - switch (GET_CODE (addr)) - { - case PRE_INC: - case POST_INC: - this_delta = GET_MODE_SIZE (GET_MODE (dest)); - break; - case PRE_DEC: - case POST_DEC: - this_delta = -GET_MODE_SIZE (GET_MODE (dest)); - break; - case PRE_MODIFY: - case POST_MODIFY: - addr = XEXP (addr, 1); - gcc_assert (GET_CODE (addr) == PLUS); - gcc_assert (XEXP (addr, 0) == stack_pointer_rtx); - gcc_assert (CONST_INT_P (XEXP (addr, 1))); - this_delta = INTVAL (XEXP (addr, 1)); - break; - default: - gcc_unreachable (); - } + mem = dest; + gcc_checking_assert (mem_autoinc_base (SET_SRC (set)) + != stack_pointer_rtx); } + else if (mem_autoinc_base (SET_SRC (set)) == stack_pointer_rtx) + mem = SET_SRC (set); else + return 0; + + addr = XEXP (mem, 0); + switch (GET_CODE (addr)) + { + case PRE_INC: + case POST_INC: + return GET_MODE_SIZE (GET_MODE (mem)); + case PRE_DEC: + case POST_DEC: + return -GET_MODE_SIZE (GET_MODE (mem)); + case PRE_MODIFY: + case POST_MODIFY: + addr = XEXP (addr, 1); + gcc_assert (GET_CODE (addr) == PLUS); + gcc_assert (XEXP (addr, 0) == stack_pointer_rtx); + gcc_assert (CONST_INT_P (XEXP (addr, 1))); + return INTVAL (XEXP (addr, 1)); + default: + gcc_unreachable (); + } + } +} + +int +fixup_args_size_notes (rtx prev, rtx last, int end_args_size) +{ + int args_size = end_args_size; + bool saw_unknown = false; + rtx insn; + + for (insn = last; insn != prev; insn = PREV_INSN (insn)) + { + HOST_WIDE_INT this_delta; + + if (!NONDEBUG_INSN_P (insn)) + continue; + + this_delta = find_args_size_adjust (insn); + if (this_delta == 0) continue; + gcc_assert (!saw_unknown); + if (this_delta == HOST_WIDE_INT_MIN) + saw_unknown = true; + add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size)); #ifdef STACK_GROWS_DOWNWARD this_delta = -this_delta; |