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:
parent
ce133c3fa2
commit
8a4a83ed92
23 changed files with 682 additions and 528 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
292
gcc/cgraph.c
292
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.
|
||||
|
||||
|
|
52
gcc/cgraph.h
52
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);
|
||||
|
|
228
gcc/cgraphunit.c
228
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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
34
gcc/tree.c
34
gcc/tree.c
|
@ -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. */
|
||||
|
|
14
gcc/varasm.c
14
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. */
|
||||
|
|
451
gcc/varpool.c
Normal file
451
gcc/varpool.c
Normal 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"
|
Loading…
Add table
Reference in a new issue