OSDN Git Service

2007-08-26 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / ipa.c
index 44b0456..918225d 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -1,11 +1,11 @@
 /* Basic IPA optimizations and utilities.
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.  
+   Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.  
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -14,15 +14,16 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "cgraph.h"
+#include "tree-pass.h"
+#include "timevar.h"
 
 /* Fill array order with all nodes with output flag set in the reverse
    topological order.  */
@@ -56,7 +57,7 @@ cgraph_postorder (struct cgraph_node **order)
          {
            while (node2->aux != &last)
              {
-               edge = node2->aux;
+               edge = (struct cgraph_edge *) node2->aux;
                if (edge->next_caller)
                  node2->aux = edge->next_caller;
                else
@@ -96,8 +97,8 @@ cgraph_postorder (struct cgraph_node **order)
 bool
 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 {
-  struct cgraph_node *first = (void *) 1;
-  struct cgraph_node *node;
+  struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
+  struct cgraph_node *node, *next;
   bool changed = false;
   int insns = 0;
 
@@ -129,7 +130,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
     {
       struct cgraph_edge *e;
       node = first;
-      first = first->aux;
+      first = (struct cgraph_node *) first->aux;
 
       for (e = node->callees; e; e = e->next_callee)
        if (!e->callee->aux
@@ -151,8 +152,9 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
      unanalyzed nodes so they look like for true extern functions to the rest
      of code.  Body of such functions is released via remove_node once the
      inline clones are eliminated.  */
-  for (node = cgraph_nodes; node; node = node->next)
+  for (node = cgraph_nodes; node; node = next)
     {
+      next = node->next;
       if (!node->aux)
        {
          int local_insns;
@@ -185,9 +187,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
                      break;
                  if (!clone)
                    {
-                     DECL_SAVED_TREE (node->decl) = NULL;
-                     DECL_STRUCT_FUNCTION (node->decl) = NULL;
-                     DECL_INITIAL (node->decl) = error_mark_node;
+                     cgraph_release_function_body (node);
                      node->analyzed = false;
                    }
                  cgraph_node_remove_callees (node);
@@ -205,5 +205,91 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
     node->aux = NULL;
   if (file)
     fprintf (file, "\nReclaimed %i insns", insns);
+#ifdef ENABLE_CHECKING
+  verify_cgraph ();
+#endif
   return changed;
 }
+
+/* Mark visibility of all functions.
+
+   A local function is one whose calls can occur only in the current
+   compilation unit and all its calls are explicit, so we can change
+   its calling convention.  We simply mark all static functions whose
+   address is not taken as local.
+
+   We also change the TREE_PUBLIC flag of all declarations that are public
+   in language point of view but we want to overwrite this default
+   via visibilities for the backend point of view.  */
+
+static unsigned int
+function_and_variable_visibility (void)
+{
+  struct cgraph_node *node;
+  struct varpool_node *vnode;
+
+  for (node = cgraph_nodes; node; node = node->next)
+    {
+      if (node->reachable
+         && (DECL_COMDAT (node->decl)
+             || (!flag_whole_program
+                 && TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl))))
+       node->local.externally_visible = true;
+      if (!node->local.externally_visible && node->analyzed
+         && !DECL_EXTERNAL (node->decl))
+       {
+         gcc_assert (flag_whole_program || !TREE_PUBLIC (node->decl));
+         TREE_PUBLIC (node->decl) = 0;
+       }
+      node->local.local = (!node->needed
+                          && node->analyzed
+                          && !DECL_EXTERNAL (node->decl)
+                          && !node->local.externally_visible);
+    }
+  for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+    {
+      if (vnode->needed
+         && !flag_whole_program
+         && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)))
+       vnode->externally_visible = 1;
+      if (!vnode->externally_visible)
+       {
+         gcc_assert (flag_whole_program || !TREE_PUBLIC (vnode->decl));
+         TREE_PUBLIC (vnode->decl) = 0;
+       }
+     gcc_assert (TREE_STATIC (vnode->decl));
+    }
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "\nMarking local functions:");
+      for (node = cgraph_nodes; node; node = node->next)
+       if (node->local.local)
+         fprintf (dump_file, " %s", cgraph_node_name (node));
+      fprintf (dump_file, "\n\n");
+      fprintf (dump_file, "\nMarking externally visible functions:");
+      for (node = cgraph_nodes; node; node = node->next)
+       if (node->local.externally_visible)
+         fprintf (dump_file, " %s", cgraph_node_name (node));
+      fprintf (dump_file, "\n\n");
+    }
+  cgraph_function_flags_ready = true;
+  return 0;
+}
+
+struct tree_opt_pass pass_ipa_function_and_variable_visibility = 
+{
+  "visibility",                                /* name */
+  NULL,                                        /* gate */
+  function_and_variable_visibility,    /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_CGRAPHOPT,                                /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_remove_functions | TODO_dump_cgraph,/* todo_flags_finish */
+  0                                    /* letter */
+};