diff options
Diffstat (limited to 'gcc/except.c')
-rw-r--r-- | gcc/except.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/gcc/except.c b/gcc/except.c index a2818c3408f..bc2c393f0e0 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -353,7 +353,7 @@ static void sjlj_output_call_site_table PARAMS ((void)); /* Routine to see if exception handling is turned on. - DO_WARN is non-zero if we want to inform the user that exception + DO_WARN is nonzero if we want to inform the user that exception handling is turned off. This is used to ensure that -fexceptions has been specified if the @@ -672,12 +672,12 @@ expand_start_catch (type_or_list) void expand_end_catch () { - struct eh_region *try_region, *catch_region; + struct eh_region *try_region; if (! doing_eh (0)) return; - catch_region = expand_eh_region_end (); + expand_eh_region_end (); try_region = cfun->eh->try_region; emit_jump (try_region->u.try.continue_label); @@ -2893,25 +2893,50 @@ can_throw_external (insn) return true; } -/* True if nothing in this function can throw outside this function. */ +/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls. */ -bool -nothrow_function_p () +void +set_nothrow_function_flags () { rtx insn; + + current_function_nothrow = 1; - if (! flag_exceptions) - return true; + /* Assume cfun->all_throwers_are_sibcalls until we encounter + something that can throw an exception. We specifically exempt + CALL_INSNs that are SIBLING_CALL_P, as these are really jumps, + and can't throw. Most CALL_INSNs are not SIBLING_CALL_P, so this + is optimistic. */ + cfun->all_throwers_are_sibcalls = 1; + + if (! flag_exceptions) + return; + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) if (can_throw_external (insn)) - return false; + { + current_function_nothrow = 0; + + if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn)) + { + cfun->all_throwers_are_sibcalls = 0; + return; + } + } + for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) - if (can_throw_external (XEXP (insn, 0))) - return false; + if (can_throw_external (insn)) + { + current_function_nothrow = 0; - return true; + if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn)) + { + cfun->all_throwers_are_sibcalls = 0; + return; + } + } } @@ -2968,6 +2993,16 @@ expand_builtin_extract_return_addr (addr_tree) { rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0); + if (GET_MODE (addr) != Pmode + && GET_MODE (addr) != VOIDmode) + { +#ifdef POINTERS_EXTEND_UNSIGNED + addr = convert_memory_address (Pmode, addr); +#else + addr = convert_to_mode (Pmode, addr, 0); +#endif + } + /* First mask out any unwanted bits. */ #ifdef MASK_RETURN_ADDR expand_and (Pmode, addr, MASK_RETURN_ADDR, addr); @@ -3600,7 +3635,7 @@ output_function_exception_table () assemble_align (tt_format_size * BITS_PER_UNIT); } - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA", + (*targetm.asm_out.internal_label) (asm_out_file, "LLSDA", current_function_funcdef_no); /* The LSDA header. */ |