OSDN Git Service

2009-04-07 Bob Duff <duff@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / cgraphunit.c
index d011041..9f6a50d 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph based interprocedural optimizations.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
@@ -426,7 +426,7 @@ cgraph_process_new_functions (void)
        case CGRAPH_STATE_EXPANSION:
          /* Functions created during expansion shall be compiled
             directly.  */
-         node->output = 0;
+         node->process = 0;
          cgraph_expand_function (node);
          break;
 
@@ -452,12 +452,12 @@ cgraph_process_new_functions (void)
 static void
 cgraph_reset_node (struct cgraph_node *node)
 {
-  /* If node->output is set, then we have already begun whole-unit analysis.
+  /* If node->process is set, then we have already begun whole-unit analysis.
      This is *not* testing for whether we've already emitted the function.
      That case can be sort-of legitimately seen with real function redefinition
      errors.  I would argue that the front end should never present us with
      such a case, but don't enforce that for now.  */
-  gcc_assert (!node->output);
+  gcc_assert (!node->process);
 
   /* Reset our data structures so we can analyze the function again.  */
   memset (&node->local, 0, sizeof (node->local));
@@ -896,6 +896,15 @@ cgraph_analyze_functions (void)
        if (!edge->callee->reachable)
          cgraph_mark_reachable_node (edge->callee);
 
+      /* If decl is a clone of an abstract function, mark that abstract
+        function so that we don't release its body. The DECL_INITIAL() of that
+         abstract function declaration will be later needed to output debug info.  */
+      if (DECL_ABSTRACT_ORIGIN (decl))
+       {
+         struct cgraph_node *origin_node = cgraph_node (DECL_ABSTRACT_ORIGIN (decl));
+         origin_node->abstract_and_needed = true;
+       }
+
       /* We finalize local static variables during constructing callgraph
          edges.  Process their attributes too.  */
       process_function_and_variable_attributes (first_processed,
@@ -981,7 +990,7 @@ cgraph_mark_functions_to_output (void)
       tree decl = node->decl;
       struct cgraph_edge *e;
 
-      gcc_assert (!node->output);
+      gcc_assert (!node->process);
 
       for (e = node->callers; e; e = e->next_caller)
        if (e->inline_failed)
@@ -996,7 +1005,7 @@ cgraph_mark_functions_to_output (void)
              || (e && node->reachable))
          && !TREE_ASM_WRITTEN (decl)
          && !DECL_EXTERNAL (decl))
-       node->output = 1;
+       node->process = 1;
       else
        {
          /* We should've reclaimed all functions that are not needed.  */
@@ -1029,6 +1038,7 @@ cgraph_expand_function (struct cgraph_node *node)
   gcc_assert (!node->global.inlined_to);
 
   announce_function (decl);
+  node->process = 0;
 
   gcc_assert (node->lowered);
 
@@ -1052,7 +1062,7 @@ cgraph_expand_function (struct cgraph_node *node)
 /* Return true when CALLER_DECL should be inlined into CALLEE_DECL.  */
 
 bool
-cgraph_inline_p (struct cgraph_edge *e, const char **reason)
+cgraph_inline_p (struct cgraph_edge *e, cgraph_inline_failed_t *reason)
 {
   *reason = e->inline_failed;
   return !e->inline_failed;
@@ -1084,16 +1094,16 @@ cgraph_expand_all_functions (void)
   /* Garbage collector may remove inline clones we eliminate during
      optimization.  So we must be sure to not reference them.  */
   for (i = 0; i < order_pos; i++)
-    if (order[i]->output)
+    if (order[i]->process)
       order[new_order_pos++] = order[i];
 
   for (i = new_order_pos - 1; i >= 0; i--)
     {
       node = order[i];
-      if (node->output)
+      if (node->process)
        {
          gcc_assert (node->reachable);
-         node->output = 0;
+         node->process = 0;
          cgraph_expand_function (node);
        }
     }
@@ -1142,7 +1152,7 @@ cgraph_output_in_order (void)
 
   for (pf = cgraph_nodes; pf; pf = pf->next)
     {
-      if (pf->output)
+      if (pf->process)
        {
          i = pf->order;
          gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
@@ -1182,7 +1192,7 @@ cgraph_output_in_order (void)
       switch (nodes[i].kind)
        {
        case ORDER_FUNCTION:
-         nodes[i].u.f->output = 0;
+         nodes[i].u.f->process = 0;
          cgraph_expand_function (nodes[i].u.f);
          break;
 
@@ -1304,7 +1314,6 @@ cgraph_optimize (void)
 
       varpool_assemble_pending_decls ();
     }
-  varpool_output_debug_info ();
   cgraph_process_new_functions ();
   cgraph_state = CGRAPH_STATE_FINISHED;
 
@@ -1417,7 +1426,14 @@ update_call_expr (struct cgraph_node *new_version)
 
   /* Update the call expr on the edges to call the new version.  */
   for (e = new_version->callers; e; e = e->next_caller)
-    gimple_call_set_fndecl (e->call_stmt, new_version->decl);
+    {
+      struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->decl);
+      gimple_call_set_fndecl (e->call_stmt, new_version->decl);
+      /* Update EH information too, just in case.  */
+      if (!stmt_could_throw_p (e->call_stmt)
+          && lookup_stmt_eh_region_fn (inner_function, e->call_stmt))
+        remove_stmt_from_eh_region_fn (inner_function, e->call_stmt);
+    }
 }
 
 
@@ -1524,20 +1540,25 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
 
   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
   tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip);
-  /* Update the call_expr on the edges to call the new version node. */
-  update_call_expr (new_version_node);
 
   /* Update the new version's properties.
-     Make The new version visible only within this translation unit.
+     Make The new version visible only within this translation unit.  Make sure
+     that is not weak also.
      ??? We cannot use COMDAT linkage because there is no
      ABI support for this.  */
   DECL_EXTERNAL (new_version_node->decl) = 0;
   DECL_ONE_ONLY (new_version_node->decl) = 0;
   TREE_PUBLIC (new_version_node->decl) = 0;
   DECL_COMDAT (new_version_node->decl) = 0;
+  DECL_WEAK (new_version_node->decl) = 0;
+  DECL_VIRTUAL_P (new_version_node->decl) = 0;
   new_version_node->local.externally_visible = 0;
   new_version_node->local.local = 1;
   new_version_node->lowered = true;
+
+  /* Update the call_expr on the edges to call the new version node. */
+  update_call_expr (new_version_node);
+  
   cgraph_call_function_insertion_hooks (new_version_node);
   return new_version_node;
 }