OSDN Git Service

/c-family
[pf3gnuchains/gcc-fork.git] / gcc / varpool.c
index 2a96d79..5d0eb68 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
@@ -241,6 +241,9 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
     fprintf (f, " output");
   if (node->externally_visible)
     fprintf (f, " externally_visible");
+  if (node->resolution != LDPR_UNKNOWN)
+    fprintf (f, " %s",
+            ld_plugin_symbol_resolution_names[(int)node->resolution]);
   if (node->in_other_partition)
     fprintf (f, " in_other_partition");
   else if (node->used_from_other_partition)
@@ -331,31 +334,24 @@ varpool_reset_queue (void)
 bool
 decide_is_variable_needed (struct varpool_node *node, tree decl)
 {
-  if (node->used_from_other_partition)
-    return true;
   /* If the user told us it is used, then it must be so.  */
-  if ((node->externally_visible && !DECL_COMDAT (decl))
-      || node->force_output)
+  if (node->force_output)
     return true;
 
+  gcc_assert (!DECL_EXTERNAL (decl));
+
   /* Externally visible variables must be output.  The exception is
      COMDAT variables that must be output only when they are needed.  */
   if (TREE_PUBLIC (decl)
-      && !flag_whole_program
-      && !flag_lto
       && !DECL_COMDAT (decl)
       && !DECL_EXTERNAL (decl))
     return true;
 
   /* When not reordering top level variables, we have to assume that
      we are going to keep everything.  */
-  if (flag_toplevel_reorder)
-    return false;
-
-  /* We want to emit COMDAT variables only when absolutely necessary.  */
-  if (DECL_COMDAT (decl))
-    return false;
-  return true;
+  if (!flag_toplevel_reorder)
+    return true;
+  return false;
 }
 
 /* Return if DECL is constant and its initial value is known (so we can do
@@ -374,7 +370,7 @@ const_value_known_p (tree decl)
 
   gcc_assert (TREE_CODE (decl) == VAR_DECL);
 
-  if (!TREE_READONLY (decl))
+  if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl))
     return false;
 
   /* Gimplifier takes away constructors of local vars  */
@@ -427,11 +423,6 @@ varpool_finalize_decl (tree decl)
 
   if (decide_is_variable_needed (node, decl))
     varpool_mark_needed_node (node);
-  /* Since we reclaim unreachable nodes at the end of every language
-     level unit, we need to be conservative about possible entry points
-     there.  */
-  else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
-    varpool_mark_needed_node (node);
   if (cgraph_global_info_ready)
     varpool_assemble_pending_decls ();
 }
@@ -557,18 +548,14 @@ varpool_remove_unreferenced_decls (void)
 
   while (node)
     {
-      tree decl = node->decl;
       next = node->next_needed;
       node->needed = 0;
 
-      if (node->finalized
-         && (decide_is_variable_needed (node, decl)
-             /* ??? Cgraph does not yet rule the world with an iron hand,
-                and does not control the emission of debug information.
-                After a variable has its DECL_RTL set, we must assume that
-                it may be referenced by the debug information, and we can
-                no longer elide it.  */
-             || DECL_RTL_SET_P (decl)))
+      if (node->analyzed
+         && (!varpool_can_remove_if_no_refs (node)
+             /* We just expanded all function bodies.  See if any of
+                them needed the variable.  */
+             || DECL_RTL_SET_P (node->decl)))
        varpool_mark_needed_node (node);
 
       node = next;
@@ -578,11 +565,29 @@ varpool_remove_unreferenced_decls (void)
   varpool_analyze_pending_decls ();
 }
 
+/* For variables in named sections make sure get_variable_section
+   is called before we switch to those sections.  Then section
+   conflicts between read-only and read-only requiring relocations
+   sections can be resolved.  */
+void
+varpool_finalize_named_section_flags (struct varpool_node *node)
+{
+  if (!TREE_ASM_WRITTEN (node->decl)
+      && !node->alias
+      && !node->in_other_partition
+      && !DECL_EXTERNAL (node->decl)
+      && TREE_CODE (node->decl) == VAR_DECL
+      && !DECL_HAS_VALUE_EXPR_P (node->decl)
+      && DECL_SECTION_NAME (node->decl))
+    get_variable_section (node->decl, false);
+}
+
 /* Output all variables enqueued to be assembled.  */
 bool
 varpool_assemble_pending_decls (void)
 {
   bool changed = false;
+  struct varpool_node *node;
 
   if (seen_error ())
     return false;
@@ -593,6 +598,9 @@ varpool_assemble_pending_decls (void)
      elsewhere.  */
   varpool_analyze_pending_decls ();
 
+  for (node = varpool_nodes_queue; node; node = node->next_needed)
+    varpool_finalize_named_section_flags (node);
+
   while (varpool_nodes_queue)
     {
       struct varpool_node *node = varpool_nodes_queue;