Move all varpool routines out of cgraph/cgraphunit to varpool.c

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.

From-SVN: r119731
This commit is contained in:
Jan Hubicka 2006-12-11 09:07:52 +01:00 committed by Jan Hubicka
parent ce133c3fa2
commit 8a4a83ed92
23 changed files with 682 additions and 528 deletions

View file

@ -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

View file

@ -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)
@ -2290,11 +2290,16 @@ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
$(TREE_INLINE_H) $(VARRAY_H) $(TREE_DUMP_H)
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

View file

@ -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.

View file

@ -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);

View file

@ -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"

View file

@ -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.

View file

@ -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,

View file

@ -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

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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);

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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. */

View file

@ -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.

View file

@ -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. */

View file

@ -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. */

View file

@ -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. */

451
gcc/varpool.c Normal file
View file

@ -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"