This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Move varpool stuff into varpool.c and drop cgraph_ in cgraph_varpool prefix.


Hi,
this patch moves all varpool related stuff into separate file.   The
varpool was originally created in order to help cgraph conversion
proceed but it does not really belong into cgraph/cgraphunit files.
In general I would hope to find better places for most of what is in
cgraphunit.c together with sanitizing the interfaces.  That file was
originally invented in order to avoid unresolved symbols on walk_tree
for frontends still not doing function-at-a-time.

There are no functional changes, just move the code around, update
comments and drop cgraph_ prefix, as cgraph_varpool_whatever was little
bit too long and illogical.

Earlier version of the patch bootstrapped/regtested i686-linux, I am
re-testing current version and will commit it after testing of there are
no complains.

In incremental patch I would like to make little sanitization to the
varpool API, but overall I hope it is pretty manageable as it is now.
In particular I would like to make abstraction for IPA passes who are
interested to either walk all variables or all static initializers.
I am not sure if there was some consensus, but is there some reason to
preffer iterators over FOR_EACH_STATIC_INITIALIZER macro?
I find the second little bit more readable in such a simple context, but 
I see it is not terribly consistent.

Honza

	Move all varpool routines out of cgraph/cgraphunit to varpool.c
	* cgraph.c: Update comments.
	(cgraph_varpool_hash,
	cgraph_varpool_nodes, cgraph_varpool_last_needed_node
	cgraph_varpool_node_name, cgraph_varpool_node,
	cgraph_varpol_mode_for_asm, cgraph_varpool_mark_needed_node,
	cgraph_variable_initializer_availability): Move to
	varpool.c and drop cgraph_ prefixes.
	(cgraph_varpool_enqueue_needed_node, cgraph_varpool_reset_queue,
	cgraph_varpool_first_unanalyzed_node, cgraph_varpool_finalize_decl):
	move to varpool.c; drop cgraph_ prefix; make static.
	(dump_cgraph_varpool_node): Move to varpool.c under name
	dump_varpool_node.
	(dump_varpool, hash_varpool_node, eq_varpool_node,
	decide_is_variable_needed): Move to varpool.c
	(decl_assembler_name_equal): Move to tree.c.
	(availability_names): Rename to ...
	(cgraph_availability_names): ... this one.
	(dump_cgraph_node): Update.
	* cgraph.h: Reorder declarations now in varpool.c
	(cgraph_vailablity_names): Declare.
	(struct cgraph_varpool_node): Rename to ...
	(struct varpool_node): ... this one.
	(cgraph_varpool_first_unanalyzed_node, cgraph_varpool_nodes_queue,
	cgraph_varpool_first_unanalyzed_node, cgraph_varpool_node,
	cgraph_varpool_node_for_asm, cgraph_varpool_mark_needed_node,
	cgraph_varpool_finalize_decl, cgraph_varpool_enqueue_needed_node,
	cgraph_varpool_reset_queue, cgraph_varpool_assemble_pending_decls,
	cgraph_variable_initializer_availability): Rename to ...
	(varpool_first_unanalyzed_node, varpool_nodes_queue,
	varpool_first_unanalyzed_node, varpool_node,
	varpool_node_for_asm, varpool_mark_needed_node,
	varpool_finalize_decl, varpool_enqueue_needed_node,
	varpool_assemble_pending_decls, variable_initializer_availability):
	Rename to ...
	* tree.c (decl_assembler_name_equal): Move here from cgraph.c.
	* tree.h (decl_assembler_name_equal): Declare.
	* omp-low.c (lower_omp_critical): Update.
	* ipa-reference (analyze_variable, static_execute): Likewise.
	* toplev.c (wrapup_global_declaration_2, compile_file): Update.
	* cgraphunit.c: Update comments.
	(cgraph_varpool_assembled_nodes_queue): Move to varpool.c under name
	varpool_assembled_nodes_queue.
	(cgraph_varpool_analyze_pending_decls): Move to varpool.c under name
	varpool_analyze_pending_decls.
	(cgraph_varpool_remove_unreferenced_decls): Move to varpool.c under name
	varpool_remove_unreferenced_decls.
	(record_reference): Update.
	(cgraph_create_edges): Update.
	(record_referneces_in_initializer): New function.
	(cgraph_varpool_assemble_decl): Move to varpool.c under name
	varpool_assemble_decl; make global.
	(cgraph_varpool_assemble_pending_decls): Move to varpool.c under name
	varpool_assemble_pending_decls.
	(process_function_and_variable_attributes, cgraph_finalize_compilation_unit,
	struct cgraph_order_sort, cgraph_output_in_order,
	cgraph_function_and_variable_invisibility, cgraph_optimize,
	cgraph_increase_alignment): Update.
	* dwarf2out.c (decls_for_scope): Likewise.
	* ipa-type-escape.c (analyze_variable, type_escape_execute): Likewise.
	* except.c (output_ttype): Likewise.
	* varasm.c (mark_decl_referenced): Likewise.
	(find_decl_and_mark_referenced, assemble_alias): update.
	* Makefile.in: Add varpool.c, gt-varpool.c and remove gt-cgraphunit.c
	* passes.c (rest_of_decl_compilation): Update.

	* cp/decl2.c (var_finalized_p): Update for renamed varpool functions.
	* fortran/f59-lang.c (gfc_expand_function): Update for renamed varpool functions.
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 119691)
--- cgraph.c	(working copy)
*************** along with GCC; see the file COPYING.  I
*** 19,25 ****
  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.  */
  
! /*  This file contains basic routines manipulating call graph and variable pool
  
  The callgraph:
  
--- 19,25 ----
  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.  */
  
! /*  This file contains basic routines manipulating call graph
  
  The callgraph:
  
*************** The callgraph:
*** 69,83 ****
  
        Each edge has "inline_failed" field.  When the field is set to NULL,
        the call will be inlined.  When it is non-NULL it contains a reason
!       why inlining wasn't performed.
! 
! 
! The varpool data structure:
! 
!     Varpool is used to maintain variables in similar manner as call-graph
!     is used for functions.  Most of the API is symmetric replacing cgraph
!     function prefix by cgraph_varpool  */
! 
  
  #include "config.h"
  #include "system.h"
--- 69,75 ----
  
        Each edge has "inline_failed" field.  When the field is set to NULL,
        the call will be inlined.  When it is non-NULL it contains a reason
!       why inlining wasn't performed.  */
  
  #include "config.h"
  #include "system.h"
*************** bool cgraph_global_info_ready = false;
*** 130,147 ****
  /* Set when the cgraph is fully build and the basic flags are computed.  */
  bool cgraph_function_flags_ready = false;
  
- /* Hash table used to convert declarations into nodes.  */
- static GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
- 
- /* Queue of cgraph nodes scheduled to be lowered and output.  */
- struct cgraph_varpool_node *cgraph_varpool_nodes_queue, *cgraph_varpool_first_unanalyzed_node;
- 
- /* The linked list of cgraph varpool nodes.  */
- struct cgraph_varpool_node *cgraph_varpool_nodes;
- 
- /* End of the varpool queue.  Needs to be QTYed to work with PCH.  */
- static GTY(()) struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
- 
  /* Linked list of cgraph asm nodes.  */
  struct cgraph_asm_node *cgraph_asm_nodes;
  
--- 122,127 ----
*************** cgraph_insert_node_to_hashtable (struct 
*** 243,282 ****
    *slot = node;
  }
  
- /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
- 
- static bool
- decl_assembler_name_equal (tree decl, tree asmname)
- {
-   tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
- 
-   if (decl_asmname == asmname)
-     return true;
- 
-   /* If the target assembler name was set by the user, things are trickier.
-      We have a leading '*' to begin with.  After that, it's arguable what
-      is the correct thing to do with -fleading-underscore.  Arguably, we've
-      historically been doing the wrong thing in assemble_alias by always
-      printing the leading underscore.  Since we're not changing that, make
-      sure user_label_prefix follows the '*' before matching.  */
-   if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
-     {
-       const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
-       size_t ulp_len = strlen (user_label_prefix);
- 
-       if (ulp_len == 0)
- 	;
-       else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
- 	decl_str += ulp_len;
-       else
- 	return false;
- 
-       return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
-     }
- 
-   return false;
- }
- 
  
  /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
     Return NULL if there's no such node.  */
--- 223,228 ----
*************** cgraph_node_name (struct cgraph_node *no
*** 683,697 ****
    return lang_hooks.decl_printable_name (node->decl, 2);
  }
  
- /* Return name of the node used in debug output.  */
- static const char *
- cgraph_varpool_node_name (struct cgraph_varpool_node *node)
- {
-   return lang_hooks.decl_printable_name (node->decl, 2);
- }
- 
  /* Names used to print out the availability enum.  */
! static const char * const availability_names[] =
    {"unset", "not_available", "overwrittable", "available", "local"};
  
  /* Dump given cgraph node.  */
