OSDN Git Service

2009-08-28 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / varpool.c
index 03c351b..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.
 
@@ -43,7 +45,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
     The varpool nodes are allocated lazily for declarations
     either by frontend or at callgraph construction time.
     All variables supposed to be output into final file needs to be
-    explicitely marked by frontend via VARPOOL_FINALIZE_DECL function.  */
+    explicitly marked by frontend via VARPOOL_FINALIZE_DECL function.  */
 
 /* Hash table used to convert declarations into nodes.  */
 static GTY((param_is (struct varpool_node))) htab_t varpool_hash;
@@ -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"