From: Bernd Schmidt Date: Wed, 4 Apr 2001 13:26:24 +0000 (+0000) Subject: Fix an abort in purge_addressof_1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c423fd56b2369fb20d0026704ec9831967b3807;p=thirdparty%2Fgcc.git Fix an abort in purge_addressof_1 From-SVN: r41080 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d12f8e2b8ca8..cf9174ea0e5a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2001-04-04 Bernd Schmidt + + Fri Nov 5 10:07:25 1999 Nick Clifton + * function.c (is_addressof): New function. Returns true if + the given piece of RTL is an ADDRESSOF. + (purge_addressof_1): Make boolean. Return false if the + ADDRESSOFs could not be purged. + (purge_addressof): If ADDRESSOFs could not be purged from the + notes attached to an insn, remove the offending note(s), + unless they are attached to a libcall. + 2001-04-03 Bernd Schmidt 2001-03-16 Jakub Jelinek diff --git a/gcc/function.c b/gcc/function.c index edd0bca12168..5a7a2e2ed32e 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -513,8 +513,9 @@ static int *record_insns PROTO((rtx)); static int contains PROTO((rtx, int *)); #endif /* HAVE_prologue || HAVE_epilogue */ static void put_addressof_into_stack PROTO((rtx, struct hash_table *)); -static void purge_addressof_1 PROTO((rtx *, rtx, int, int, +static boolean purge_addressof_1 PROTO((rtx *, rtx, int, int, struct hash_table *)); +static int is_addressof PROTO ((rtx *, void *)); static struct hash_entry *insns_for_mem_newfunc PROTO((struct hash_entry *, struct hash_table *, hash_table_key)); @@ -3055,9 +3056,10 @@ static rtx purge_addressof_replacements; /* Helper function for purge_addressof. See if the rtx expression at *LOC in INSN needs to be changed. If FORCE, always put any ADDRESSOFs into - the stack. */ + the stack. If the function returns FALSE then the replacement could not + be made. */ -static void +static boolean purge_addressof_1 (loc, insn, force, store, ht) rtx *loc; rtx insn; @@ -3068,13 +3070,14 @@ purge_addressof_1 (loc, insn, force, store, ht) RTX_CODE code; int i, j; char *fmt; + boolean result = true; /* Re-start here to avoid recursion in common cases. */ restart: x = *loc; if (x == 0) - return; + return true; code = GET_CODE (x); @@ -3087,7 +3090,7 @@ purge_addressof_1 (loc, insn, force, store, ht) if (validate_change (insn, loc, sub, 0) || validate_replace_rtx (x, sub, insn)) - return; + return true; start_sequence (); sub = force_operand (sub, NULL_RTX); @@ -3098,7 +3101,7 @@ purge_addressof_1 (loc, insn, force, store, ht) insns = gen_sequence (); end_sequence (); emit_insn_before (insns, insn); - return; + return true; } else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force) { @@ -3117,7 +3120,7 @@ purge_addressof_1 (loc, insn, force, store, ht) && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode)) { put_addressof_into_stack (XEXP (x, 0), ht); - return; + return true; } else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub)) { @@ -3136,7 +3139,7 @@ purge_addressof_1 (loc, insn, force, store, ht) if (rtx_equal_p (x, XEXP (tem, 0))) { *loc = XEXP (XEXP (tem, 1), 0); - return; + return true; } /* See comment for purge_addressof_replacements. */ @@ -3176,11 +3179,17 @@ purge_addressof_1 (loc, insn, force, store, ht) z = gen_lowpart (GET_MODE (x), z); *loc = z; - return; + return true; } - /* There should always be such a replacement. */ - abort (); + /* Sometimes we may not be able to find the replacement. For + example when the original insn was a MEM in a wider mode, + and the note is part of a sign extension of a narrowed + version of that MEM. Gcc testcase compile/990829-1.c can + generate an example of this siutation. Rather than complain + we return false, which will prompt our caller to remove the + offending note. */ + return false; } size_x = GET_MODE_BITSIZE (GET_MODE (x)); @@ -3266,7 +3275,7 @@ purge_addressof_1 (loc, insn, force, store, ht) purge_bitfield_addressof_replacements)); /* We replaced with a reg -- all done. */ - return; + return true; } } else if (validate_change (insn, loc, sub, 0)) @@ -3283,13 +3292,13 @@ purge_addressof_1 (loc, insn, force, store, ht) if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0))) { XEXP (XEXP (tem, 1), 0) = sub; - return; + return true; } purge_addressof_replacements = gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0), gen_rtx_EXPR_LIST (VOIDmode, sub, purge_addressof_replacements)); - return; + return true; } goto restart; } @@ -3299,13 +3308,13 @@ purge_addressof_1 (loc, insn, force, store, ht) else if (code == ADDRESSOF) { put_addressof_into_stack (x, ht); - return; + return true; } else if (code == SET) { - purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht); - purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); - return; + result = purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht); + result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); + return result; } /* Scan all subexpressions. */ @@ -3313,11 +3322,13 @@ purge_addressof_1 (loc, insn, force, store, ht) for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) { if (*fmt == 'e') - purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht); + result &= purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht); else if (*fmt == 'E') for (j = 0; j < XVECLEN (x, i); j++) - purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht); + result &= purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht); } + + return result; } /* Return a new hash table entry in HT. */ @@ -3437,6 +3448,16 @@ compute_insns_for_mem (insns, last_insn, ht) } } +/* Helper function for purge_addressof called through for_each_rtx. + Returns true iff the rtl is an ADDRESSOF. */ +static int +is_addressof (rtl, data) + rtx * rtl; + void * data ATTRIBUTE_UNUSED; +{ + return GET_CODE (* rtl) == ADDRESSOF; +} + /* Eliminate all occurrences of ADDRESSOF from INSNS. Elide any remaining (MEM (ADDRESSOF)) patterns, and force any needed registers into the stack. */ @@ -3465,9 +3486,30 @@ purge_addressof (insns) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN) { - purge_addressof_1 (&PATTERN (insn), insn, - asm_noperands (PATTERN (insn)) > 0, 0, &ht); - purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, &ht); + if (! purge_addressof_1 (&PATTERN (insn), insn, + asm_noperands (PATTERN (insn)) > 0, 0, &ht)) + /* If we could not replace the ADDRESSOFs in the insn, + something is wrong. */ + abort (); + + if (! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, &ht)) + { + /* If we could not replace the ADDRESSOFs in the insn's notes, + we can just remove the offending notes instead. */ + rtx note; + + for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) + { + /* If we find a REG_RETVAL note then the insn is a libcall. + Such insns must have REG_EQUAL notes as well, in order + for later passes of the compiler to work. So it is not + safe to delete the notes here, and instead we abort. */ + if (REG_NOTE_KIND (note) == REG_RETVAL) + abort (); + if (for_each_rtx (& note, is_addressof, NULL)) + remove_note (insn, note); + } + } } /* Clean up. */