summaryrefslogtreecommitdiff
path: root/gcc/except.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2009-03-28 09:08:52 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2009-03-28 09:08:52 +0000
commita5bfef5b903f411fa79333e850b65d304835a159 (patch)
tree4ebe94b877890d5f85418fb99ec4730610bcb172 /gcc/except.c
parent86ecf8ad3e82852c1c5992e005c60409833f7549 (diff)
downloadgcc-a5bfef5b903f411fa79333e850b65d304835a159.tar.gz
* tree-eh.c (inlinable_call_p): New function.
(make_eh_edges): Use it. (verify_eh_edges): Use it. (stmt_can_throw_external, stmt_can_throw_internal): Use it. * except.c (reachable_next_level): Add inlinable_function argument (sjlj_find_directly_reachable_regions): Update. (add_reachable_handler): Do not set saw_any_handlers. (reachable_next_level): Handle MUST_NOT_THROW more curefully. (foreach_reachable_handler, can_throw_internal_1, can_throw_external_1): Add new inlinable call parameter. (can_throw_internal, can_throw_external): Update. * except.h (can_throw_internal_1, can_throw_external_1, foreach_reachable_handler): Update declaration. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145166 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/except.c')
-rw-r--r--gcc/except.c49
1 files changed, 26 insertions, 23 deletions
diff --git a/gcc/except.c b/gcc/except.c
index 2913fc8f31f..91af716f631 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -271,7 +271,7 @@ enum reachable_code
struct reachable_info;
static enum reachable_code reachable_next_level (struct eh_region *, tree,
- struct reachable_info *);
+ struct reachable_info *, bool);
static int action_record_eq (const void *, const void *);
static hashval_t action_record_hash (const void *);
@@ -1660,7 +1660,7 @@ sjlj_find_directly_reachable_regions (struct sjlj_lp_info *lp_info)
rc = RNL_NOT_CAUGHT;
for (; region; region = region->outer)
{
- rc = reachable_next_level (region, type_thrown, NULL);
+ rc = reachable_next_level (region, type_thrown, NULL, false);
if (rc != RNL_NOT_CAUGHT)
break;
}
@@ -2359,8 +2359,6 @@ add_reachable_handler (struct reachable_info *info,
if (! info)
return;
- info->saw_any_handlers = true;
-
if (crtl->eh.built_landing_pads)
info->callback (lp_region, info->callback_data);
else
@@ -2374,7 +2372,8 @@ add_reachable_handler (struct reachable_info *info,
static enum reachable_code
reachable_next_level (struct eh_region *region, tree type_thrown,
- struct reachable_info *info)
+ struct reachable_info *info,
+ bool maybe_resx)
{
switch (region->type)
{
@@ -2510,15 +2509,16 @@ reachable_next_level (struct eh_region *region, tree type_thrown,
case ERT_MUST_NOT_THROW:
/* Here we end our search, since no exceptions may propagate.
- If we've touched down at some landing pad previous, then the
- explicit function call we generated may be used. Otherwise
- the call is made by the runtime.
+
+ Local landing pads of ERT_MUST_NOT_THROW instructions are reachable
+ only via locally handled RESX instructions.
- Before inlining, do not perform this optimization. We may
- inline a subroutine that contains handlers, and that will
- change the value of saw_any_handlers. */
+ When we inline a function call, we can bring in new handlers. In order
+ to avoid ERT_MUST_NOT_THROW landing pads from being deleted as unreachable
+ assume that such handlers exists prior for any inlinable call prior
+ inlining decisions are fixed. */
- if ((info && info->saw_any_handlers) || !cfun->after_inlining)
+ if (maybe_resx)
{
add_reachable_handler (info, region, region);
return RNL_CAUGHT;
@@ -2539,7 +2539,7 @@ reachable_next_level (struct eh_region *region, tree type_thrown,
/* Invoke CALLBACK on each region reachable from REGION_NUMBER. */
void
-foreach_reachable_handler (int region_number, bool is_resx,
+foreach_reachable_handler (int region_number, bool is_resx, bool inlinable_call,
void (*callback) (struct eh_region *, void *),
void *callback_data)
{
@@ -2570,7 +2570,8 @@ foreach_reachable_handler (int region_number, bool is_resx,
while (region)
{
- if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
+ if (reachable_next_level (region, type_thrown, &info,
+ inlinable_call || is_resx) >= RNL_CAUGHT)
break;
/* If we have processed one cleanup, there is no point in
processing any more of them. Each cleanup will have an edge
@@ -2622,7 +2623,7 @@ reachable_handlers (rtx insn)
region_number = INTVAL (XEXP (note, 0));
}
- foreach_reachable_handler (region_number, is_resx,
+ foreach_reachable_handler (region_number, is_resx, false,
(crtl->eh.built_landing_pads
? arh_to_landing_pad
: arh_to_label),
@@ -2635,7 +2636,7 @@ reachable_handlers (rtx insn)
within the function. */
bool
-can_throw_internal_1 (int region_number, bool is_resx)
+can_throw_internal_1 (int region_number, bool is_resx, bool inlinable_call)
{
struct eh_region *region;
tree type_thrown;
@@ -2656,7 +2657,8 @@ can_throw_internal_1 (int region_number, bool is_resx)
regions, which also do not require processing internally. */
for (; region; region = region->outer)
{
- enum reachable_code how = reachable_next_level (region, type_thrown, 0);
+ enum reachable_code how = reachable_next_level (region, type_thrown, 0,
+ inlinable_call || is_resx);
if (how == RNL_BLOCKED)
return false;
if (how != RNL_NOT_CAUGHT)
@@ -2677,7 +2679,7 @@ can_throw_internal (const_rtx insn)
if (JUMP_P (insn)
&& GET_CODE (PATTERN (insn)) == RESX
&& XINT (PATTERN (insn), 0) > 0)
- return can_throw_internal_1 (XINT (PATTERN (insn), 0), true);
+ return can_throw_internal_1 (XINT (PATTERN (insn), 0), true, false);
if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
@@ -2688,14 +2690,14 @@ can_throw_internal (const_rtx insn)
if (!note || INTVAL (XEXP (note, 0)) <= 0)
return false;
- return can_throw_internal_1 (INTVAL (XEXP (note, 0)), false);
+ return can_throw_internal_1 (INTVAL (XEXP (note, 0)), false, false);
}
/* Determine if the given INSN can throw an exception that is
visible outside the function. */
bool
-can_throw_external_1 (int region_number, bool is_resx)
+can_throw_external_1 (int region_number, bool is_resx, bool inlinable_call)
{
struct eh_region *region;
tree type_thrown;
@@ -2714,7 +2716,8 @@ can_throw_external_1 (int region_number, bool is_resx)
/* If the exception is caught or blocked by any containing region,
then it is not seen by any calling function. */
for (; region ; region = region->outer)
- if (reachable_next_level (region, type_thrown, NULL) >= RNL_CAUGHT)
+ if (reachable_next_level (region, type_thrown, NULL,
+ inlinable_call || is_resx) >= RNL_CAUGHT)
return false;
return true;
@@ -2731,7 +2734,7 @@ can_throw_external (const_rtx insn)
if (JUMP_P (insn)
&& GET_CODE (PATTERN (insn)) == RESX
&& XINT (PATTERN (insn), 0) > 0)
- return can_throw_external_1 (XINT (PATTERN (insn), 0), true);
+ return can_throw_external_1 (XINT (PATTERN (insn), 0), true, false);
if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
@@ -2752,7 +2755,7 @@ can_throw_external (const_rtx insn)
if (INTVAL (XEXP (note, 0)) <= 0)
return false;
- return can_throw_external_1 (INTVAL (XEXP (note, 0)), false);
+ return can_throw_external_1 (INTVAL (XEXP (note, 0)), false, false);
}
/* Set TREE_NOTHROW and crtl->all_throwers_are_sibcalls. */