diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 68 | ||||
-rw-r--r-- | gcc/Makefile.in | 17 | ||||
-rw-r--r-- | gcc/cgraph.c | 292 | ||||
-rw-r--r-- | gcc/cgraph.h | 52 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 228 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 2 | ||||
-rw-r--r-- | gcc/except.c | 6 | ||||
-rw-r--r-- | gcc/fortran/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/fortran/f95-lang.c | 2 | ||||
-rw-r--r-- | gcc/ipa-reference.c | 6 | ||||
-rw-r--r-- | gcc/ipa-type-escape.c | 6 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/java/class.c | 2 | ||||
-rw-r--r-- | gcc/java/resource.c | 2 | ||||
-rw-r--r-- | gcc/omp-low.c | 2 | ||||
-rw-r--r-- | gcc/passes.c | 4 | ||||
-rw-r--r-- | gcc/toplev.c | 6 | ||||
-rw-r--r-- | gcc/tree.c | 34 | ||||
-rw-r--r-- | gcc/tree.h | 1 | ||||
-rw-r--r-- | gcc/varasm.c | 14 | ||||
-rw-r--r-- | gcc/varpool.c | 451 |
23 files changed, 682 insertions, 528 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b4c1f139..7d7cf28 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,71 @@ +2006-12-11 Jan Hubicka <jh@suse.cz> + + 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. + 2006-12-11 Ira Rosen <irar@il.ibm.com> * tree-vect-patterns.c (vect_recog_dot_prod_pattern): Use diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 8da131d..8613e6c 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1024,7 +1024,7 @@ OBJS-md = $(out_object_file) 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 + ipa-prop.o ipa-cp.o varpool.o OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive) @@ -2293,8 +2293,13 @@ cgraphunit.o : cgraphunit.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 +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-cgraphunit.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 \ @@ -2873,8 +2878,8 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \ $(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) \ + $(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@ @@ -2904,8 +2909,8 @@ gt-tree-mudflap.h gt-tree-vect-generic.h \ 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-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 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 23429fe..7706098 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -19,7 +19,7 @@ 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. */ -/* This file contains basic routines manipulating call graph and variable pool +/* This file contains basic routines manipulating call graph The callgraph: @@ -69,15 +69,7 @@ The callgraph: 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 */ - + why inlining wasn't performed. */ #include "config.h" #include "system.h" @@ -130,18 +122,6 @@ bool cgraph_global_info_ready = false; /* 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; @@ -243,40 +223,6 @@ cgraph_insert_node_to_hashtable (struct cgraph_node *node) *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. */ @@ -683,15 +629,8 @@ cgraph_node_name (struct cgraph_node *node) 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[] = +const char * const cgraph_availability_names[] = {"unset", "not_available", "overwrittable", "available", "local"}; /* Dump given cgraph node. */ @@ -706,7 +645,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) node->global.inlined_to->uid); if (cgraph_function_flags_ready) fprintf (f, " availability:%s", - availability_names [cgraph_function_body_availability (node)]); + 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) @@ -785,100 +724,6 @@ dump_cgraph (FILE *f) 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) @@ -898,116 +743,6 @@ change_decl_assembler_name (tree decl, tree name) 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 * @@ -1181,25 +916,6 @@ cgraph_function_body_availability (struct cgraph_node *node) 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. diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 8965563..b60239c 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -46,6 +46,8 @@ enum availability AVAIL_LOCAL }; +extern const char * const cgraph_availability_names[]; + /* Information about the function collected locally. Available after function is analyzed. */ @@ -204,16 +206,16 @@ typedef struct cgraph_edge *cgraph_edge_p; 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. */ +/* The varpool data structure. + Each static variable decl has assigned varpool_node. */ -struct cgraph_varpool_node GTY(()) +struct 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; + /* 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; @@ -256,9 +258,6 @@ extern bool cgraph_function_flags_ready; 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; @@ -266,8 +265,6 @@ extern GTY(()) int cgraph_order; 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); @@ -288,28 +285,19 @@ struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, 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); @@ -327,11 +315,33 @@ struct cgraph_node *cgraph_function_versioning (struct cgraph_node *, 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); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 26399d3..73015b6 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -35,7 +35,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA (There is one exception needed for implementing GCC extern inline function.) - - cgraph_varpool_finalize_variable + - varpool_finalize_variable This function has same behavior as the above but is used for static variables. @@ -60,7 +60,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA modify calling conventions, do better inlining or similar optimizations. - cgraph_mark_needed_node - - cgraph_varpool_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. @@ -82,8 +82,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 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 + 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. @@ -168,9 +168,6 @@ static tree record_reference (tree *, int *, void *); 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 @@ -265,83 +262,6 @@ decide_is_function_needed (struct cgraph_node *node, tree decl) 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. */ @@ -521,7 +441,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data) after rtl has been generated. */ if (TREE_STATIC (t) || DECL_EXTERNAL (t)) { - cgraph_varpool_mark_needed_node (cgraph_varpool_node (t)); + varpool_mark_needed_node (varpool_node (t)); if (lang_hooks.callgraph.analyze_expr) return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees, data); @@ -602,7 +522,7 @@ cgraph_create_edges (struct cgraph_node *node, tree body) if (TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) && flag_unit_at_a_time) - cgraph_varpool_finalize_decl (decl); + varpool_finalize_decl (decl); else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl)) walk_tree (&DECL_INITIAL (decl), record_reference, node, visited_nodes); } @@ -611,6 +531,16 @@ cgraph_create_edges (struct cgraph_node *node, tree body) 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. */ @@ -844,78 +774,6 @@ verify_cgraph (void) 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 @@ -990,10 +848,10 @@ cgraph_analyze_function (struct cgraph_node *node) static void process_function_and_variable_attributes (struct cgraph_node *first, - struct cgraph_varpool_node *first_var) + struct varpool_node *first_var) { struct cgraph_node *node; - struct cgraph_varpool_node *vnode; + struct varpool_node *vnode; for (node = cgraph_nodes; node != first; node = node->next) { @@ -1018,14 +876,14 @@ process_function_and_variable_attributes (struct cgraph_node *first, } } } - for (vnode = cgraph_varpool_nodes; vnode != first_var; vnode = vnode->next) + 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) - cgraph_varpool_mark_needed_node (vnode); + varpool_mark_needed_node (vnode); } if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) { @@ -1036,7 +894,7 @@ process_function_and_variable_attributes (struct cgraph_node *first, else { if (vnode->finalized) - cgraph_varpool_mark_needed_node (vnode); + varpool_mark_needed_node (vnode); vnode->externally_visible = true; } } @@ -1053,7 +911,7 @@ cgraph_finalize_compilation_unit (void) intermodule optimization. */ static struct cgraph_node *first_analyzed; struct cgraph_node *first_processed = first_analyzed; - static struct cgraph_varpool_node *first_analyzed_var; + static struct varpool_node *first_analyzed_var; if (errorcount || sorrycount) return; @@ -1064,7 +922,7 @@ cgraph_finalize_compilation_unit (void) { cgraph_output_pending_asms (); cgraph_assemble_pending_functions (); - cgraph_varpool_output_debug_info (); + varpool_output_debug_info (); return; } @@ -1078,8 +936,8 @@ cgraph_finalize_compilation_unit (void) 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 (); + first_analyzed_var = varpool_nodes; + varpool_analyze_pending_decls (); if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Initial entry points:"); @@ -1125,8 +983,8 @@ cgraph_finalize_compilation_unit (void) 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 (); + first_analyzed_var = varpool_nodes; + varpool_analyze_pending_decls (); } /* Collect entry points to the unit. */ @@ -1328,7 +1186,7 @@ struct cgraph_order_sort union { struct cgraph_node *f; - struct cgraph_varpool_node *v; + struct varpool_node *v; struct cgraph_asm_node *a; } u; }; @@ -1347,7 +1205,7 @@ cgraph_output_in_order (void) struct cgraph_order_sort *nodes; int i; struct cgraph_node *pf; - struct cgraph_varpool_node *pv; + struct varpool_node *pv; struct cgraph_asm_node *pa; max = cgraph_order; @@ -1355,7 +1213,7 @@ cgraph_output_in_order (void) nodes = (struct cgraph_order_sort *) alloca (size); memset (nodes, 0, size); - cgraph_varpool_analyze_pending_decls (); + varpool_analyze_pending_decls (); for (pf = cgraph_nodes; pf; pf = pf->next) { @@ -1368,7 +1226,7 @@ cgraph_output_in_order (void) } } - for (pv = cgraph_varpool_nodes_queue; pv; pv = pv->next_needed) + for (pv = varpool_nodes_queue; pv; pv = pv->next_needed) { i = pv->order; gcc_assert (nodes[i].kind == ORDER_UNDEFINED); @@ -1394,7 +1252,7 @@ cgraph_output_in_order (void) break; case ORDER_VAR: - cgraph_varpool_assemble_decl (nodes[i].u.v); + varpool_assemble_decl (nodes[i].u.v); break; case ORDER_ASM: @@ -1427,7 +1285,7 @@ static void cgraph_function_and_variable_visibility (void) { struct cgraph_node *node; - struct cgraph_varpool_node *vnode; + struct varpool_node *vnode; for (node = cgraph_nodes; node; node = node->next) { @@ -1447,7 +1305,7 @@ cgraph_function_and_variable_visibility (void) && !DECL_EXTERNAL (node->decl) && !node->local.externally_visible); } - for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed) + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) { if (vnode->needed && !flag_whole_program @@ -1525,8 +1383,8 @@ cgraph_optimize (void) if (!flag_unit_at_a_time) { cgraph_output_pending_asms (); - cgraph_varpool_assemble_pending_decls (); - cgraph_varpool_output_debug_info (); + varpool_assemble_pending_decls (); + varpool_output_debug_info (); return; } @@ -1534,7 +1392,7 @@ cgraph_optimize (void) /* 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 (); + varpool_analyze_pending_decls (); timevar_push (TV_CGRAPHOPT); if (!quiet_flag) @@ -1580,10 +1438,10 @@ cgraph_optimize (void) cgraph_output_pending_asms (); cgraph_expand_all_functions (); - cgraph_varpool_remove_unreferenced_decls (); + varpool_remove_unreferenced_decls (); - cgraph_varpool_assemble_pending_decls (); - cgraph_varpool_output_debug_info (); + varpool_assemble_pending_decls (); + varpool_output_debug_info (); } if (cgraph_dump_file) @@ -1627,10 +1485,10 @@ cgraph_increase_alignment (void) { if (flag_section_anchors && flag_tree_vectorize) { - struct cgraph_varpool_node *vnode; + struct varpool_node *vnode; /* Increase the alignment of all global arrays for vectorization. */ - for (vnode = cgraph_varpool_nodes_queue; + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) { @@ -1923,5 +1781,3 @@ save_inline_function_body (struct cgraph_node *node) #endif return first_clone; } - -#include "gt-cgraphunit.h" diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e72ffeb..54b244c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2006-12-11 Jan Hubicka <jh@suse.cz> + + * decl2.c (var_finalized_p): Update for renamed varpool functions. + 2006-12-09 Zack Weinberg <zackw@panix.com> * parser.c (yydebug, enum pragma_omp_clause): Delete. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index b2a97ff..0c0695e 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1410,7 +1410,7 @@ import_export_class (tree ctype) static bool var_finalized_p (tree var) { - return cgraph_varpool_node (var)->finalized; + return varpool_node (var)->finalized; } /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason, diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 9a4903b..a9f6308 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -12926,7 +12926,7 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth) 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. */ + in varpool_analyze_pending_decls. */ if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) ; else diff --git a/gcc/except.c b/gcc/except.c index c51307b..9f40dc4 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -3581,7 +3581,7 @@ output_ttype (tree type, int tt_format, int tt_format_size) value = const0_rtx; else { - struct cgraph_varpool_node *node; + struct varpool_node *node; type = lookup_type_for_runtime (type); value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); @@ -3595,9 +3595,9 @@ output_ttype (tree type, int tt_format, int tt_format_size) type = TREE_OPERAND (type, 0); if (TREE_CODE (type) == VAR_DECL) { - node = cgraph_varpool_node (type); + node = varpool_node (type); if (node) - cgraph_varpool_mark_needed_node (node); + varpool_mark_needed_node (node); public = TREE_PUBLIC (type); } } diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 16845ee..e3b6852 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,7 @@ +2006-12-11 Jan Hubicka <jh@suse.cz> + + * f59-lang.c (gfc_expand_function): Update for renamed varpool functions. + 2006-12-10 Tobias Burnus <burnus@net-b.de> * gfortran.texi: Update Fortran 2003 section. diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index 1151318..4caaa1a 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -226,7 +226,7 @@ gfc_expand_function (tree fndecl) && 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 + && varpool_node (TREE_OPERAND (expr, 0))->needed && errorcount == 0 && sorrycount == 0) { timevar_push (TV_SYMOUT); diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index 9780acf..9427fd5d 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -770,7 +770,7 @@ ipa_init (void) to variables defined within this unit. */ static void -analyze_variable (struct cgraph_varpool_node *vnode) +analyze_variable (struct varpool_node *vnode) { tree global = vnode->decl; if (TREE_CODE (global) == VAR_DECL) @@ -892,7 +892,7 @@ static unsigned int static_execute (void) { struct cgraph_node *node; - struct cgraph_varpool_node *vnode; + struct varpool_node *vnode; struct cgraph_node *w; struct cgraph_node **order = xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *)); @@ -902,7 +902,7 @@ static_execute (void) ipa_init (); /* Process all of the variables first. */ - for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed) + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) analyze_variable (vnode); /* Process all of the functions next. diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c index 0b0c19a..faddb77 100644 --- a/gcc/ipa-type-escape.c +++ b/gcc/ipa-type-escape.c @@ -1337,7 +1337,7 @@ ipa_init (void) to variables defined within this unit. */ static void -analyze_variable (struct cgraph_varpool_node *vnode) +analyze_variable (struct varpool_node *vnode) { tree global = vnode->decl; tree type = get_canon_type (TREE_TYPE (global), false, false); @@ -1674,7 +1674,7 @@ static unsigned int type_escape_execute (void) { struct cgraph_node *node; - struct cgraph_varpool_node *vnode; + struct varpool_node *vnode; unsigned int i; bitmap_iterator bi; splay_tree_node result; @@ -1682,7 +1682,7 @@ type_escape_execute (void) ipa_init (); /* Process all of the variables first. */ - for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed) + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) analyze_variable (vnode); /* Process all of the functions. next diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 46d7d1d..edd58d4 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,8 @@ +2006-11-12 Jan Hubicka <jh@suse.cz> + + * resource.c (compile_resource_data): Update for new varpool names. + * java/class.c (build_utf8_ref): Likewise. + 2006-11-12 David Daney <ddaney@avtrex.com> PR java/29805 diff --git a/gcc/java/class.c b/gcc/java/class.c index cdb298e..b1faafc 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -937,7 +937,7 @@ build_utf8_ref (tree name) layout_decl (decl, 0); pushdecl (decl); rest_of_decl_compilation (decl, global_bindings_p (), 0); - cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl)); + varpool_mark_needed_node (varpool_node (decl)); utf8_decl_list = decl; ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl); IDENTIFIER_UTF8_REF (name) = ref; diff --git a/gcc/java/resource.c b/gcc/java/resource.c index fd3d494..b0b941c 100644 --- a/gcc/java/resource.c +++ b/gcc/java/resource.c @@ -93,7 +93,7 @@ compile_resource_data (const char *name, const char *buffer, int length) layout_decl (decl, 0); pushdecl (decl); rest_of_decl_compilation (decl, global_bindings_p (), 0); - cgraph_varpool_finalize_decl (decl); + varpool_finalize_decl (decl); resources = tree_cons (NULL_TREE, decl, resources); } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 625ac37..141efa0 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3929,7 +3929,7 @@ lower_omp_critical (tree *stmt_p, omp_context *ctx) DECL_COMMON (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; - cgraph_varpool_finalize_decl (decl); + varpool_finalize_decl (decl); splay_tree_insert (critical_name_mutexes, (splay_tree_key) name, (splay_tree_value) decl); diff --git a/gcc/passes.c b/gcc/passes.c index 13b3b33..e5faaa4 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -159,7 +159,7 @@ rest_of_decl_compilation (tree decl, && !DECL_EXTERNAL (decl)) { if (TREE_CODE (decl) != FUNCTION_DECL) - cgraph_varpool_finalize_decl (decl); + varpool_finalize_decl (decl); else assemble_variable (decl, top_level, at_end, 0); } @@ -186,7 +186,7 @@ rest_of_decl_compilation (tree decl, /* Let cgraph know about the existence of variables. */ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) - cgraph_varpool_node (decl); + varpool_node (decl); } /* Called after finishing a record, union or enumeral type. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 5fd8c4d..0aa6f6c 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -751,9 +751,9 @@ wrapup_global_declaration_2 (tree decl) if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) { - struct cgraph_varpool_node *node; + struct varpool_node *node; bool needed = true; - node = cgraph_varpool_node (decl); + node = varpool_node (decl); if (node->finalized) needed = false; @@ -1042,7 +1042,7 @@ compile_file (void) if (errorcount || sorrycount) return; - cgraph_varpool_assemble_pending_decls (); + varpool_assemble_pending_decls (); finish_aliases_2 (); /* This must occur after the loop to output deferred functions. @@ -307,6 +307,40 @@ decl_assembler_name (tree decl) 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. */ @@ -3496,6 +3496,7 @@ enum ptrmemfunc_vbit_where_t #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. */ diff --git a/gcc/varasm.c b/gcc/varasm.c index 1e7af0e..50487d2 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2018,8 +2018,8 @@ mark_decl_referenced (tree decl) } else if (TREE_CODE (decl) == VAR_DECL) { - struct cgraph_varpool_node *node = cgraph_varpool_node (decl); - cgraph_varpool_mark_needed_node (node); + 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; @@ -4808,17 +4808,17 @@ static tree find_decl_and_mark_needed (tree decl, tree target) { struct cgraph_node *fnode = NULL; - struct cgraph_varpool_node *vnode = NULL; + struct 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); + vnode = varpool_node_for_asm (target); } else { - vnode = cgraph_varpool_node_for_asm (target); + vnode = varpool_node_for_asm (target); if (vnode == NULL) fnode = cgraph_node_for_asm (target); } @@ -4836,7 +4836,7 @@ find_decl_and_mark_needed (tree decl, tree target) } else if (vnode) { - cgraph_varpool_mark_needed_node (vnode); + varpool_mark_needed_node (vnode); return vnode->decl; } else @@ -5029,7 +5029,7 @@ assemble_alias (tree decl, tree target) if (TREE_CODE (decl) == FUNCTION_DECL) cgraph_node (decl)->alias = true; else - cgraph_varpool_node (decl)->alias = true; + 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. */ diff --git a/gcc/varpool.c b/gcc/varpool.c new file mode 100644 index 0000000..2c3a43e --- /dev/null +++ b/gcc/varpool.c @@ -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" |