aboutsummaryrefslogtreecommitdiff
path: root/gcc/except.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/except.c')
-rw-r--r--gcc/except.c61
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. */