]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
except.c (duplicate_eh_region_1, [...]): New functions, based on old implementation...
authorSteven Bosscher <stevenb@suse.de>
Thu, 12 May 2005 19:29:21 +0000 (19:29 +0000)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 12 May 2005 19:29:21 +0000 (19:29 +0000)
* 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

gcc/ChangeLog
gcc/except.c
gcc/except.h
gcc/function.h
gcc/tree-cfg.c
gcc/tree-eh.c
gcc/tree-optimize.c

index 566158517735c2313c317cb2a400d4210d42ee60..cb6bc1bc2395907a0b5b548a51eec191cbb02f07 100644 (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.
index 35105f9d7ad380827323b2047787c3fb855ce0e0..9f1bfe926af5972937687c3d897aa7a53042c8e0 100644 (file)
@@ -853,6 +853,148 @@ current_function_has_exception_handlers (void)
   return false;
 }
 \f
+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;
+}
+\f
 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;
index 746b3d4aca881bb9fc3949e5e57c1accec59cce3..9526b865909dd0e6a232e35b2eae91c783fa3135 100644 (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);
 
index 4f6181aa08c830b583cdd0969e46ff4d9ff0c8b5..0720c12ca5de3ad0696ce1e3804e3865a1f2ef12 100644 (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.  */
 
index c54305c898b5402de3e3887c9a647b6248197a6c..9860a29da006311c25f9c5508aadeeb78ce73268 100644 (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);
 }
 
index 72644aa0b0499cad0c425f88a2f017b02e459844..3bf58300d27e4fb844d58ccadd601af72a3419bc 100644 (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;
index 6e07a2b504f55d13b77055e49a9bf4d250ccd644..c3ceb31f59cc71bf64d435beef9463de9dd46288 100644 (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);