From fad41cd7d43ffce40a20f11cfbe68da548ef6b79 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 22 Mar 2006 04:50:45 -0800 Subject: [PATCH] re PR middle-end/26084 (ICE (segfault) on C++ OpenMP code) PR middle-end/26084 * except.c (duplicate_eh_regions_0): New. (duplicate_eh_region_1): Duplicate the children of the node as well as the node itself. Link them up properly. (duplicate_eh_region_2): Merge into ... (duplicate_eh_regions): ... here. Take copy_region argument, and copy only a sub-tree if asked. Simplify copying and fixup. (eh_region_outer_p): New. * except.h (duplicate_eh_regions): Update decl. (eh_region_outer_p): Declare. * omp-low.c (lower_omp_single): Fix eh region placement wrt OMP_RETURN. (lower_omp_master): Likewise. (lower_omp_ordered): Likewise. * tree-cfg.c (struct move_stmt_d): Add new_label_map. (move_stmt_r): Use it to remap labels. Handle recursion vs remap_decls_p properly. (move_block_to_fn): Pass in new_label_map. Remap RESX_EXPR. (find_outermost_region_in_block): New. (new_label_mapper): New. (move_sese_region_to_fn): Copy eh information to the new function properly. * tree-inline.c (copy_cfg_body): Update for new duplicate_eh_regions argument. * tree-pretty-print.c (dump_generic_node): Dump RESX_EXPR region number. From-SVN: r112283 --- gcc/ChangeLog | 28 ++++ gcc/except.c | 283 +++++++++++++++++++++++++--------------- gcc/except.h | 4 +- gcc/omp-low.c | 9 +- gcc/tree-cfg.c | 147 ++++++++++++++++++--- gcc/tree-inline.c | 3 +- gcc/tree-pretty-print.c | 4 +- 7 files changed, 345 insertions(+), 133 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f5c7e889872..1f564ad23da3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2006-03-22 Richard Henderson + + PR middle-end/26084 + * except.c (duplicate_eh_regions_0): New. + (duplicate_eh_region_1): Duplicate the children of the node as + well as the node itself. Link them up properly. + (duplicate_eh_region_2): Merge into ... + (duplicate_eh_regions): ... here. Take copy_region argument, and + copy only a sub-tree if asked. Simplify copying and fixup. + (eh_region_outer_p): New. + * except.h (duplicate_eh_regions): Update decl. + (eh_region_outer_p): Declare. + * omp-low.c (lower_omp_single): Fix eh region placement wrt OMP_RETURN. + (lower_omp_master): Likewise. + (lower_omp_ordered): Likewise. + * tree-cfg.c (struct move_stmt_d): Add new_label_map. + (move_stmt_r): Use it to remap labels. Handle recursion vs + remap_decls_p properly. + (move_block_to_fn): Pass in new_label_map. Remap RESX_EXPR. + (find_outermost_region_in_block): New. + (new_label_mapper): New. + (move_sese_region_to_fn): Copy eh information to the new function + properly. + * tree-inline.c (copy_cfg_body): Update for new duplicate_eh_regions + argument. + * tree-pretty-print.c (dump_generic_node): Dump RESX_EXPR region + number. + 2006-03-22 Richard Sandiford * doc/md.texi (-mshared): Mention that -mshared code can be linked diff --git a/gcc/except.c b/gcc/except.c index 7c0088e123a3..01f11087c3bd 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -857,84 +857,145 @@ 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; +/* A subroutine of duplicate_eh_regions. Search the region tree under O + for the miniumum and maximum region numbers. Update *MIN and *MAX. */ - n->region_number = o->region_number + cfun->eh->last_region_number; - VEC_replace (eh_region, cfun->eh->region_array, n->region_number, n); - gcc_assert (!o->aka); +static void +duplicate_eh_regions_0 (eh_region o, int *min, int *max) +{ + if (o->region_number < *min) + *min = o->region_number; + if (o->region_number > *max) + *max = o->region_number; - return n; + if (o->inner) + { + o = o->inner; + duplicate_eh_regions_0 (o, min, max); + while (o->next_peer) + { + o = o->next_peer; + duplicate_eh_regions_0 (o, min, max); + } + } } -static void -duplicate_eh_region_2 (struct eh_region *o, struct eh_region **n_array, - struct eh_region *prev_try) +/* A subroutine of duplicate_eh_regions. Copy the region tree under OLD. + Root it at OUTER, and apply EH_OFFSET to the region number. Don't worry + about the other internal pointers just yet, just the tree-like pointers. */ + +static eh_region +duplicate_eh_regions_1 (eh_region old, eh_region outer, int eh_offset) { - struct eh_region *n = n_array[o->region_number]; + eh_region ret, n; - 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; + ret = n = ggc_alloc (sizeof (struct eh_region)); - 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; + *n = *old; + n->outer = outer; + gcc_assert (!old->aka); - 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; + n->region_number += eh_offset; + VEC_replace (eh_region, cfun->eh->region_array, n->region_number, n); - default: - break; + if (old->inner) + { + old = old->inner; + n = n->inner = duplicate_eh_regions_1 (old, ret, eh_offset); + while (old->next_peer) + { + old = old->next_peer; + n = n->next_peer = duplicate_eh_regions_1 (old, ret, eh_offset); + } } - 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]; + return ret; } -/* Duplicate the EH regions of IFUN into current function, root the tree in - OUTER_REGION and remap labels using MAP callback. */ +/* Duplicate the EH regions of IFUN, rootted at COPY_REGION, into current + function and root the tree below OUTER_REGION. Remap labels using MAP + callback. The special case of COPY_REGION of 0 means all regions. */ + int duplicate_eh_regions (struct function *ifun, duplicate_eh_regions_map map, - void *data, int outer_region) + void *data, int copy_region, int outer_region) { - int ifun_last_region_number = ifun->eh->last_region_number; - struct eh_region **n_array, *root, *cur, *prev_try; - int i; + eh_region cur, prev_try, outer, *splice; + int i, min_region, max_region, eh_offset, cfun_last_region_number; + int num_regions; - if (ifun_last_region_number == 0 || !ifun->eh->region_tree) + if (!ifun->eh->region_tree) return 0; - n_array = xcalloc (ifun_last_region_number + 1, sizeof (*n_array)); + /* Find the range of region numbers to be copied. The interface we + provide here mandates a single offset to find new number from old, + which means we must look at the numbers present, instead of the + count or something else. */ + if (copy_region > 0) + { + min_region = INT_MAX; + max_region = 0; + + cur = VEC_index (eh_region, ifun->eh->region_array, copy_region); + duplicate_eh_regions_0 (cur, &min_region, &max_region); + } + else + min_region = 1, max_region = ifun->eh->last_region_number; + num_regions = max_region - min_region + 1; + cfun_last_region_number = cfun->eh->last_region_number; + eh_offset = cfun_last_region_number + 1 - min_region; + + /* If we've not yet created a region array, do so now. */ VEC_safe_grow (eh_region, gc, cfun->eh->region_array, - cfun->eh->last_region_number + 1 + ifun_last_region_number); + cfun_last_region_number + 1 + num_regions); + cfun->eh->last_region_number = max_region + eh_offset; - /* We might've created new cfun->eh->region_array so zero out nonexisting region 0. */ + /* We may have just allocated the array for the first time. + Make sure that element zero is null. */ VEC_replace (eh_region, cfun->eh->region_array, 0, 0); - for (i = cfun->eh->last_region_number + 1; - i < cfun->eh->last_region_number + 1 + ifun_last_region_number; i++) - VEC_replace (eh_region, cfun->eh->region_array, i, 0); + /* Zero all entries in the range allocated. */ + memset (VEC_address (eh_region, cfun->eh->region_array) + + cfun_last_region_number + 1, 0, num_regions); + + /* Locate the spot at which to insert the new tree. */ + if (outer_region > 0) + { + outer = VEC_index (eh_region, cfun->eh->region_array, outer_region); + splice = &outer->inner; + } + else + { + outer = NULL; + splice = &cfun->eh->region_tree; + } + while (*splice) + splice = &(*splice)->next_peer; + + /* Copy all the regions in the subtree. */ + if (copy_region > 0) + { + cur = VEC_index (eh_region, ifun->eh->region_array, copy_region); + *splice = duplicate_eh_regions_1 (cur, outer, eh_offset); + } + else + { + eh_region n; + + cur = ifun->eh->region_tree; + *splice = n = duplicate_eh_regions_1 (cur, outer, eh_offset); + while (cur->next_peer) + { + cur = cur->next_peer; + n = n->next_peer = duplicate_eh_regions_1 (cur, outer, eh_offset); + } + } + + /* Remap all the labels in the new regions. */ + for (i = cfun_last_region_number + 1; + VEC_iterate (eh_region, cfun->eh->region_array, i, cur); ++i) + if (cur && cur->tree_label) + cur->tree_label = map (cur->tree_label, data); /* Search for the containing ERT_TRY region to fix up the prev_try short-cuts for ERT_CLEANUP regions. */ @@ -945,67 +1006,77 @@ duplicate_eh_regions (struct function *ifun, duplicate_eh_regions_map map, prev_try = prev_try->outer) ; - for (i = 1; i <= ifun_last_region_number; ++i) - { - cur = VEC_index (eh_region, 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) + /* Remap all of the internal catch and cleanup linkages. Since we + duplicate entire subtrees, all of the referenced regions will have + been copied too. And since we renumbered them as a block, a simple + bit of arithmetic finds us the index for the replacement region. */ + for (i = cfun_last_region_number + 1; + VEC_iterate (eh_region, cfun->eh->region_array, i, cur); ++i) { - cur = VEC_index (eh_region, ifun->eh->region_array, i); - if (!cur || cur->region_number != i) + if (cur == NULL) 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 - = VEC_index (eh_region, cfun->eh->region_array, outer_region); - struct eh_region *p = cur->inner; +#define REMAP(REG) \ + (REG) = VEC_index (eh_region, cfun->eh->region_array, \ + (REG)->region_number + eh_offset) - if (p) + switch (cur->type) { - 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; + case ERT_TRY: + if (cur->u.try.catch) + REMAP (cur->u.try.catch); + if (cur->u.try.last_catch) + REMAP (cur->u.try.last_catch); + break; + + case ERT_CATCH: + if (cur->u.catch.next_catch) + REMAP (cur->u.catch.next_catch); + if (cur->u.catch.prev_catch) + REMAP (cur->u.catch.prev_catch); + break; + + case ERT_CLEANUP: + if (cur->u.cleanup.prev_try) + REMAP (cur->u.cleanup.prev_try); + else + cur->u.cleanup.prev_try = prev_try; + break; + + default: + break; } - else - cfun->eh->region_tree = root; + +#undef REMAP } - free (n_array); + return eh_offset; +} - i = cfun->eh->last_region_number; - cfun->eh->last_region_number = i + ifun_last_region_number; +/* Return true if REGION_A is outer to REGION_B in IFUN. */ - return i; +bool +eh_region_outer_p (struct function *ifun, int region_a, int region_b) +{ + struct eh_region *rp_a, *rp_b; + + gcc_assert (ifun->eh->last_region_number > 0); + gcc_assert (ifun->eh->region_tree); + + rp_a = VEC_index (eh_region, ifun->eh->region_array, region_a); + rp_b = VEC_index (eh_region, ifun->eh->region_array, region_b); + gcc_assert (rp_a != NULL); + gcc_assert (rp_b != NULL); + + do + { + if (rp_a == rp_b) + return true; + rp_b = rp_b->outer; + } + while (rp_b); + + return false; } static int diff --git a/gcc/except.h b/gcc/except.h index 46914d4205ce..5b28296c8b46 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -82,7 +82,8 @@ 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 int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, + void *, int, int); extern void sjlj_emit_function_exit_after (rtx); extern void default_init_unwind_resume_libfunc (void); @@ -106,6 +107,7 @@ extern void collect_eh_region_array (void); extern void expand_resx_expr (tree); extern void verify_eh_tree (struct function *); extern void dump_eh_tree (FILE *, struct function *); +extern bool eh_region_outer_p (struct function *, int, int); /* tree-eh.c */ extern void add_stmt_to_eh_region_fn (struct function *, tree, int); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 65f7151b0cec..41b4093e692d 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3464,6 +3464,9 @@ lower_omp_sections (tree *stmt_p, omp_context *ctx) new_body = alloc_stmt_list (); append_to_statement_list (ilist, &new_body); append_to_statement_list (stmt, &new_body); + /* ??? The OMP_RETURN doesn't logically belong here, but in + expand_omp_sections we expect this marker to be where the + individual sections join after completing the loop. */ append_to_statement_list (region_exit, &new_body); append_to_statement_list (olist, &new_body); append_to_statement_list (dlist, &new_body); @@ -3610,9 +3613,9 @@ lower_omp_single (tree *stmt_p, omp_context *ctx) lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind)); append_to_statement_list (dlist, &BIND_EXPR_BODY (bind)); + maybe_catch_exception (&BIND_EXPR_BODY (bind)); t = make_node (OMP_RETURN_EXPR); append_to_statement_list (t, &BIND_EXPR_BODY (bind)); - maybe_catch_exception (&BIND_EXPR_BODY (bind)); pop_gimplify_context (bind); BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); @@ -3647,9 +3650,9 @@ lower_omp_master (tree *stmt_p, omp_context *ctx) x = build1 (LABEL_EXPR, void_type_node, lab); gimplify_and_add (x, &BIND_EXPR_BODY (bind)); + maybe_catch_exception (&BIND_EXPR_BODY (bind)); x = make_node (OMP_RETURN_EXPR); append_to_statement_list (x, &BIND_EXPR_BODY (bind)); - maybe_catch_exception (&BIND_EXPR_BODY (bind)); pop_gimplify_context (bind); BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); @@ -3683,9 +3686,9 @@ lower_omp_ordered (tree *stmt_p, omp_context *ctx) x = built_in_decls[BUILT_IN_GOMP_ORDERED_END]; x = build_function_call_expr (x, NULL); gimplify_and_add (x, &BIND_EXPR_BODY (bind)); + maybe_catch_exception (&BIND_EXPR_BODY (bind)); x = make_node (OMP_RETURN_EXPR); append_to_statement_list (x, &BIND_EXPR_BODY (bind)); - maybe_catch_exception (&BIND_EXPR_BODY (bind)); pop_gimplify_context (bind); BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index b7f147ce77f2..6f0e947f9432 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -4591,6 +4591,7 @@ struct move_stmt_d tree from_context; tree to_context; bitmap vars_to_remove; + htab_t new_label_map; bool remap_decls_p; }; @@ -4599,39 +4600,62 @@ struct move_stmt_d variable referenced in *TP. */ static tree -move_stmt_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) +move_stmt_r (tree *tp, int *walk_subtrees, void *data) { struct move_stmt_d *p = (struct move_stmt_d *) data; + tree t = *tp; - if (p->block && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (*tp)))) - TREE_BLOCK (*tp) = p->block; + if (p->block && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t)))) + TREE_BLOCK (t) = p->block; - if (OMP_DIRECTIVE_P (*tp)) + if (OMP_DIRECTIVE_P (t) && TREE_CODE (t) != OMP_RETURN_EXPR) { /* Do not remap variables inside OMP directives. Variables referenced in clauses and directive header belong to the parent function and should not be moved into the child function. */ + bool save_remap_decls_p = p->remap_decls_p; p->remap_decls_p = false; - } + *walk_subtrees = 0; + + walk_tree (&OMP_BODY (t), move_stmt_r, p, NULL); - if (p->remap_decls_p - && DECL_P (*tp) - && DECL_CONTEXT (*tp) == p->from_context) + p->remap_decls_p = save_remap_decls_p; + } + else if (DECL_P (t) && DECL_CONTEXT (t) == p->from_context) { - DECL_CONTEXT (*tp) = p->to_context; + if (TREE_CODE (t) == LABEL_DECL) + { + if (p->new_label_map) + { + struct tree_map in, *out; + in.from = t; + out = htab_find_with_hash (p->new_label_map, &in, DECL_UID (t)); + if (out) + *tp = t = out->to; + } - if (TREE_CODE (*tp) == VAR_DECL) + DECL_CONTEXT (t) = p->to_context; + } + else if (p->remap_decls_p) { - struct function *f = DECL_STRUCT_FUNCTION (p->to_context); - f->unexpanded_var_list = tree_cons (0, *tp, f->unexpanded_var_list); + DECL_CONTEXT (t) = p->to_context; - /* Mark *TP to be removed from the original function, - otherwise it will be given a DECL_RTL when the original - function is expanded. */ - bitmap_set_bit (p->vars_to_remove, DECL_UID (*tp)); + if (TREE_CODE (t) == VAR_DECL) + { + struct function *f = DECL_STRUCT_FUNCTION (p->to_context); + f->unexpanded_var_list + = tree_cons (0, t, f->unexpanded_var_list); + + /* Mark T to be removed from the original function, + otherwise it will be given a DECL_RTL when the + original function is expanded. */ + bitmap_set_bit (p->vars_to_remove, DECL_UID (t)); + } } } + else if (TYPE_P (t)) + *walk_subtrees = 0; return NULL_TREE; } @@ -4650,7 +4674,7 @@ move_stmt_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) static void move_block_to_fn (struct function *dest_cfun, basic_block bb, basic_block after, bool update_edge_count_p, - bitmap vars_to_remove) + bitmap vars_to_remove, htab_t new_label_map, int eh_offset) { struct control_flow_graph *cfg; edge_iterator ei; @@ -4701,10 +4725,12 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) { tree stmt = bsi_stmt (si); + int region; d.from_context = cfun->decl; d.to_context = dest_cfun->decl; d.remap_decls_p = true; + d.new_label_map = new_label_map; if (TREE_BLOCK (stmt)) d.block = DECL_INITIAL (dest_cfun->decl); @@ -4736,11 +4762,66 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, if (uid >= dest_cfun->last_label_uid) dest_cfun->last_label_uid = uid + 1; } + else if (TREE_CODE (stmt) == RESX_EXPR && eh_offset != 0) + TREE_OPERAND (stmt, 0) = + build_int_cst (NULL_TREE, + TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0)) + + eh_offset); + + region = lookup_stmt_eh_region (stmt); + if (region >= 0) + { + add_stmt_to_eh_region_fn (dest_cfun, stmt, region + eh_offset); + remove_stmt_from_eh_region (stmt); + } + } +} + +/* Examine the statements in BB (which is in SRC_CFUN); find and return + the outermost EH region. Use REGION as the incoming base EH region. */ + +static int +find_outermost_region_in_block (struct function *src_cfun, + basic_block bb, int region) +{ + block_stmt_iterator si; + + for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) + { + tree stmt = bsi_stmt (si); + int stmt_region; - remove_stmt_from_eh_region (stmt); + stmt_region = lookup_stmt_eh_region_fn (src_cfun, stmt); + if (stmt_region > 0 + && (region < 0 || eh_region_outer_p (src_cfun, stmt_region, region))) + region = stmt_region; } + + return region; } +static tree +new_label_mapper (tree decl, void *data) +{ + htab_t hash = (htab_t) data; + struct tree_map *m; + void **slot; + + gcc_assert (TREE_CODE (decl) == LABEL_DECL); + + m = xmalloc (sizeof (struct tree_map)); + m->hash = DECL_UID (decl); + m->from = decl; + m->to = create_artificial_label (); + LABEL_DECL_UID (m->to) = LABEL_DECL_UID (decl); + + slot = htab_find_slot_with_hash (hash, m, m->hash, INSERT); + gcc_assert (*slot == NULL); + + *slot = m; + + return m->to; +} /* Move a single-entry, single-exit region delimited by ENTRY_BB and EXIT_BB to function DEST_CFUN. The whole region is replaced by a @@ -4763,11 +4844,12 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, VEC(basic_block,heap) *bbs; basic_block after, bb, *entry_pred, *exit_succ; struct function *saved_cfun; - int *entry_flag, *exit_flag; + int *entry_flag, *exit_flag, eh_offset; unsigned i, num_entry_edges, num_exit_edges; edge e; edge_iterator ei; bitmap vars_to_remove; + htab_t new_label_map; saved_cfun = cfun; @@ -4813,7 +4895,28 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, /* Switch context to the child function to initialize DEST_FN's CFG. */ gcc_assert (dest_cfun->cfg == NULL); cfun = dest_cfun; + init_empty_tree_cfg (); + + /* Initialize EH information for the new function. */ + eh_offset = 0; + new_label_map = NULL; + if (saved_cfun->eh) + { + int region = -1; + + for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++) + region = find_outermost_region_in_block (saved_cfun, bb, region); + + init_eh_for_function (); + if (region != -1) + { + new_label_map = htab_create (17, tree_map_hash, tree_map_eq, free); + eh_offset = duplicate_eh_regions (saved_cfun, new_label_mapper, + new_label_map, region, 0); + } + } + cfun = saved_cfun; /* Move blocks from BBS into DEST_CFUN. */ @@ -4825,10 +4928,14 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, /* No need to update edge counts on the last block. It has already been updated earlier when we detached the region from the original CFG. */ - move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_to_remove); + move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_to_remove, + new_label_map, eh_offset); after = bb; } + if (new_label_map) + htab_delete (new_label_map); + /* Remove the variables marked in VARS_TO_REMOVE from CFUN->UNEXPANDED_VAR_LIST. Otherwise, they will be given a DECL_RTL in the context of CFUN. */ diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 8d258ffd0c5a..3e35842a76e7 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -924,7 +924,8 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency, if (id->transform_new_cfg) init_eh_for_function (); id->eh_region_offset - = duplicate_eh_regions (cfun_to_copy, remap_decl_1, id, id->eh_region); + = duplicate_eh_regions (cfun_to_copy, remap_decl_1, id, + 0, id->eh_region); } /* Use aux pointers to map the original blocks to copy. */ FOR_EACH_BB_FN (bb, cfun_to_copy) diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 23bea8391627..a8a33a50fcfc 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -1557,8 +1557,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, break; case RESX_EXPR: - pp_string (buffer, "resx"); - /* ??? Any sensible way to present the eh region? */ + pp_string (buffer, "resx "); + dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false); break; case ASM_EXPR: -- 2.43.5