--- 629,636 ----
    return lang_hooks.decl_printable_name (node->decl, 2);
  }
  
  /* Names used to print out the availability enum.  */
! const char * const cgraph_availability_names[] =
    {"unset", "not_available", "overwrittable", "available", "local"};
  
  /* Dump given cgraph node.  */
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 706,712 ****
  	     node->global.inlined_to->uid);
    if (cgraph_function_flags_ready)
      fprintf (f, " availability:%s",
! 	     availability_names [cgraph_function_body_availability (node)]);
    if (node->master_clone && node->master_clone->uid != node->uid)
      fprintf (f, "(%i)", node->master_clone->uid);
    if (node->count)
--- 645,651 ----
  	     node->global.inlined_to->uid);
    if (cgraph_function_flags_ready)
      fprintf (f, " availability:%s",
! 	     cgraph_availability_names [cgraph_function_body_availability (node)]);
    if (node->master_clone && node->master_clone->uid != node->uid)
      fprintf (f, "(%i)", node->master_clone->uid);
    if (node->count)
*************** dump_cgraph (FILE *f)
*** 785,884 ****
      dump_cgraph_node (f, node);
  }
  
- /* Dump given cgraph node.  */
- void
- dump_cgraph_varpool_node (FILE *f, struct cgraph_varpool_node *node)
- {
-   fprintf (f, "%s:", cgraph_varpool_node_name (node));
-   fprintf (f, " availability:%s",
- 	   cgraph_function_flags_ready
- 	   ? availability_names[cgraph_variable_initializer_availability (node)]
- 	   : "not-ready");
-   if (DECL_INITIAL (node->decl))
-     fprintf (f, " initialized");
-   if (node->needed)
-     fprintf (f, " needed");
-   if (node->analyzed)
-     fprintf (f, " analyzed");
-   if (node->finalized)
-     fprintf (f, " finalized");
-   if (node->output)
-     fprintf (f, " output");
-   if (node->externally_visible)
-     fprintf (f, " externally_visible");
-   fprintf (f, "\n");
- }
- 
- /* Dump the callgraph.  */
- 
- void
- dump_varpool (FILE *f)
- {
-   struct cgraph_varpool_node *node;
- 
-   fprintf (f, "variable pool:\n\n");
-   for (node = cgraph_varpool_nodes; node; node = node->next_needed)
-     dump_cgraph_varpool_node (f, node);
- }
- 
- /* Returns a hash code for P.  */
- 
- static hashval_t
- hash_varpool_node (const void *p)
- {
-   const struct cgraph_varpool_node *n = (const struct cgraph_varpool_node *) p;
-   return (hashval_t) DECL_UID (n->decl);
- }
- 
- /* Returns nonzero if P1 and P2 are equal.  */
- 
- static int
- eq_varpool_node (const void *p1, const void *p2)
- {
-   const struct cgraph_varpool_node *n1 =
-     (const struct cgraph_varpool_node *) p1;
-   const struct cgraph_varpool_node *n2 =
-     (const struct cgraph_varpool_node *) p2;
-   return DECL_UID (n1->decl) == DECL_UID (n2->decl);
- }
- 
- /* Return cgraph_varpool node assigned to DECL.  Create new one when needed.  */
- struct cgraph_varpool_node *
- cgraph_varpool_node (tree decl)
- {
-   struct cgraph_varpool_node key, *node, **slot;
- 
-   gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
- 
-   if (!cgraph_varpool_hash)
-     cgraph_varpool_hash = htab_create_ggc (10, hash_varpool_node,
- 					   eq_varpool_node, NULL);
-   key.decl = decl;
-   slot = (struct cgraph_varpool_node **)
-     htab_find_slot (cgraph_varpool_hash, &key, INSERT);
-   if (*slot)
-     return *slot;
-   node = GGC_CNEW (struct cgraph_varpool_node);
-   node->decl = decl;
-   node->order = cgraph_order++;
-   node->next = cgraph_varpool_nodes;
-   cgraph_varpool_nodes = node;
-   *slot = node;
-   return node;
- }
- 
- struct cgraph_varpool_node *
- cgraph_varpool_node_for_asm (tree asmname)
- {
-   struct cgraph_varpool_node *node;
- 
-   for (node = cgraph_varpool_nodes; node ; node = node->next)
-     if (decl_assembler_name_equal (node->decl, asmname))
-       return node;
- 
-   return NULL;
- }
- 
  /* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables.  */
  void
  change_decl_assembler_name (tree decl, tree name)
--- 724,729 ----
*************** change_decl_assembler_name (tree decl, t
*** 898,1013 ****
    SET_DECL_ASSEMBLER_NAME (decl, name);
  }
  
- /* Helper function for finalization code - add node into lists so it will
-    be analyzed and compiled.  */
- void
- cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *node)
- {
-   if (cgraph_varpool_last_needed_node)
-     cgraph_varpool_last_needed_node->next_needed = node;
-   cgraph_varpool_last_needed_node = node;
-   node->next_needed = NULL;
-   if (!cgraph_varpool_nodes_queue)
-     cgraph_varpool_nodes_queue = node;
-   if (!cgraph_varpool_first_unanalyzed_node)
-     cgraph_varpool_first_unanalyzed_node = node;
-   notice_global_symbol (node->decl);
- }
- 
- /* Reset the queue of needed nodes.  */
- void
- cgraph_varpool_reset_queue (void)
- {
-   cgraph_varpool_last_needed_node = NULL;
-   cgraph_varpool_nodes_queue = NULL;
-   cgraph_varpool_first_unanalyzed_node = NULL;
- }
- 
- /* Notify finalize_compilation_unit that given node is reachable
-    or needed.  */
- void
- cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
- {
-   if (!node->needed && node->finalized
-       && !TREE_ASM_WRITTEN (node->decl))
-     cgraph_varpool_enqueue_needed_node (node);
-   node->needed = 1;
- }
- 
- /* 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.  */
- 
- bool
- decide_is_variable_needed (struct cgraph_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)))
-     return true;
- 
-   /* ??? If the assembler name is set by hand, it is possible to assemble
-      the name later after finalizing the function and the fact is noticed
-      in assemble_name then.  This is arguably a bug.  */
-   if (DECL_ASSEMBLER_NAME_SET_P (decl)
-       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
-     return true;
- 
-   /* If we decided it was needed before, but at the time we didn't have
-      the definition available, then it's still needed.  */
-   if (node->needed)
-     return true;
- 
-   /* 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 && !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_unit_at_a_time && flag_toplevel_reorder)
-     return false;
- 
-   /* We want to emit COMDAT variables only when absolutely necessary.  */
-   if (DECL_COMDAT (decl))
-     return false;
-   return true;
- }
- 
- void
- cgraph_varpool_finalize_decl (tree decl)
- {
-   struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
- 
-   /* The first declaration of a variable that comes through this function
-      decides whether it is global (in C, has external linkage)
-      or local (in C, has internal linkage).  So do nothing more
-      if this function has already run.  */
-   if (node->finalized)
-     {
-       if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
- 	cgraph_varpool_assemble_pending_decls ();
-       return;
-     }
-   if (node->needed)
-     cgraph_varpool_enqueue_needed_node (node);
-   node->finalized = true;
- 
-   if (decide_is_variable_needed (node, decl))
-     cgraph_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))
-     cgraph_varpool_mark_needed_node (node);
-   if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
-     cgraph_varpool_assemble_pending_decls ();
- }
- 
  /* Add a top-level asm statement to the list.  */
  
  struct cgraph_asm_node *
--- 743,748 ----
*************** cgraph_function_body_availability (struc
*** 1181,1205 ****
    return avail;
  }
  
- /* Return variable availability.  See cgraph.h for description of individual
-    return values.  */
- enum availability
- cgraph_variable_initializer_availability (struct cgraph_varpool_node *node)
- {
-   gcc_assert (cgraph_function_flags_ready);
-   if (!node->finalized)
-     return AVAIL_NOT_AVAILABLE;
-   if (!TREE_PUBLIC (node->decl))
-     return AVAIL_AVAILABLE;
-   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
-      care of at least two notable extensions - the COMDAT variables
-      used to share template instantiations in C++.  */
-   if (!(*targetm.binds_local_p) (node->decl) && !DECL_COMDAT (node->decl))
-     return AVAIL_OVERWRITABLE;
-   return AVAIL_AVAILABLE;
- }
- 
- 
  /* Add the function FNDECL to the call graph.  FNDECL is assumed to be
     in low GIMPLE form and ready to be processed by cgraph_finalize_function.
  
--- 916,921 ----
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 119691)
--- cgraph.h	(working copy)
*************** enum availability
*** 46,51 ****
--- 46,53 ----
    AVAIL_LOCAL
  };
  
+ extern const char * const cgraph_availability_names[];
+ 
  /* Information about the function collected locally.
     Available after function is analyzed.  */
  
