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:
Steven Bosscher 2005-05-12 19:29:21 +00:00 committed by Jan Hubicka
parent 1ed17cd539
commit 98f464e058
7 changed files with 177 additions and 2 deletions

View file

@ -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.

View file

@ -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;

View file

@ -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);

View file

@ -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. */

View file

@ -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);
}

View file

@ -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;

View file

@ -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);