cgraph.c (dump_cgraph_node): Print new flags.

* cgraph.c (dump_cgraph_node): Print new flags.
	(dump_cgraph_varpool_node): Likewise.
	(decide_variable_is_needed): Initialize externally_visible flag.
	* cgraph.h (cgraph_local_info): Add externally_visible flag.
	(cgraph_varpool_node): Likewise.
	(cgraph_function_flags_ready): Declare.
	* cgraph.c (cgraph_mark_local_functions): Rename to ...
	(cgraph_function_and_variable_visibility) ... this one; handle
	externally_visible flags.
	(decide_is_function_needed): Set externally_visible flag.
	(cgraph_finalize_function): Deal properly with early cleanups.
	(cgraph_optimize): Update call of
	cgraph_function_and_variable_visibility.

From-SVN: r100491
This commit is contained in:
Jan Hubicka 2005-06-02 12:59:00 +02:00 committed by Jan Hubicka
parent 75c702541a
commit e7d6beb0f8
4 changed files with 89 additions and 21 deletions

View File

@ -1,3 +1,19 @@
2005-06-02 Jan Hubicka <jh@suse.cz>
* cgraph.c (dump_cgraph_node): Print new flags.
(dump_cgraph_varpool_node): Likewise.
(decide_variable_is_needed): Initialize externally_visible flag.
* cgraph.h (cgraph_local_info): Add externally_visible flag.
(cgraph_varpool_node): Likewise.
(cgraph_function_flags_ready): Declare.
* cgraph.c (cgraph_mark_local_functions): Rename to ...
(cgraph_function_and_variable_visibility) ... this one; handle
externally_visible flags.
(decide_is_function_needed): Set externally_visible flag.
(cgraph_finalize_function): Deal properly with early cleanups.
(cgraph_optimize): Update call of
cgraph_function_and_variable_visibility.
2005-06-02 Steven Bosscher <stevenb@suse.de>
Mostafa Hagog <mustafa@il.ibm.com>

View File

@ -582,10 +582,16 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " output");
if (node->local.local)
fprintf (f, " local");
if (node->local.externally_visible)
fprintf (f, " externally_visible");
if (node->local.finalized)
fprintf (f, " finalized");
if (node->local.disregard_inline_limits)
fprintf (f, " always_inline");
else if (node->local.inlinable)
fprintf (f, " inlinable");
if (node->local.redefined_extern_inline)
fprintf (f, " redefined_extern_inline");
if (TREE_ASM_WRITTEN (node->decl))
fprintf (f, " asm_written");
@ -639,6 +645,8 @@ dump_cgraph_varpool_node (FILE *f, struct cgraph_varpool_node *node)
fprintf (f, " finalized");
if (node->output)
fprintf (f, " output");
if (node->externally_visible)
fprintf (f, " externally_visible");
fprintf (f, "\n");
}
@ -786,8 +794,8 @@ decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
if (node->needed)
return true;
/* Externally visible functions must be output. The exception is
COMDAT functions that must be output only when they are needed. */
/* Externally visible variables must be output. The exception is
COMDAT variables that must be output only when they are needed. */
if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
return true;
@ -824,6 +832,11 @@ cgraph_varpool_finalize_decl (tree decl)
if (decide_is_variable_needed (node, decl))
cgraph_varpool_mark_needed_node (node);
/* Since we reclaim unrechable nodes at the end of every language
level unit, we need to be conservative about possible entry points
there. */
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)
cgraph_varpool_assemble_pending_decls ();
}

View File

@ -36,6 +36,9 @@ struct cgraph_local_info GTY(())
and its address is never taken. */
bool local;
/* Set when function is visible by other units. */
bool externally_visible;
/* Set once it has been finalized so we consider it to be output. */
bool finalized;
@ -177,6 +180,8 @@ struct cgraph_varpool_node GTY(())
bool finalized;
/* Set when function is scheduled to be assembled. */
bool output;
/* Set when function is visible by other units. */
bool externally_visible;
/* Set for aliases once they got through assemble_alias. */
bool alias;
};
@ -185,6 +190,7 @@ extern GTY(()) struct cgraph_node *cgraph_nodes;
extern GTY(()) int cgraph_n_nodes;
extern GTY(()) int cgraph_max_uid;
extern bool cgraph_global_info_ready;
extern bool cgraph_function_flags_ready;
extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_first_unanalyzed_node;

