* except.c (can_throw): See through a SEQUENCE.
(nothrow_function_p): New fn.
* except.h: Declare it.
* function.c (current_function_nothrow): New var.
(prepare_function_start): Initialize it.
* output.h: Declare it.
* toplev.c (rest_of_compilation): Set it.
* dwarf2out.c (dwarf2out_begin_prologue): Use it.
From-SVN: r32449
+2000-03-09 Jason Merrill <jason@casey.cygnus.com>
+
+ * except.c (can_throw): See through a SEQUENCE.
+ (nothrow_function_p): New fn.
+ * except.h: Declare it.
+ * function.c (current_function_nothrow): New var.
+ (prepare_function_start): Initialize it.
+ * output.h: Declare it.
+ * toplev.c (rest_of_compilation): Set it.
+ * dwarf2out.c (dwarf2out_begin_prologue): Use it.
+
2000-03-09 Zack Weinberg <zack@wolery.cumb.org>
* cpphash.c (collect_formal_parameters): strncmp returns 0 for
(struct tree_int_cst): int_cst_low is now unsigned HOST_WIDE_INT.
(attribute_hash_list, type_hash_canon): hashcode is now unsigned.
(type_hash_lookup, type_hash_add, type_hash_list): Likewise.
- (min_precision): Result is unsignd.
+ (min_precision): Result is unsigned.
(add_double, neg_double, mul_double): Low word is unsigned.
(lshift_double, rshift_double, lrotate_double): Likewise.
(rrotate_double, div_and_round_double): Likewise.
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
fde->dw_fde_cfi = NULL;
-
- /* Normally, only calls can throw, so a leaf function will never throw. */
- fde->nothrow = (current_function_is_leaf && !asynchronous_exceptions);
+ fde->nothrow = current_function_nothrow;
args_size = old_args_size = 0;
}
Doing this for nested functions is wrong, however; functions are
distinct units, and our context might not even be inline. */
- tree fn = decl_function_context (origin);
+ tree fn = origin;
+ if (TYPE_P (fn))
+ fn = TYPE_STUB_DECL (fn);
+ fn = decl_function_context (fn);
if (fn)
gen_abstract_function (fn);
}
}
/* If we are using the setjmp/longjmp EH codegen method, we emit a
- call to __sjthrow.
-
- Otherwise, we emit a call to __throw and note that we threw
- something, so we know we need to generate the necessary code for
- __throw.
-
- Before invoking throw, the __eh_pc variable must have been set up
- to contain the PC being thrown from. This address is used by
- __throw to determine which exception region (if any) is
- responsible for handling the exception. */
+ call to __sjthrow. Otherwise, we emit a call to __throw. */
void
emit_throw ()
can_throw (insn)
rtx insn;
{
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ insn = XVECEXP (PATTERN (insn), 0, 0);
+
/* Calls can always potentially throw exceptions, unless they have
a REG_EH_REGION note with a value of 0 or less. */
if (GET_CODE (insn) == CALL_INSN)
return 0;
}
+/* Return nonzero if nothing in this function can throw. */
+
+int
+nothrow_function_p ()
+{
+ rtx insn;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (can_throw (insn))
+ return 0;
+ for (insn = current_function_epilogue_delay_list; insn;
+ insn = XEXP (insn, 1))
+ if (can_throw (insn))
+ return 0;
+
+ return 1;
+}
+
/* Scan a exception region looking for the matching end and then
remove it if possible. INSN is the start of the region, N is the
region number, and DELETE_OUTER is to note if anything in this
extern rtx exception_handler_labels;
+/* Return nonzero if nothing in this function can throw. */
+
+extern int nothrow_function_p PARAMS ((void));
+
/* Performs optimizations for exception handling, such as removing
unnecessary exception regions. Invoked from jump_optimize (). */
compiler passes. */
int current_function_is_leaf;
+/* Nonzero if function being compiled doesn't contain any instructions
+ that can throw an exception. This is set prior to final. */
+
+int current_function_nothrow;
+
/* Nonzero if function being compiled doesn't modify the stack pointer
(ignoring the prologue and epilogue). This is only valid after
life_analysis has run. */
current_function_calls_alloca = 0;
current_function_contains_functions = 0;
current_function_is_leaf = 0;
+ current_function_nothrow = 0;
current_function_sp_is_unchanging = 0;
current_function_uses_only_leaf_regs = 0;
current_function_has_computed_jump = 0;
extern int current_function_is_leaf;
+/* Nonzero if function being compiled doesn't contain any instructions
+ that can throw an exception. This is set prior to final. */
+
+extern int current_function_nothrow;
+
/* Nonzero if function being compiled doesn't modify the stack pointer
(ignoring the prologue and epilogue). This is only valid after
life_analysis has run. */
print_rtl_graph_with_bb (dump_base_name, ".20.stack", insns);
}
- if (ggc_p)
- ggc_collect ();
+ if (ggc_p)
+ ggc_collect ();
#endif
+ current_function_nothrow = nothrow_function_p ();
+
/* Now turn the rtl into assembler code. */
TIMEVAR (final_time,