*************** typedef struct cgraph_edge *cgraph_edge_
*** 204,219 ****
  DEF_VEC_P(cgraph_edge_p);
  DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
  
! /* The cgraph_varpool data structure.
!    Each static variable decl has assigned cgraph_varpool_node.  */
  
! struct cgraph_varpool_node GTY(())
  {
    tree decl;
!   /* Pointer to the next function in cgraph_varpool_nodes.  */
!   struct cgraph_varpool_node *next;
!   /* Pointer to the next function in cgraph_varpool_nodes_queue.  */
!   struct cgraph_varpool_node *next_needed;
    /* Ordering of all cgraph nodes.  */
    int order;
  
--- 206,221 ----
  DEF_VEC_P(cgraph_edge_p);
  DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
  
! /* The varpool data structure.
!    Each static variable decl has assigned varpool_node.  */
  
! struct varpool_node GTY(())
  {
    tree decl;
!   /* Pointer to the next function in varpool_nodes.  */
!   struct varpool_node *next;
!   /* Pointer to the next function in varpool_nodes_queue.  */
!   struct varpool_node *next_needed;
    /* Ordering of all cgraph nodes.  */
    int order;
  
*************** extern bool cgraph_function_flags_ready;
*** 256,264 ****
  extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
  extern GTY(()) struct cgraph_node *cgraph_expand_queue;
  
- extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_first_unanalyzed_node;
- extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
- extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
  extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
  extern GTY(()) int cgraph_order;
  
--- 258,263 ----
*************** extern GTY(()) int cgraph_order;
*** 266,273 ****
  void dump_cgraph (FILE *);
  void dump_cgraph_node (FILE *, struct cgraph_node *);
  void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
- void dump_varpool (FILE *);
- void dump_cgraph_varpool_node (FILE *, struct cgraph_varpool_node *);
  void cgraph_remove_edge (struct cgraph_edge *);
  void cgraph_remove_node (struct cgraph_node *);
  void cgraph_node_remove_callees (struct cgraph_node *node);
--- 265,270 ----
*************** struct cgraph_edge * cgraph_clone_edge (
*** 288,315 ****
  struct cgraph_node * cgraph_clone_node (struct cgraph_node *, gcov_type,
  					int, bool);
  
- struct cgraph_varpool_node *cgraph_varpool_node (tree);
- struct cgraph_varpool_node *cgraph_varpool_node_for_asm (tree asmname);
- void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
- void cgraph_varpool_finalize_decl (tree);
  void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
  
  struct cgraph_asm_node *cgraph_add_asm_node (tree);
  
  bool cgraph_function_possibly_inlined_p (tree);
  void cgraph_unnest_node (struct cgraph_node *);
- void cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *);
- void cgraph_varpool_reset_queue (void);
- bool decide_is_variable_needed (struct cgraph_varpool_node *, tree);
  
  enum availability cgraph_function_body_availability (struct cgraph_node *);
- enum availability cgraph_variable_initializer_availability (struct cgraph_varpool_node *);
  bool cgraph_is_master_clone (struct cgraph_node *);
  struct cgraph_node *cgraph_master_clone (struct cgraph_node *);
  void cgraph_add_new_function (tree);
  
  /* In cgraphunit.c  */
- bool cgraph_varpool_assemble_pending_decls (void);
  void cgraph_finalize_function (tree, bool);
  void cgraph_finalize_compilation_unit (void);
  void cgraph_optimize (void);
--- 285,303 ----
*************** struct cgraph_node *cgraph_function_vers
*** 327,337 ****
--- 315,347 ----
  						varray_type);
  void cgraph_analyze_function (struct cgraph_node *);
  struct cgraph_node *save_inline_function_body (struct cgraph_node *);
+ void record_references_in_initializer (tree);
  
  /* In ipa.c  */
  bool cgraph_remove_unreachable_nodes (bool, FILE *);
  int cgraph_postorder (struct cgraph_node **);
  
+ /* In varpool.c  */
+ 
+ extern GTY(()) struct varpool_node *varpool_nodes_queue;
+ extern GTY(()) struct varpool_node *varpool_nodes;
+ 
+ struct varpool_node *varpool_node (tree);
+ struct varpool_node *varpool_node_for_asm (tree asmname);
+ void varpool_mark_needed_node (struct varpool_node *);
+ void dump_varpool (FILE *);
+ void dump_varpool_node (FILE *, struct varpool_node *);
+ 
+ void varpool_finalize_decl (tree);
+ bool decide_is_variable_needed (struct varpool_node *, tree);
+ enum availability cgraph_variable_initializer_availability (struct varpool_node *);
+ 
+ bool varpool_assemble_pending_decls (void);
+ bool varpool_assemble_decl (struct varpool_node *node);
+ bool varpool_analyze_pending_decls (void);
+ void varpool_output_debug_info (void);
+ void varpool_remove_unreferenced_decls (void);
+ 
  /* In ipa-inline.c  */
  bool cgraph_decide_inlining_incrementally (struct cgraph_node *, bool);
  void cgraph_clone_inlined_nodes (struct cgraph_edge *, bool, bool);
Index: tree.c
===================================================================
*** tree.c	(revision 119690)
--- tree.c	(working copy)
*************** decl_assembler_name (tree decl)
*** 307,312 ****
--- 307,346 ----
    return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
  }
  
+ /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
+ 
+ bool
+ decl_assembler_name_equal (tree decl, tree asmname)
+ {
+   tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
+ 
+   if (decl_asmname == asmname)
+     return true;
+ 
+   /* If the target assembler name was set by the user, things are trickier.
+      We have a leading '*' to begin with.  After that, it's arguable what
+      is the correct thing to do with -fleading-underscore.  Arguably, we've
+      historically been doing the wrong thing in assemble_alias by always
+      printing the leading underscore.  Since we're not changing that, make
+      sure user_label_prefix follows the '*' before matching.  */
+   if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
+     {
+       const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
+       size_t ulp_len = strlen (user_label_prefix);
+ 
+       if (ulp_len == 0)
+ 	;
+       else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
+ 	decl_str += ulp_len;
+       else
+ 	return false;
+ 
+       return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
+     }
+ 
+   return false;
+ }
+ 
  /* Compute the number of bytes occupied by a tree with code CODE.
     This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST
     codes, which are of variable length.  */
Index: tree.h
===================================================================
*** tree.h	(revision 119690)
--- tree.h	(working copy)
*************** enum ptrmemfunc_vbit_where_t
*** 3490,3495 ****
--- 3490,3496 ----
  #define NULL_TREE (tree) NULL
  
  extern tree decl_assembler_name (tree);
+ extern bool decl_assembler_name_equal (tree decl, tree asmname);
  
  /* Compute the number of bytes occupied by 'node'.  This routine only
     looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH.  */
Index: omp-low.c
===================================================================
*** omp-low.c	(revision 119690)
--- omp-low.c	(working copy)
*************** lower_omp_critical (tree *stmt_p, omp_co
*** 3929,3935 ****
  	  DECL_COMMON (decl) = 1;
  	  DECL_ARTIFICIAL (decl) = 1;
  	  DECL_IGNORED_P (decl) = 1;
! 	  cgraph_varpool_finalize_decl (decl);
  
  	  splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
  			     (splay_tree_value) decl);
--- 3929,3935 ----
  	  DECL_COMMON (decl) = 1;
  	  DECL_ARTIFICIAL (decl) = 1;
  	  DECL_IGNORED_P (decl) = 1;
! 	  varpool_finalize_decl (decl);
  
  	  splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
  			     (splay_tree_value) decl);
Index: ipa-reference.c
===================================================================
*** ipa-reference.c	(revision 119690)
--- ipa-reference.c	(working copy)
*************** ipa_init (void) 
*** 770,776 ****
     to variables defined within this unit.  */
  
  static void 
