except.c (duplicate_eh_region_1, [...]): New functions, based on old implementation removed with RTL inliner.
* except.c (duplicate_eh_region_1, duplicate_eh_region_2, duplicate_eh_regions): New functions, based on old implementation removed with RTL inliner. (reachable_next_level): Modify behaviour pre-inline. * except.h (duplicate_eh_regions_map, duplicate_eh_regions): Declare. * function.h (struct function): Add after_inlining flag. * tree-optimize.c (tree_rest_of_compilation): Set it. * tree-eh.c (add_stmt_to_eh_region_fn): Initialize hashtable when needed. * tree-cfg.c (label_to_block_fn): Deal with cases where label was never insterted into code. Co-Authored-By: Jan Hubicka <jh@suse.cz> Co-Authored-By: Stuart Hastings <stuart@apple.com> From-SVN: r99625
This commit is contained in:
parent
1ed17cd539
commit
98f464e058
7 changed files with 177 additions and 2 deletions
|
@ -1,3 +1,20 @@
|
|||
2005-05-12 Steven Bosscher <stevenb@suse.de>
|
||||
Stuart Hastings <stuart@apple.com>
|
||||
Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* except.c (duplicate_eh_region_1, duplicate_eh_region_2,
|
||||
duplicate_eh_regions): New functions, based on old
|
||||
implementation removed with RTL inliner.
|
||||
(reachable_next_level): Modify behaviour pre-inline.
|
||||
* except.h (duplicate_eh_regions_map, duplicate_eh_regions):
|
||||
Declare.
|
||||
* function.h (struct function): Add after_inlining flag.
|
||||
* tree-optimize.c (tree_rest_of_compilation): Set it.
|
||||
* tree-eh.c (add_stmt_to_eh_region_fn): Initialize hashtable
|
||||
when needed.
|
||||
* tree-cfg.c (label_to_block_fn): Deal with cases where
|
||||
label was never insterted into code.
|
||||
|
||||
2005-05-12 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
* doc/cpp.texi: Document that #sccs is a synonym for #ident.
|
||||
|
|
151
gcc/except.c
151
gcc/except.c
|
@ -853,6 +853,148 @@ current_function_has_exception_handlers (void)
|
|||
return false;
|
||||
}
|
||||
|
||||
static struct eh_region *
|
||||
duplicate_eh_region_1 (struct eh_region *o)
|
||||
{
|
||||
struct eh_region *n = ggc_alloc_cleared (sizeof (struct eh_region));
|
||||
|
||||
*n = *o;
|
||||
|
||||
n->region_number = o->region_number + cfun->eh->last_region_number;
|
||||
gcc_assert (!o->aka);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
duplicate_eh_region_2 (struct eh_region *o, struct eh_region **n_array,
|
||||
struct eh_region *prev_try)
|
||||
{
|
||||
struct eh_region *n = n_array[o->region_number];
|
||||
|
||||
switch (n->type)
|
||||
{
|
||||
case ERT_TRY:
|
||||
if (o->u.try.catch)
|
||||
n->u.try.catch = n_array[o->u.try.catch->region_number];
|
||||
if (o->u.try.last_catch)
|
||||
n->u.try.last_catch = n_array[o->u.try.last_catch->region_number];
|
||||
break;
|
||||
|
||||
case ERT_CATCH:
|
||||
if (o->u.catch.next_catch)
|
||||
n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
|
||||
if (o->u.catch.prev_catch)
|
||||
n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
|
||||
break;
|
||||
|
||||
case ERT_CLEANUP:
|
||||
if (o->u.cleanup.prev_try)
|
||||
n->u.cleanup.prev_try = n_array[o->u.cleanup.prev_try->region_number];
|
||||
else
|
||||
n->u.cleanup.prev_try = prev_try;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (o->outer)
|
||||
n->outer = n_array[o->outer->region_number];
|
||||
if (o->inner)
|
||||
n->inner = n_array[o->inner->region_number];
|
||||
if (o->next_peer)
|
||||
n->next_peer = n_array[o->next_peer->region_number];
|
||||
}
|
||||
|
||||
/* Duplicate the EH regions of IFUN into current function, root the tree in
|
||||
OUTER_REGION and remap labels using MAP callback. */
|
||||
int
|
||||
duplicate_eh_regions (struct function *ifun, duplicate_eh_regions_map map,
|
||||
void *data, int outer_region)
|
||||
{
|
||||
int ifun_last_region_number = ifun->eh->last_region_number;
|
||||
struct eh_region **n_array, *root, *cur, *prev_try;
|
||||
int i;
|
||||
|
||||
if (ifun_last_region_number == 0 || !ifun->eh->region_tree)
|
||||
return 0;
|
||||
|
||||
n_array = xcalloc (ifun_last_region_number + 1, sizeof (*n_array));
|
||||
|
||||
/* Search for the containing ERT_TRY region to fix up
|
||||
the prev_try short-cuts for ERT_CLEANUP regions. */
|
||||
prev_try = NULL;
|
||||
if (outer_region > 0)
|
||||
for (prev_try = cfun->eh->region_array[outer_region];
|
||||
prev_try && prev_try->type != ERT_TRY;
|
||||
prev_try = prev_try->outer)
|
||||
;
|
||||
|
||||
for (i = 1; i <= ifun_last_region_number; ++i)
|
||||
{
|
||||
cur = ifun->eh->region_array[i];
|
||||
if (!cur || cur->region_number != i)
|
||||
continue;
|
||||
n_array[i] = duplicate_eh_region_1 (cur);
|
||||
if (cur->tree_label)
|
||||
{
|
||||
tree newlabel = map (cur->tree_label, data);
|
||||
n_array[i]->tree_label = newlabel;
|
||||
}
|
||||
else
|
||||
n_array[i]->tree_label = NULL;
|
||||
}
|
||||
for (i = 1; i <= ifun_last_region_number; ++i)
|
||||
{
|
||||
cur = ifun->eh->region_array[i];
|
||||
if (!cur || cur->region_number != i)
|
||||
continue;
|
||||
duplicate_eh_region_2 (cur, n_array, prev_try);
|
||||
}
|
||||
|
||||
root = n_array[ifun->eh->region_tree->region_number];
|
||||
gcc_assert (root->outer == NULL);
|
||||
if (outer_region > 0)
|
||||
{
|
||||
struct eh_region *cur = cfun->eh->region_array[outer_region];
|
||||
struct eh_region *p = cur->inner;
|
||||
|
||||
if (p)
|
||||
{
|
||||
while (p->next_peer)
|
||||
p = p->next_peer;
|
||||
p->next_peer = root;
|
||||
}
|
||||
else
|
||||
cur->inner = root;
|
||||
for (i = 1; i <= ifun_last_region_number; ++i)
|
||||
if (n_array[i] && n_array[i]->outer == NULL)
|
||||
n_array[i]->outer = cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct eh_region *p = cfun->eh->region_tree;
|
||||
if (p)
|
||||
{
|
||||
while (p->next_peer)
|
||||
p = p->next_peer;
|
||||
p->next_peer = root;
|
||||
}
|
||||
else
|
||||
cfun->eh->region_tree = root;
|
||||
}
|
||||
|
||||
free (n_array);
|
||||
|
||||
i = cfun->eh->last_region_number;
|
||||
cfun->eh->last_region_number = i + ifun_last_region_number;
|
||||
|
||||
collect_eh_region_array ();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
t2r_eq (const void *pentry, const void *pdata)
|
||||
{
|
||||
|
@ -2273,8 +2415,13 @@ reachable_next_level (struct eh_region *region, tree type_thrown,
|
|||
/* 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. */
|
||||
if (info && info->saw_any_handlers)
|
||||
the call is made by the runtime.
|
||||
|
||||
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. */
|
||||
|
||||
if ((info && info->saw_any_handlers) || !cfun->after_inlining)
|
||||
{
|
||||
add_reachable_handler (info, region, region);
|
||||
return RNL_CAUGHT;
|
||||
|
|
|
@ -81,6 +81,8 @@ extern void expand_eh_return (void);
|
|||
extern rtx expand_builtin_extend_pointer (tree);
|
||||
extern rtx get_exception_pointer (struct function *);
|
||||
extern rtx get_exception_filter (struct function *);
|
||||
typedef tree (*duplicate_eh_regions_map) (tree, void *);
|
||||
extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, void *, int);
|
||||
|
||||
extern void sjlj_emit_function_exit_after (rtx);
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@ struct function GTY(())
|
|||
|
||||
/* The control flow graph for this function. */
|
||||
struct control_flow_graph *cfg;
|
||||
bool after_inlining;
|
||||
|
||||
/* For tree-optimize.c. */
|
||||
|
||||
|
|
|
@ -823,6 +823,8 @@ label_to_block_fn (struct function *ifun, tree dest)
|
|||
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
|
||||
uid = LABEL_DECL_UID (dest);
|
||||
}
|
||||
if (VARRAY_SIZE (ifun->cfg->x_label_to_block_map) <= (unsigned int)uid)
|
||||
return NULL;
|
||||
return VARRAY_BB (ifun->cfg->x_label_to_block_map, uid);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,11 @@ add_stmt_to_eh_region_fn (struct function *ifun, tree t, int num)
|
|||
n->stmt = t;
|
||||
n->region_nr = num;
|
||||
|
||||
if (!get_eh_throw_stmt_table (ifun))
|
||||
set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash,
|
||||
struct_ptr_eq,
|
||||
ggc_free));
|
||||
|
||||
slot = htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT);
|
||||
gcc_assert (!*slot);
|
||||
*slot = n;
|
||||
|
|
|
@ -675,6 +675,7 @@ tree_rest_of_compilation (tree fndecl)
|
|||
We haven't necessarily assigned RTL to all variables yet, so it's
|
||||
not safe to try to expand expressions involving them. */
|
||||
cfun->x_dont_save_pending_sizes_p = 1;
|
||||
cfun->after_inlining = true;
|
||||
|
||||
node = cgraph_node (fndecl);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue