OSDN Git Service

2009-08-28 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / varpool.c
index a3af8c7..12cdad9 100644 (file)
@@ -1,12 +1,13 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
 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
@@ -15,9 +16,8 @@ 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"
@@ -33,6 +33,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "debug.h" 
 #include "target.h"
 #include "output.h"
+#include "gimple.h"
+#include "tree-flow.h"
 
 /*  This file contains basic routines manipulating variable pool.
 
@@ -56,10 +58,11 @@ struct varpool_node *varpool_nodes;
    The queue is maintained via mark_needed_node, linked via node->next_needed
    pointer. 
 
-   LAST_NNEDED_NODE points to the end of queue, so it can be maintained in forward
-   order.  QTY is needed to make it friendly to PCH.
+   LAST_NEEDED_NODE points to the end of queue, so it can be
+   maintained in forward order.  GTY is needed to make it friendly to
+   PCH.
  
-   During unit-at-a-time compilation we construct the queue of needed variables
+   During compilation we construct the queue of needed variables
    twice: first time it is during cgraph construction, second time it is at the
    end of compilation in VARPOOL_REMOVE_UNREFERENCED_DECLS so we can avoid
    optimized out variables being output.
@@ -157,10 +160,18 @@ dump_varpool (FILE *f)
   struct varpool_node *node;
 
   fprintf (f, "variable pool:\n\n");
-  for (node = varpool_nodes; node; node = node->next_needed)
+  for (node = varpool_nodes; node; node = node->next)
     dump_varpool_node (f, node);
 }
 
+/* Dump the variable pool to stderr.  */
+
+void
+debug_varpool (void)
+{
+  dump_varpool (stderr);
+}
+
 /* Given an assembler name, lookup node.  */
 struct varpool_node *
 varpool_node_for_asm (tree asmname)
@@ -212,16 +223,12 @@ varpool_reset_queue (void)
 
 /* Determine if variable DECL is needed.  That is, visible to something
    either outside this translation unit, something magic in the system
-   configury, or (if not doing unit-at-a-time) to something we haven't
-   seen yet.  */
+   configury */
 bool
 decide_is_variable_needed (struct varpool_node *node, tree decl)
 {
   /* If the user told us it is used, then it must be so.  */
-  if (node->externally_visible)
-    return true;
-  if (!flag_unit_at_a_time
-      && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+  if (node->externally_visible || node->force_output)
     return true;
 
   /* ??? If the assembler name is set by hand, it is possible to assemble
@@ -242,9 +249,20 @@ decide_is_variable_needed (struct varpool_node *node, tree decl)
       && !DECL_EXTERNAL (decl))
     return true;
 
+  /* When emulating tls, we actually see references to the control
+     variable, rather than the user-level variable.  */
+  if (!targetm.have_tls
+      && TREE_CODE (decl) == VAR_DECL
+      && DECL_THREAD_LOCAL_P (decl))
+    {
+      tree control = emutls_decl (decl);
+      if (decide_is_variable_needed (varpool_node (control), control))
+       return true;
+    }
+
   /* When not reordering top level variables, we have to assume that
      we are going to keep everything.  */
-  if (flag_unit_at_a_time && flag_toplevel_reorder)
+  if (flag_toplevel_reorder)
     return false;
 
   /* We want to emit COMDAT variables only when absolutely necessary.  */
@@ -267,7 +285,7 @@ varpool_finalize_decl (tree decl)
      if this function has already run.  */
   if (node->finalized)
     {
-      if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
+      if (cgraph_global_info_ready)
        varpool_assemble_pending_decls ();
       return;
     }
@@ -282,7 +300,7 @@ varpool_finalize_decl (tree decl)
      there.  */
   else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
     varpool_mark_needed_node (node);
-  if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
+  if (cgraph_global_info_ready)
     varpool_assemble_pending_decls ();
 }
 
@@ -344,7 +362,13 @@ varpool_assemble_decl (struct varpool_node *node)
       && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
     {
       assemble_variable (decl, 0, 1, 0);
-      return TREE_ASM_WRITTEN (decl);
+      if (TREE_ASM_WRITTEN (decl))
+       {
+         node->next_needed = varpool_assembled_nodes_queue;
+         varpool_assembled_nodes_queue = node;
+         node->finalized = 1;
+         return true;
+       }
     }
 
   return false;
@@ -374,10 +398,7 @@ varpool_remove_unreferenced_decls (void)
       node->needed = 0;
 
       if (node->finalized
-         && ((DECL_ASSEMBLER_NAME_SET_P (decl)
-              && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
-             || node->force_output
-             || decide_is_variable_needed (node, decl)
+         && (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
@@ -413,39 +434,58 @@ varpool_assemble_pending_decls (void)
 
       varpool_nodes_queue = varpool_nodes_queue->next_needed;
       if (varpool_assemble_decl (node))
-       {
-         changed = true;
-         node->next_needed = varpool_assembled_nodes_queue;
-         varpool_assembled_nodes_queue = node;
-         node->finalized = 1;
-       }
+       changed = true;
       else
         node->next_needed = NULL;
     }
+  /* varpool_nodes_queue is now empty, clear the pointer to the last element
+     in the queue.  */
+  varpool_last_needed_node = NULL;
   return changed;
 }
 
-/* Output all variables enqueued to be assembled.  */
+/* Remove all elements from the queue so we can re-use it for debug output.  */
 void
-varpool_output_debug_info (void)
+varpool_empty_needed_queue (void)
+{
+  /* EH might mark decls as needed during expansion.  This should be safe since
+     we don't create references to new function, but it should not be used
+     elsewhere.  */
+  varpool_analyze_pending_decls ();
+
+  while (varpool_nodes_queue)
+    {
+      struct varpool_node *node = varpool_nodes_queue;
+      varpool_nodes_queue = varpool_nodes_queue->next_needed;
+      node->next_needed = NULL;
+    }
+  /* varpool_nodes_queue is now empty, clear the pointer to the last element
+     in the queue.  */
+  varpool_last_needed_node = NULL;
+}
+
+/* Create a new global variable of type TYPE.  */
+tree
+add_new_static_var (tree type)
 {
-  timevar_push (TV_SYMOUT);
-  if (errorcount == 0 && sorrycount == 0)
-    while (varpool_assembled_nodes_queue)
-      {
-       struct varpool_node *node = varpool_assembled_nodes_queue;
-
-       /* Local static variables are never seen by check_global_declarations
-          so we need to output debug info by hand.  */
-       if (DECL_CONTEXT (node->decl)
-           && (TREE_CODE (DECL_CONTEXT (node->decl)) == BLOCK
-               || TREE_CODE (DECL_CONTEXT (node->decl)) == FUNCTION_DECL)
-           && errorcount == 0 && sorrycount == 0)
-            (*debug_hooks->global_decl) (node->decl);
-       varpool_assembled_nodes_queue = node->next_needed;
-       node->next_needed = 0;
-      }
-  timevar_pop (TV_SYMOUT);
+  tree new_decl;
+  struct varpool_node *new_node;
+
+  new_decl = create_tmp_var (type, NULL);
+  DECL_NAME (new_decl) = create_tmp_var_name (NULL);
+  TREE_READONLY (new_decl) = 0;
+  TREE_STATIC (new_decl) = 1;
+  TREE_USED (new_decl) = 1;
+  DECL_CONTEXT (new_decl) = NULL_TREE;
+  DECL_ABSTRACT (new_decl) = 0;
+  lang_hooks.dup_lang_specific_decl (new_decl);
+  create_var_ann (new_decl);
+  new_node = varpool_node (new_decl);
+  varpool_mark_needed_node (new_node);
+  add_referenced_var (new_decl);
+  varpool_finalize_decl (new_decl);
+
+  return new_node->decl;
 }
 
 #include "gt-varpool.h"