! analyze_variable (struct cgraph_varpool_node *vnode)
  {
    tree global = vnode->decl;
    if (TREE_CODE (global) == VAR_DECL)
--- 770,776 ----
     to variables defined within this unit.  */
  
  static void 
! analyze_variable (struct varpool_node *vnode)
  {
    tree global = vnode->decl;
    if (TREE_CODE (global) == VAR_DECL)
*************** static unsigned int
*** 892,898 ****
  static_execute (void)
  {
    struct cgraph_node *node;
!   struct cgraph_varpool_node *vnode;
    struct cgraph_node *w;
    struct cgraph_node **order =
      xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
--- 892,898 ----
  static_execute (void)
  {
    struct cgraph_node *node;
!   struct varpool_node *vnode;
    struct cgraph_node *w;
    struct cgraph_node **order =
      xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
*************** static_execute (void)
*** 902,908 ****
    ipa_init ();
  
    /* Process all of the variables first.  */
!   for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
      analyze_variable (vnode);
  
    /* Process all of the functions next. 
--- 902,908 ----
    ipa_init ();
  
    /* Process all of the variables first.  */
!   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
      analyze_variable (vnode);
  
    /* Process all of the functions next. 
Index: toplev.c
===================================================================
*** toplev.c	(revision 119690)
--- toplev.c	(working copy)
*************** wrapup_global_declaration_2 (tree decl)
*** 751,759 ****
  
    if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
      {
!       struct cgraph_varpool_node *node;
        bool needed = true;
!       node = cgraph_varpool_node (decl);
  
        if (node->finalized)
  	needed = false;
--- 751,759 ----
  
    if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
      {
!       struct varpool_node *node;
        bool needed = true;
!       node = varpool_node (decl);
  
        if (node->finalized)
  	needed = false;
*************** compile_file (void)
*** 1042,1048 ****
    if (errorcount || sorrycount)
      return;
  
!   cgraph_varpool_assemble_pending_decls ();
    finish_aliases_2 ();
  
    /* This must occur after the loop to output deferred functions.
--- 1042,1048 ----
    if (errorcount || sorrycount)
      return;
  
!   varpool_assemble_pending_decls ();
    finish_aliases_2 ();
  
    /* This must occur after the loop to output deferred functions.
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 119691)
--- cgraphunit.c	(working copy)
*************** Software Foundation, 51 Franklin Street,
*** 35,41 ****
        (There is one exception needed for implementing GCC extern inline
  	function.)
  
!     - cgraph_varpool_finalize_variable
  
        This function has same behavior as the above but is used for static
        variables.
--- 35,41 ----
        (There is one exception needed for implementing GCC extern inline
  	function.)
  
!     - varpool_finalize_variable
  
        This function has same behavior as the above but is used for static
        variables.
*************** Software Foundation, 51 Franklin Street,
*** 60,66 ****
        modify calling conventions, do better inlining or similar optimizations.
  
      - cgraph_mark_needed_node
!     - cgraph_varpool_mark_needed_node
  
        When function or variable is referenced by some hidden way the call-graph
        data structure must be updated accordingly by this function.
--- 60,66 ----
        modify calling conventions, do better inlining or similar optimizations.
  
      - cgraph_mark_needed_node
!     - varpool_mark_needed_node
  
        When function or variable is referenced by some hidden way the call-graph
        data structure must be updated accordingly by this function.
*************** Software Foundation, 51 Franklin Street,
*** 82,89 ****
        This function is used to expand function and pass it into RTL back-end.
        Front-end should not make any assumptions about when this function can be
        called.  In particular cgraph_assemble_pending_functions,
!       cgraph_varpool_assemble_pending_variables, cgraph_finalize_function,
!       cgraph_varpool_finalize_function, cgraph_optimize can cause arbitrarily
        previously finalized functions to be expanded.
  
      We implement two compilation modes.
--- 82,89 ----
        This function is used to expand function and pass it into RTL back-end.
        Front-end should not make any assumptions about when this function can be
        called.  In particular cgraph_assemble_pending_functions,
!       varpool_assemble_pending_variables, cgraph_finalize_function,
!       varpool_finalize_function, cgraph_optimize can cause arbitrarily
        previously finalized functions to be expanded.
  
      We implement two compilation modes.
*************** static tree record_reference (tree *, in
*** 168,176 ****
  static void cgraph_output_pending_asms (void);
  static void cgraph_increase_alignment (void);
  
- /* Lists all assembled variables to be sent to debugger output later on.  */
- static GTY(()) struct cgraph_varpool_node *cgraph_varpool_assembled_nodes_queue;
- 
  /* Records tree nodes seen in record_reference.  Simply using
     walk_tree_without_duplicates doesn't guarantee each node is visited
     once because it gets a new htab upon each recursive call from
--- 168,173 ----
*************** decide_is_function_needed (struct cgraph
*** 265,347 ****
    return false;
  }
  
- /* Walk the decls we marked as necessary and see if they reference new
-    variables or functions and add them into the worklists.  */
- static bool
- cgraph_varpool_analyze_pending_decls (void)
- {
-   bool changed = false;
-   timevar_push (TV_CGRAPH);
- 
-   while (cgraph_varpool_first_unanalyzed_node)
-     {
-       tree decl = cgraph_varpool_first_unanalyzed_node->decl;
- 
-       cgraph_varpool_first_unanalyzed_node->analyzed = true;
- 
-       cgraph_varpool_first_unanalyzed_node = cgraph_varpool_first_unanalyzed_node->next_needed;
- 
-       /* Compute the alignment early so function body expanders are
- 	 already informed about increased alignment.  */
-       align_variable (decl, 0);
- 
-       if (DECL_INITIAL (decl))
- 	{
- 	  visited_nodes = pointer_set_create ();
- 	  walk_tree (&DECL_INITIAL (decl), record_reference, NULL, visited_nodes);
- 	  pointer_set_destroy (visited_nodes);
- 	  visited_nodes = NULL;
- 	}
-       changed = true;
-     }
-   timevar_pop (TV_CGRAPH);
-   return changed;
- }
- 
- /* Optimization of function bodies might've rendered some variables as
-    unnecessary so we want to avoid these from being compiled.
- 
-    This is done by pruning the queue and keeping only the variables that
-    really appear needed (ie they are either externally visible or referenced
-    by compiled function). Re-doing the reachability analysis on variables
-    brings back the remaining variables referenced by these.  */
- static void
- cgraph_varpool_remove_unreferenced_decls (void)
- {
-   struct cgraph_varpool_node *next, *node = cgraph_varpool_nodes_queue;
- 
-   cgraph_varpool_reset_queue ();
- 
-   if (errorcount || sorrycount)
-     return;
- 
-   while (node)
-     {
-       tree decl = node->decl;
-       next = node->next_needed;
-       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)
- 	      /* ??? 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)))
- 	cgraph_varpool_mark_needed_node (node);
- 
-       node = next;
-     }
-   /* Make sure we mark alias targets as used targets.  */
-   finish_aliases_1 ();
-   cgraph_varpool_analyze_pending_decls ();
- }
- 
- 
  /* When not doing unit-at-a-time, output all functions enqueued.
     Return true when such a functions were found.  */
  
--- 262,267 ----
*************** record_reference (tree *tp, int *walk_su
*** 521,527 ****
  	 after rtl has been generated.  */
        if (TREE_STATIC (t) || DECL_EXTERNAL (t))
  	{
! 	  cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
  	  if (lang_hooks.callgraph.analyze_expr)
  	    return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees,
  						      data);
--- 441,447 ----
  	 after rtl has been generated.  */
        if (TREE_STATIC (t) || DECL_EXTERNAL (t))
  	{
! 	  varpool_mark_needed_node (varpool_node (t));
  	  if (lang_hooks.callgraph.analyze_expr)
  	    return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees,
  						      data);
*************** cgraph_create_edges (struct cgraph_node 
*** 602,608 ****
        if (TREE_CODE (decl) == VAR_DECL
  	  && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
  	  && flag_unit_at_a_time)
! 	cgraph_varpool_finalize_decl (decl);
        else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
  	walk_tree (&DECL_INITIAL (decl), record_reference, node, visited_nodes);
      }
--- 522,528 ----
        if (TREE_CODE (decl) == VAR_DECL
  	  && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
  	  && flag_unit_at_a_time)
! 	varpool_finalize_decl (decl);
        else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
  	walk_tree (&DECL_INITIAL (decl), record_reference, node, visited_nodes);
      }
*************** cgraph_create_edges (struct cgraph_node 
*** 611,616 ****
--- 531,546 ----
    visited_nodes = NULL;
  }
  
+ void
+ record_references_in_initializer (tree decl)
+ {
+   visited_nodes = pointer_set_create ();
+   walk_tree (&DECL_INITIAL (decl), record_reference, NULL, visited_nodes);
+   pointer_set_destroy (visited_nodes);
+   visited_nodes = NULL;
+ }
+ 
+ 
  /* Give initial reasons why inlining would fail.  Those gets
     either NULLified or usually overwritten by more precise reason
     later.  */
*************** verify_cgraph (void)
*** 844,921 ****
      verify_cgraph_node (node);
  }
  
- /* Output one variable, if necessary.  Return whether we output it.  */
- static bool
- cgraph_varpool_assemble_decl (struct cgraph_varpool_node *node)
- {
-   tree decl = node->decl;
- 
-   if (!TREE_ASM_WRITTEN (decl)
-       && !node->alias
-       && !DECL_EXTERNAL (decl)
-       && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
-     {
-       assemble_variable (decl, 0, 1, 0);
-       return TREE_ASM_WRITTEN (decl);
-     }
- 
-   return false;
- }
- 
- /* Output all variables enqueued to be assembled.  */
- bool
- cgraph_varpool_assemble_pending_decls (void)
- {
-   bool changed = false;
- 
-   if (errorcount || sorrycount)
-     return false;
- 
-   /* 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.  */
-   cgraph_varpool_analyze_pending_decls ();
- 
-   while (cgraph_varpool_nodes_queue)
-     {
-       struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
- 
-       cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
-       if (cgraph_varpool_assemble_decl (node))
- 	{
- 	  changed = true;
- 	  node->next_needed = cgraph_varpool_assembled_nodes_queue;
- 	  cgraph_varpool_assembled_nodes_queue = node;
- 	  node->finalized = 1;
- 	}
-       else
-         node->next_needed = NULL;
-     }
-   return changed;
- }
- /* Output all variables enqueued to be assembled.  */
- static void
- cgraph_varpool_output_debug_info (void)
- {
-   timevar_push (TV_SYMOUT);
-   if (errorcount == 0 && sorrycount == 0)
-     while (cgraph_varpool_assembled_nodes_queue)
-       {
- 	struct cgraph_varpool_node *node = cgraph_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);
- 	cgraph_varpool_assembled_nodes_queue = node->next_needed;
- 	node->next_needed = 0;
-       }
-   timevar_pop (TV_SYMOUT);
- }
- 
  /* Output all asm statements we have stored up to be output.  */
  
  static void
--- 774,779 ----
*************** cgraph_analyze_function (struct cgraph_n
*** 990,999 ****
  
  static void
  process_function_and_variable_attributes (struct cgraph_node *first,
!                                           struct cgraph_varpool_node *first_var)
  {
    struct cgraph_node *node;
!   struct cgraph_varpool_node *vnode;
  
    for (node = cgraph_nodes; node != first; node = node->next)
      {
--- 848,857 ----
  
  static void
  process_function_and_variable_attributes (struct cgraph_node *first,
!                                           struct varpool_node *first_var)
  {
    struct cgraph_node *node;
!   struct varpool_node *vnode;
  
    for (node = cgraph_nodes; node != first; node = node->next)
      {
*************** process_function_and_variable_attributes
*** 1018,1031 ****
  	    }
  	}
      }
!   for (vnode = cgraph_varpool_nodes; vnode != first_var; vnode = vnode->next)
      {
        tree decl = vnode->decl;
        if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
  	{
  	  mark_decl_referenced (decl);
  	  if (vnode->finalized)
! 	    cgraph_varpool_mark_needed_node (vnode);
  	}
        if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
  	{
--- 876,889 ----
  	    }
  	}
      }
!   for (vnode = varpool_nodes; vnode != first_var; vnode = vnode->next)
      {
        tree decl = vnode->decl;
        if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
  	{
  	  mark_decl_referenced (decl);
  	  if (vnode->finalized)
! 	    varpool_mark_needed_node (vnode);
  	}
        if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
  	{
*************** process_function_and_variable_attributes
*** 1036,1042 ****
  	  else
  	    {
  	      if (vnode->finalized)
! 		cgraph_varpool_mark_needed_node (vnode);
  	      vnode->externally_visible = true;
  	    }
  	}
--- 894,900 ----
  	  else
  	    {
  	      if (vnode->finalized)
! 		varpool_mark_needed_node (vnode);
  	      vnode->externally_visible = true;
  	    }
  	}
*************** cgraph_finalize_compilation_unit (void)
*** 1053,1059 ****
       intermodule optimization.  */
    static struct cgraph_node *first_analyzed;
    struct cgraph_node *first_processed = first_analyzed;
!   static struct cgraph_varpool_node *first_analyzed_var;
  
    if (errorcount || sorrycount)
      return;
--- 911,917 ----
       intermodule optimization.  */
    static struct cgraph_node *first_analyzed;
    struct cgraph_node *first_processed = first_analyzed;
!   static struct varpool_node *first_analyzed_var;
  
    if (errorcount || sorrycount)
      return;
*************** cgraph_finalize_compilation_unit (void)
*** 1064,1070 ****
      {
        cgraph_output_pending_asms ();
        cgraph_assemble_pending_functions ();
!       cgraph_varpool_output_debug_info ();
        return;
      }
  
--- 922,928 ----
      {
        cgraph_output_pending_asms ();
        cgraph_assemble_pending_functions ();
!       varpool_output_debug_info ();
        return;
      }
  
*************** cgraph_finalize_compilation_unit (void)
*** 1078,1085 ****
    process_function_and_variable_attributes (first_processed,
  					    first_analyzed_var);
    first_processed = cgraph_nodes;
!   first_analyzed_var = cgraph_varpool_nodes;
!   cgraph_varpool_analyze_pending_decls ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "Initial entry points:");
--- 936,943 ----
    process_function_and_variable_attributes (first_processed,
  					    first_analyzed_var);
    first_processed = cgraph_nodes;
!   first_analyzed_var = varpool_nodes;
!   varpool_analyze_pending_decls ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "Initial entry points:");
*************** cgraph_finalize_compilation_unit (void)
*** 1125,1132 ****
        process_function_and_variable_attributes (first_processed,
  						first_analyzed_var);
        first_processed = cgraph_nodes;
!       first_analyzed_var = cgraph_varpool_nodes;
!       cgraph_varpool_analyze_pending_decls ();
      }
  
    /* Collect entry points to the unit.  */
--- 983,990 ----
        process_function_and_variable_attributes (first_processed,
  						first_analyzed_var);
        first_processed = cgraph_nodes;
!       first_analyzed_var = varpool_nodes;
!       varpool_analyze_pending_decls ();
      }
  
    /* Collect entry points to the unit.  */
*************** struct cgraph_order_sort
*** 1328,1334 ****
    union
    {
      struct cgraph_node *f;
!     struct cgraph_varpool_node *v;
      struct cgraph_asm_node *a;
    } u;
  };
--- 1186,1192 ----
    union
    {
      struct cgraph_node *f;
!     struct varpool_node *v;
      struct cgraph_asm_node *a;
    } u;
  };
*************** cgraph_output_in_order (void)
*** 1347,1353 ****
    struct cgraph_order_sort *nodes;
    int i;
    struct cgraph_node *pf;
!   struct cgraph_varpool_node *pv;
    struct cgraph_asm_node *pa;
  
    max = cgraph_order;
--- 1205,1211 ----
    struct cgraph_order_sort *nodes;
    int i;
    struct cgraph_node *pf;
!   struct varpool_node *pv;
    struct cgraph_asm_node *pa;
  
    max = cgraph_order;
*************** cgraph_output_in_order (void)
*** 1355,1361 ****
    nodes = (struct cgraph_order_sort *) alloca (size);
    memset (nodes, 0, size);
  
!   cgraph_varpool_analyze_pending_decls ();
  
    for (pf = cgraph_nodes; pf; pf = pf->next)
      {
--- 1213,1219 ----
    nodes = (struct cgraph_order_sort *) alloca (size);
    memset (nodes, 0, size);
  
!   varpool_analyze_pending_decls ();
  
    for (pf = cgraph_nodes; pf; pf = pf->next)
      {
*************** cgraph_output_in_order (void)
*** 1368,1374 ****
  	}
      }
  
!   for (pv = cgraph_varpool_nodes_queue; pv; pv = pv->next_needed)
      {
        i = pv->order;
        gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
--- 1226,1232 ----
  	}
      }
  
!   for (pv = varpool_nodes_queue; pv; pv = pv->next_needed)
      {
        i = pv->order;
        gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
*************** cgraph_output_in_order (void)
*** 1394,1400 ****
  	  break;
  
  	case ORDER_VAR:
! 	  cgraph_varpool_assemble_decl (nodes[i].u.v);
  	  break;
  
  	case ORDER_ASM:
--- 1252,1258 ----
  	  break;
  
  	case ORDER_VAR:
! 	  varpool_assemble_decl (nodes[i].u.v);
  	  break;
  
  	case ORDER_ASM:
*************** static void
*** 1427,1433 ****
  cgraph_function_and_variable_visibility (void)
  {
    struct cgraph_node *node;
!   struct cgraph_varpool_node *vnode;
  
    for (node = cgraph_nodes; node; node = node->next)
      {
--- 1285,1291 ----
  cgraph_function_and_variable_visibility (void)
  {
    struct cgraph_node *node;
!   struct varpool_node *vnode;
  
    for (node = cgraph_nodes; node; node = node->next)
      {
*************** cgraph_function_and_variable_visibility 
*** 1447,1453 ****
  			   && !DECL_EXTERNAL (node->decl)
  			   && !node->local.externally_visible);
      }
!   for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
      {
        if (vnode->needed
  	  && !flag_whole_program
--- 1305,1311 ----
  			   && !DECL_EXTERNAL (node->decl)
  			   && !node->local.externally_visible);
      }
!   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
      {
        if (vnode->needed
  	  && !flag_whole_program
*************** cgraph_optimize (void)
*** 1525,1532 ****
    if (!flag_unit_at_a_time)
      {
        cgraph_output_pending_asms ();
!       cgraph_varpool_assemble_pending_decls ();
!       cgraph_varpool_output_debug_info ();
        return;
      }
  
--- 1383,1390 ----
    if (!flag_unit_at_a_time)
      {
        cgraph_output_pending_asms ();
!       varpool_assemble_pending_decls ();
!       varpool_output_debug_info ();
        return;
      }
  
*************** cgraph_optimize (void)
*** 1534,1540 ****
  
    /* Frontend may output common variables after the unit has been finalized.
       It is safe to deal with them here as they are always zero initialized.  */
!   cgraph_varpool_analyze_pending_decls ();
  
    timevar_push (TV_CGRAPHOPT);
    if (!quiet_flag)
--- 1392,1398 ----
  
    /* Frontend may output common variables after the unit has been finalized.
       It is safe to deal with them here as they are always zero initialized.  */
!   varpool_analyze_pending_decls ();
  
    timevar_push (TV_CGRAPHOPT);
    if (!quiet_flag)
*************** cgraph_optimize (void)
*** 1580,1589 ****
        cgraph_output_pending_asms ();
  
        cgraph_expand_all_functions ();
!       cgraph_varpool_remove_unreferenced_decls ();
  
!       cgraph_varpool_assemble_pending_decls ();
!       cgraph_varpool_output_debug_info ();
      }
  
    if (cgraph_dump_file)
--- 1438,1447 ----
        cgraph_output_pending_asms ();
  
        cgraph_expand_all_functions ();
!       varpool_remove_unreferenced_decls ();
  
!       varpool_assemble_pending_decls ();
!       varpool_output_debug_info ();
      }
  
    if (cgraph_dump_file)
*************** cgraph_increase_alignment (void)
*** 1627,1636 ****
  {
    if (flag_section_anchors && flag_tree_vectorize)
      {
!       struct cgraph_varpool_node *vnode;
  
        /* Increase the alignment of all global arrays for vectorization.  */
!       for (vnode = cgraph_varpool_nodes_queue;
             vnode;
             vnode = vnode->next_needed)
          {
--- 1485,1494 ----
  {
    if (flag_section_anchors && flag_tree_vectorize)
      {
!       struct varpool_node *vnode;
  
        /* Increase the alignment of all global arrays for vectorization.  */
!       for (vnode = varpool_nodes_queue;
             vnode;
             vnode = vnode->next_needed)
          {
*************** save_inline_function_body (struct cgraph
*** 1923,1927 ****
  #endif
    return first_clone;
  }
- 
- #include "gt-cgraphunit.h"
--- 1781,1783 ----
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 119690)
--- cp/decl2.c	(working copy)
*************** import_export_class (tree ctype)
*** 1410,1416 ****
  static bool
  var_finalized_p (tree var)
  {
!   return cgraph_varpool_node (var)->finalized;
  }
  
  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
--- 1410,1416 ----
  static bool
  var_finalized_p (tree var)
  {
!   return varpool_node (var)->finalized;
  }
  
  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
Index: dwarf2out.c
===================================================================
*** dwarf2out.c	(revision 119690)
--- dwarf2out.c	(working copy)
*************** decls_for_scope (tree stmt, dw_die_ref c
*** 12926,12932 ****
  	    add_child_die (context_die, die);
  	  /* Do not produce debug information for static variables since
  	     these might be optimized out.  We are called for these later
! 	     in cgraph_varpool_analyze_pending_decls. */
  	  if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
  	    ;
  	  else
--- 12926,12932 ----
  	    add_child_die (context_die, die);
  	  /* Do not produce debug information for static variables since
  	     these might be optimized out.  We are called for these later
! 	     in varpool_analyze_pending_decls. */
  	  if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
  	    ;
  	  else
Index: fortran/f95-lang.c
===================================================================
*** fortran/f95-lang.c	(revision 119690)
--- fortran/f95-lang.c	(working copy)
*************** gfc_expand_function (tree fndecl)
*** 226,232 ****
  		&& TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
  		&& TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
  		   == UNION_TYPE
! 		&& cgraph_varpool_node (TREE_OPERAND (expr, 0))->needed
  		&& errorcount == 0 && sorrycount == 0)
  	      {
  		timevar_push (TV_SYMOUT);
--- 226,232 ----
  		&& TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
  		&& TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
  		   == UNION_TYPE
! 		&& varpool_node (TREE_OPERAND (expr, 0))->needed
  		&& errorcount == 0 && sorrycount == 0)
  	      {
  		timevar_push (TV_SYMOUT);
Index: ipa-type-escape.c
===================================================================
*** ipa-type-escape.c	(revision 119690)
--- ipa-type-escape.c	(working copy)
*************** ipa_init (void) 
*** 1337,1343 ****
     to variables defined within this unit.  */
  
  static void 
! analyze_variable (struct cgraph_varpool_node *vnode)
  {
    tree global = vnode->decl;
    tree type = get_canon_type (TREE_TYPE (global), false, false);
--- 1337,1343 ----
     to variables defined within this unit.  */
  
  static void 
! analyze_variable (struct varpool_node *vnode)
  {
    tree global = vnode->decl;
    tree type = get_canon_type (TREE_TYPE (global), false, false);
*************** static unsigned int
*** 1674,1680 ****
  type_escape_execute (void)
  {
    struct cgraph_node *node;
!   struct cgraph_varpool_node *vnode;
    unsigned int i;
    bitmap_iterator bi;
    splay_tree_node result;
--- 1674,1680 ----
  type_escape_execute (void)
  {
    struct cgraph_node *node;
!   struct varpool_node *vnode;
    unsigned int i;
    bitmap_iterator bi;
    splay_tree_node result;
*************** type_escape_execute (void)
*** 1682,1688 ****
    ipa_init ();
  
    /* Process all of the variables first.  */
!   for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
      analyze_variable (vnode);
  
    /* Process all of the functions. next
--- 1682,1688 ----
    ipa_init ();
  
    /* Process all of the variables first.  */
!   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
      analyze_variable (vnode);
  
    /* Process all of the functions. next
Index: except.c
===================================================================
*** except.c	(revision 119690)
--- except.c	(working copy)
*************** output_ttype (tree type, int tt_format, 
*** 3581,3587 ****
      value = const0_rtx;
    else
      {
!       struct cgraph_varpool_node *node;
  
        type = lookup_type_for_runtime (type);
        value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
--- 3581,3587 ----
      value = const0_rtx;
    else
      {
!       struct varpool_node *node;
  
        type = lookup_type_for_runtime (type);
        value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
*************** output_ttype (tree type, int tt_format, 
*** 3595,3603 ****
  	  type = TREE_OPERAND (type, 0);
  	  if (TREE_CODE (type) == VAR_DECL)
  	    {
! 	      node = cgraph_varpool_node (type);
  	      if (node)
! 		cgraph_varpool_mark_needed_node (node);
  	      public = TREE_PUBLIC (type);
  	    }
  	}
--- 3595,3603 ----
  	  type = TREE_OPERAND (type, 0);
  	  if (TREE_CODE (type) == VAR_DECL)
  	    {
! 	      node = varpool_node (type);
  	      if (node)
! 		varpool_mark_needed_node (node);
  	      public = TREE_PUBLIC (type);
  	    }
  	}
Index: varasm.c
===================================================================
*** varasm.c	(revision 119690)
--- varasm.c	(working copy)
*************** mark_decl_referenced (tree decl)
*** 2018,2025 ****
      }
    else if (TREE_CODE (decl) == VAR_DECL)
      {
!       struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
!       cgraph_varpool_mark_needed_node (node);
        /* C++ frontend use mark_decl_references to force COMDAT variables
           to be output that might appear dead otherwise.  */
        node->force_output = true;
--- 2018,2025 ----
      }
    else if (TREE_CODE (decl) == VAR_DECL)
      {
!       struct varpool_node *node = varpool_node (decl);
!       varpool_mark_needed_node (node);
        /* C++ frontend use mark_decl_references to force COMDAT variables
           to be output that might appear dead otherwise.  */
        node->force_output = true;
*************** static tree
*** 4808,4824 ****
  find_decl_and_mark_needed (tree decl, tree target)
  {
    struct cgraph_node *fnode = NULL;
!   struct cgraph_varpool_node *vnode = NULL;
  
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        fnode = cgraph_node_for_asm (target);
        if (fnode == NULL)
! 	vnode = cgraph_varpool_node_for_asm (target);
      }
    else
      {
!       vnode = cgraph_varpool_node_for_asm (target);
        if (vnode == NULL)
  	fnode = cgraph_node_for_asm (target);
      }
--- 4808,4824 ----
  find_decl_and_mark_needed (tree decl, tree target)
  {
    struct cgraph_node *fnode = NULL;
!   struct varpool_node *vnode = NULL;
  
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        fnode = cgraph_node_for_asm (target);
        if (fnode == NULL)
! 	vnode = varpool_node_for_asm (target);
      }
    else
      {
!       vnode = varpool_node_for_asm (target);
        if (vnode == NULL)
  	fnode = cgraph_node_for_asm (target);
      }
*************** find_decl_and_mark_needed (tree decl, tr
*** 4836,4842 ****
      }
    else if (vnode)
      {
!       cgraph_varpool_mark_needed_node (vnode);
        return vnode->decl;
      }
    else
--- 4836,4842 ----
      }
    else if (vnode)
      {
!       varpool_mark_needed_node (vnode);
        return vnode->decl;
      }
    else
*************** assemble_alias (tree decl, tree target)
*** 5029,5035 ****
    if (TREE_CODE (decl) == FUNCTION_DECL)
      cgraph_node (decl)->alias = true;
    else
!     cgraph_varpool_node (decl)->alias = true;
  
    /* If the target has already been emitted, we don't have to queue the
       alias.  This saves a tad o memory.  */
--- 5029,5035 ----
    if (TREE_CODE (decl) == FUNCTION_DECL)
      cgraph_node (decl)->alias = true;
    else
!     varpool_node (decl)->alias = true;
  
    /* If the target has already been emitted, we don't have to queue the
       alias.  This saves a tad o memory.  */
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 119690)
--- Makefile.in	(working copy)
*************** OBJS-md = $(out_object_file)
*** 1024,1030 ****
  OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) tree-inline.o		   \
    cgraph.o cgraphunit.o tree-nomudflap.o ipa.o ipa-inline.o                \
    ipa-utils.o ipa-reference.o ipa-pure-const.o ipa-type-escape.o           \
!   ipa-prop.o ipa-cp.o
  
  OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
  
--- 1024,1030 ----
  OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) tree-inline.o		   \
    cgraph.o cgraphunit.o tree-nomudflap.o ipa.o ipa-inline.o                \
    ipa-utils.o ipa-reference.o ipa-pure-const.o ipa-type-escape.o           \
!   ipa-prop.o ipa-cp.o varpool.o
  
  OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
  
*************** cgraphunit.o : cgraphunit.c $(CONFIG_H) 
*** 2298,2305 ****
     $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
     $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
     $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h \
!    gt-cgraphunit.h
  ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) 
  ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) ipa-prop.h \
--- 2298,2310 ----
     $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
     $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
+    $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h 
+ varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+    $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \
+    $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
+    $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
     $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h \
!    gt-varpool.h
  ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) 
  ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) ipa-prop.h \
*************** GTFILES = $(srcdir)/input.h $(srcdir)/co
*** 2878,2885 ****
    $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \
    $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
    $(srcdir)/tree-ssa-structalias.c \
!   $(srcdir)/c-pragma.h $(srcdir)/omp-low.c \
!   $(srcdir)/targhooks.c $(srcdir)/cgraphunit.c $(out_file) \
    @all_gtfiles@
  
  GTFILES_FILES_LANGS = @all_gtfiles_files_langs@
--- 2883,2890 ----
    $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \
    $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
    $(srcdir)/tree-ssa-structalias.c \
!   $(srcdir)/c-pragma.h $(srcdir)/omp-low.c $(srcdir)/varpool.c \
!   $(srcdir)/targhooks.c $(out_file) \
    @all_gtfiles@
  
  GTFILES_FILES_LANGS = @all_gtfiles_files_langs@
*************** gt-tree-mudflap.h gt-tree-vect-generic.h
*** 2909,2916 ****
  gt-tree-profile.h gt-tree-ssa-address.h \
  gt-tree-iterator.h gt-gimplify.h \
  gt-tree-phinodes.h gt-tree-nested.h \
! gt-tree-ssa-propagate.h \
! gt-tree-ssa-structalias.h gt-ipa-inline.h gt-cgraphunit.h \
  gt-stringpool.h gt-targhooks.h gt-omp-low.h : s-gtype ; @true
  
  define echo_quoted_to_gtyp
--- 2914,2921 ----
  gt-tree-profile.h gt-tree-ssa-address.h \
  gt-tree-iterator.h gt-gimplify.h \
  gt-tree-phinodes.h gt-tree-nested.h \
! gt-tree-ssa-propagate.h gt-varpool.h \
! gt-tree-ssa-structalias.h gt-ipa-inline.h \
  gt-stringpool.h gt-targhooks.h gt-omp-low.h : s-gtype ; @true
  
  define echo_quoted_to_gtyp
Index: passes.c
===================================================================
*** passes.c	(revision 119690)
--- passes.c	(working copy)
*************** rest_of_decl_compilation (tree decl,
*** 159,165 ****
  	  && !DECL_EXTERNAL (decl))
  	{
  	  if (TREE_CODE (decl) != FUNCTION_DECL)
! 	    cgraph_varpool_finalize_decl (decl);
  	  else
  	    assemble_variable (decl, top_level, at_end, 0);
  	}
--- 159,165 ----
  	  && !DECL_EXTERNAL (decl))
  	{
  	  if (TREE_CODE (decl) != FUNCTION_DECL)
! 	    varpool_finalize_decl (decl);
  	  else
  	    assemble_variable (decl, top_level, at_end, 0);
  	}
*************** rest_of_decl_compilation (tree decl,
*** 186,192 ****
  
    /* Let cgraph know about the existence of variables.  */
    if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
!     cgraph_varpool_node (decl);
  }
  
  /* Called after finishing a record, union or enumeral type.  */
--- 186,192 ----
  
    /* Let cgraph know about the existence of variables.  */
    if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
!     varpool_node (decl);
  }
  
  /* Called after finishing a record, union or enumeral type.  */
Index: varpool.c
===================================================================
*** varpool.c	(revision 0)
--- varpool.c	(revision 0)
***************
*** 0 ****
--- 1,451 ----
+ /* Callgraph handling code.
+    Copyright (C) 2003, 2004, 2005, 2006 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
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ 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.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "tree.h"
+ #include "cgraph.h"
+ #include "langhooks.h"
+ #include "diagnostic.h"
+ #include "hashtab.h"
+ #include "ggc.h"
+ #include "timevar.h"
+ #include "debug.h" 
+ #include "target.h"
+ #include "output.h"
+ 
+ /*  This file contains basic routines manipulating variable pool.
+ 
+     Varpool acts as interface in between the front-end and middle-end
+     and drives the decision process on what variables and when are
+     going to be compiled.
+ 
+     The varpool nodes are alocated lazilly 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.  */
+ 
+ /* Hash table used to convert declarations into nodes.  */
+ static GTY((param_is (struct varpool_node))) htab_t varpool_hash;
+ 
+ /* The linked list of cgraph varpool nodes.
+    Linked via node->next pointer.  */
+ struct varpool_node *varpool_nodes;
+ 
+ /* Queue of cgraph nodes scheduled to be lowered and output.
+    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.
+  
+    During unit-at-a-time 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.
+    
+    Each variable is thus first analyzed and then later possibly output.  
+    FIRST_UNANALYZED_NODE points to first node in queue that was not analyzed
+    yet and is moved via VARPOOL_ANALYZE_PENDING_DECLS.  */
+    
+ struct varpool_node *varpool_nodes_queue;
+ static GTY(()) struct varpool_node *varpool_last_needed_node;
+ static GTY(()) struct varpool_node *varpool_first_unanalyzed_node;
+ 
+ /* Lists all assembled variables to be sent to debugger output later on.  */
+ static GTY(()) struct varpool_node *varpool_assembled_nodes_queue;
+ 
+ /* Return name of the node used in debug output.  */
+ static const char *
+ varpool_node_name (struct varpool_node *node)
+ {
+   return lang_hooks.decl_printable_name (node->decl, 2);
+ }
+ 
+ /* Returns a hash code for P.  */
+ static hashval_t
+ hash_varpool_node (const void *p)
+ {
+   const struct varpool_node *n = (const struct varpool_node *) p;
+   return (hashval_t) DECL_UID (n->decl);
+ }
+ 
+ /* Returns nonzero if P1 and P2 are equal.  */
+ static int
+ eq_varpool_node (const void *p1, const void *p2)
+ {
+   const struct varpool_node *n1 =
+     (const struct varpool_node *) p1;
+   const struct varpool_node *n2 =
+     (const struct varpool_node *) p2;
+   return DECL_UID (n1->decl) == DECL_UID (n2->decl);
+ }
+ 
+ /* Return varpool node assigned to DECL.  Create new one when needed.  */
+ struct varpool_node *
+ varpool_node (tree decl)
+ {
+   struct varpool_node key, *node, **slot;
+ 
+   gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
+ 
+   if (!varpool_hash)
+     varpool_hash = htab_create_ggc (10, hash_varpool_node,
+ 					   eq_varpool_node, NULL);
+   key.decl = decl;
+   slot = (struct varpool_node **)
+     htab_find_slot (varpool_hash, &key, INSERT);
+   if (*slot)
+     return *slot;
+   node = GGC_CNEW (struct varpool_node);
+   node->decl = decl;
+   node->order = cgraph_order++;
+   node->next = varpool_nodes;
+   varpool_nodes = node;
+   *slot = node;
+   return node;
+ }
+ 
+ /* Dump given cgraph node.  */
+ void
+ dump_varpool_node (FILE *f, struct varpool_node *node)
+ {
+   fprintf (f, "%s:", varpool_node_name (node));
+   fprintf (f, " availability:%s",
+ 	   cgraph_function_flags_ready
+ 	   ? cgraph_availability_names[cgraph_variable_initializer_availability (node)]
+ 	   : "not-ready");
+   if (DECL_INITIAL (node->decl))
+     fprintf (f, " initialized");
+   if (node->needed)
+     fprintf (f, " needed");
+   if (node->analyzed)
+     fprintf (f, " analyzed");
+   if (node->finalized)
+     fprintf (f, " finalized");
+   if (node->output)
+     fprintf (f, " output");
+   if (node->externally_visible)
+     fprintf (f, " externally_visible");
+   fprintf (f, "\n");
+ }
+ 
+ /* Dump the variable pool.  */
+ void
+ dump_varpool (FILE *f)
+ {
+   struct varpool_node *node;
+ 
+   fprintf (f, "variable pool:\n\n");
+   for (node = varpool_nodes; node; node = node->next_needed)
+     dump_varpool_node (f, node);
+ }
+ 
+ /* Given an assembler name, lookup node.  */
+ struct varpool_node *
+ varpool_node_for_asm (tree asmname)
+ {
+   struct varpool_node *node;
+ 
+   for (node = varpool_nodes; node ; node = node->next)
+     if (decl_assembler_name_equal (node->decl, asmname))
+       return node;
+ 
+   return NULL;
+ }
+ 
+ /* Helper function for finalization code - add node into lists so it will
+    be analyzed and compiled.  */
+ static void
+ varpool_enqueue_needed_node (struct varpool_node *node)
+ {
+   if (varpool_last_needed_node)
+     varpool_last_needed_node->next_needed = node;
+   varpool_last_needed_node = node;
+   node->next_needed = NULL;
+   if (!varpool_nodes_queue)
+     varpool_nodes_queue = node;
+   if (!varpool_first_unanalyzed_node)
+     varpool_first_unanalyzed_node = node;
+   notice_global_symbol (node->decl);
+ }
+ 
+ /* Notify finalize_compilation_unit that given node is reachable
+    or needed.  */
+ void
+ varpool_mark_needed_node (struct varpool_node *node)
+ {
+   if (!node->needed && node->finalized
+       && !TREE_ASM_WRITTEN (node->decl))
+     varpool_enqueue_needed_node (node);
+   node->needed = 1;
+ }
+ 
+ /* Reset the queue of needed nodes.  */
+ static void
+ varpool_reset_queue (void)
+ {
+   varpool_last_needed_node = NULL;
+   varpool_nodes_queue = NULL;
+   varpool_first_unanalyzed_node = NULL;
+ }
+ 
+ /* 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.  */
+ 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)))
+     return true;
+ 
+   /* ??? If the assembler name is set by hand, it is possible to assemble
+      the name later after finalizing the function and the fact is noticed
+      in assemble_name then.  This is arguably a bug.  */
+   if (DECL_ASSEMBLER_NAME_SET_P (decl)
+       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+     return true;
+ 
+   /* If we decided it was needed before, but at the time we didn't have
+      the definition available, then it's still needed.  */
+   if (node->needed)
+     return true;
+ 
+   /* 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 && !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_unit_at_a_time && flag_toplevel_reorder)
+     return false;
+ 
+   /* We want to emit COMDAT variables only when absolutely necessary.  */
+   if (DECL_COMDAT (decl))
+     return false;
+   return true;
+ }
+ 
+ /* Mark DECL as finalized.  By finalizing the declaration, frontend instruct the
+    middle end to output the variable to asm file, if needed or externally
+    visible.  */
+ void
+ varpool_finalize_decl (tree decl)
+ {
+   struct varpool_node *node = varpool_node (decl);
+ 
+   /* The first declaration of a variable that comes through this function
+      decides whether it is global (in C, has external linkage)
+      or local (in C, has internal linkage).  So do nothing more
+      if this function has already run.  */
+   if (node->finalized)
+     {
+       if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
+ 	varpool_assemble_pending_decls ();
+       return;
+     }
+   if (node->needed)
+     varpool_enqueue_needed_node (node);
+   node->finalized = true;
+ 
+   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 || (!flag_unit_at_a_time && !flag_openmp))
+     varpool_assemble_pending_decls ();
+ }
+ 
+ /* Return variable availability.  See cgraph.h for description of individual
+    return values.  */
+ enum availability
+ cgraph_variable_initializer_availability (struct varpool_node *node)
+ {
+   gcc_assert (cgraph_function_flags_ready);
+   if (!node->finalized)
+     return AVAIL_NOT_AVAILABLE;
+   if (!TREE_PUBLIC (node->decl))
+     return AVAIL_AVAILABLE;
+   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
+      care of at least two notable extensions - the COMDAT variables
+      used to share template instantiations in C++.  */
+   if (!(*targetm.binds_local_p) (node->decl) && !DECL_COMDAT (node->decl))
+     return AVAIL_OVERWRITABLE;
+   return AVAIL_AVAILABLE;
+ }
+ 
+ /* Walk the decls we marked as necessary and see if they reference new
+    variables or functions and add them into the worklists.  */
+ bool
+ varpool_analyze_pending_decls (void)
+ {
+   bool changed = false;
+   timevar_push (TV_CGRAPH);
+ 
+   while (varpool_first_unanalyzed_node)
+     {
+       tree decl = varpool_first_unanalyzed_node->decl;
+ 
+       varpool_first_unanalyzed_node->analyzed = true;
+ 
+       varpool_first_unanalyzed_node = varpool_first_unanalyzed_node->next_needed;
+ 
+       /* Compute the alignment early so function body expanders are
+ 	 already informed about increased alignment.  */
+       align_variable (decl, 0);
+ 
+       if (DECL_INITIAL (decl))
+ 	record_references_in_initializer (decl);
+       changed = true;
+     }
+   timevar_pop (TV_CGRAPH);
+   return changed;
+ }
+ 
+ /* Output one variable, if necessary.  Return whether we output it.  */
+ bool
+ varpool_assemble_decl (struct varpool_node *node)
+ {
+   tree decl = node->decl;
+ 
+   if (!TREE_ASM_WRITTEN (decl)
+       && !node->alias
+       && !DECL_EXTERNAL (decl)
+       && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
+     {
+       assemble_variable (decl, 0, 1, 0);
+       return TREE_ASM_WRITTEN (decl);
+     }
+ 
+   return false;
+ }
+ 
+ /* Optimization of function bodies might've rendered some variables as
+    unnecessary so we want to avoid these from being compiled.
+ 
+    This is done by pruning the queue and keeping only the variables that
+    really appear needed (ie they are either externally visible or referenced
+    by compiled function). Re-doing the reachability analysis on variables
+    brings back the remaining variables referenced by these.  */
+ void
+ varpool_remove_unreferenced_decls (void)
+ {
+   struct varpool_node *next, *node = varpool_nodes_queue;
+ 
+   varpool_reset_queue ();
+ 
+   if (errorcount || sorrycount)
+     return;
+ 
+   while (node)
+     {
+       tree decl = node->decl;
+       next = node->next_needed;
+       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)
+ 	      /* ??? 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)))
+ 	varpool_mark_needed_node (node);
+ 
+       node = next;
+     }
+   /* Make sure we mark alias targets as used targets.  */
+   finish_aliases_1 ();
+   varpool_analyze_pending_decls ();
+ }
+ 
+ /* Output all variables enqueued to be assembled.  */
+ bool
+ varpool_assemble_pending_decls (void)
+ {
+   bool changed = false;
+ 
+   if (errorcount || sorrycount)
+     return false;
+ 
+   /* 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;
+       if (varpool_assemble_decl (node))
+ 	{
+ 	  changed = true;
+ 	  node->next_needed = varpool_assembled_nodes_queue;
+ 	  varpool_assembled_nodes_queue = node;
+ 	  node->finalized = 1;
+ 	}
+       else
+         node->next_needed = NULL;
+     }
+   return changed;
+ }
+ 
+ /* Output all variables enqueued to be assembled.  */
+ void
+ varpool_output_debug_info (void)
+ {
+   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);
+ }
+ 
+ #include "gt-varpool.h"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]