View File

@ -170,7 +170,6 @@ static void cgraph_expand_all_functions (void);
static void cgraph_mark_functions_to_output (void);
static void cgraph_expand_function (struct cgraph_node *);
static tree record_reference (tree *, int *, void *);
static void cgraph_mark_local_functions (void);
static void cgraph_analyze_function (struct cgraph_node *node);
/* Records tree nodes seen in record_reference. Simply using
@ -191,6 +190,17 @@ decide_is_function_needed (struct cgraph_node *node, tree decl)
{
tree origin;
/* If the user told us it is used, then it must be so. */
if (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 body of the function available, then it's still needed. We have
to go back and re-check its dependencies now. */
@ -207,17 +217,6 @@ decide_is_function_needed (struct cgraph_node *node, tree decl)
if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))
return true;
/* If the user told us it is used, then it must be so. */
if (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 (flag_unit_at_a_time)
return false;
@ -422,6 +421,12 @@ cgraph_finalize_function (tree decl, bool nested)
if (decide_is_function_needed (node, decl))
cgraph_mark_needed_node (node);
/* Since we reclaim unrechable nodes at the end of every language
level unit, we need to be conservative about possible entry points
there. */
if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
cgraph_mark_reachable_node (node);
/* If not unit at a time, go ahead and emit everything we've found
to be reachable at this time. */
if (!nested)
@ -1016,25 +1021,47 @@ cgraph_expand_all_functions (void)
free (order);
}
/* Mark all local functions.
/* Mark visibility of all functions.
A local function is one whose calls can occur only in the current
compilation unit and all its calls are explicit, so we can change
its calling convention. We simply mark all static functions whose
address is not taken as local. */
address is not taken as local.
We also change the TREE_PUBLIC flag of all declarations that are public
in language point of view but we want to overwrite this default
via visibilities for the backend point of view. */
static void
cgraph_mark_local_functions (void)
cgraph_function_and_variable_visibility (void)
{
struct cgraph_node *node;
struct cgraph_varpool_node *vnode;
/* Figure out functions we want to assemble. */
for (node = cgraph_nodes; node; node = node->next)
{
if (node->reachable
&& (DECL_COMDAT (node->decl)
|| (TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl))))
node->local.externally_visible = 1;
node->local.local = (!node->needed
&& DECL_SAVED_TREE (node->decl)
&& !TREE_PUBLIC (node->decl));
&& node->analyzed
&& node->local.externally_visible);
}
for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
{
if (vnode->needed
&& (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)))
vnode->externally_visible = 1;
gcc_assert (TREE_STATIC (vnode->decl));
}
/* Because we have to be conservative on the boundaries of source
level units, it is possible that we marked some functions in
reachable just because they might be used later via external
linkage, but after making them local they are really unreachable
now. */
cgraph_remove_unreachable_nodes (true, cgraph_dump_file);
if (cgraph_dump_file)
{
@ -1043,7 +1070,13 @@ cgraph_mark_local_functions (void)
if (node->local.local)
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n\n");
fprintf (cgraph_dump_file, "\nMarking externally visible functions:");
for (node = cgraph_nodes; node; node = node->next)
if (node->local.externally_visible)
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n\n");
}
cgraph_function_flags_ready = true;
}
/* Return true when function body of DECL still needs to be kept around
@ -1088,7 +1121,7 @@ cgraph_optimize (void)
if (!quiet_flag)
fprintf (stderr, "Performing intraprocedural optimizations\n");
cgraph_mark_local_functions ();
cgraph_function_and_variable_visibility ();
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "Marked ");