mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-02 16:23:56 +08:00
cgraph.c (cgraph_nodes_queue): Declare.
* cgraph.c (cgraph_nodes_queue): Declare. (eq_node): Take identifier as p2. (cgraph_node): Update htab_find_slot_with_hash call. (cgraph_node_for_identifier): New. (cgraph_mark_needed_node): Move here from cgraphunit.c. * cgraph.h (cgraph_nodes_queue): Declare. (cgraph_node_for_identifier): Declare. * cgraphunit.c (cgraph_finalize_function): Collect entry points here instead of in cgraph_finalize_compilation_unit; constructors and destructors are entry points. (cgraph_finalize_compilation_unit): Reorganize debug outout; examine nested functions after lowerng; call collect_functions hook. (cgraph_mark_local_functions): DECL_COMDAT functions are not local. (cgraph_finalize_compilation_unit): Do not collect entry points. * varasm.c: Include cgraph.h (assemble_name): Mark referenced identifier as needed. * cgraphunit.c (record_call_1): Use get_callee_fndecl. From-SVN: r68390
This commit is contained in:
parent
89ce1c8f76
commit
1668aabc22
@ -1,3 +1,24 @@
|
||||
Mon Jun 23 23:07:35 CEST 2003 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* cgraph.c (cgraph_nodes_queue): Declare.
|
||||
(eq_node): Take identifier as p2.
|
||||
(cgraph_node): Update htab_find_slot_with_hash call.
|
||||
(cgraph_node_for_identifier): New.
|
||||
(cgraph_mark_needed_node): Move here from cgraphunit.c.
|
||||
* cgraph.h (cgraph_nodes_queue): Declare.
|
||||
(cgraph_node_for_identifier): Declare.
|
||||
* cgraphunit.c (cgraph_finalize_function): Collect entry points here
|
||||
instead of in cgraph_finalize_compilation_unit; constructors and
|
||||
destructors are entry points.
|
||||
(cgraph_finalize_compilation_unit): Reorganize debug outout;
|
||||
examine nested functions after lowerng; call collect_functions hook.
|
||||
(cgraph_mark_local_functions): DECL_COMDAT functions are not local.
|
||||
(cgraph_finalize_compilation_unit): Do not collect entry points.
|
||||
* varasm.c: Include cgraph.h
|
||||
(assemble_name): Mark referenced identifier as needed.
|
||||
|
||||
* cgraphunit.c (record_call_1): Use get_callee_fndecl.
|
||||
|
||||
2003-06-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/i386/i386.c (x86_output_mi_thunk): Don't pass MEM to %P0,
|
||||
|
54
gcc/cgraph.c
54
gcc/cgraph.c
@ -48,6 +48,9 @@ static htab_t cgraph_hash = 0;
|
||||
/* The linked list of cgraph nodes. */
|
||||
struct cgraph_node *cgraph_nodes;
|
||||
|
||||
/* Queue of cgraph nodes scheduled to be lowered. */
|
||||
struct cgraph_node *cgraph_nodes_queue;
|
||||
|
||||
/* Number of nodes in existence. */
|
||||
int cgraph_n_nodes;
|
||||
|
||||
@ -79,7 +82,7 @@ eq_node (p1, p2)
|
||||
const void *p2;
|
||||
{
|
||||
return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) ==
|
||||
DECL_ASSEMBLER_NAME ((tree) p2));
|
||||
(tree) p2);
|
||||
}
|
||||
|
||||
/* Return cgraph node assigned to DECL. Create new one when needed. */
|
||||
@ -100,7 +103,8 @@ cgraph_node (decl)
|
||||
}
|
||||
|
||||
slot =
|
||||
(struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, decl,
|
||||
(struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash,
|
||||
DECL_ASSEMBLER_NAME (decl),
|
||||
htab_hash_pointer
|
||||
(DECL_ASSEMBLER_NAME
|
||||
(decl)), 1);
|
||||
@ -125,6 +129,30 @@ cgraph_node (decl)
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Try to find existing function for identifier ID. */
|
||||
struct cgraph_node *
|
||||
cgraph_node_for_identifier (id)
|
||||
tree id;
|
||||
{
|
||||
struct cgraph_node **slot;
|
||||
|
||||
if (TREE_CODE (id) != IDENTIFIER_NODE)
|
||||
abort ();
|
||||
|
||||
if (!cgraph_hash)
|
||||
{
|
||||
cgraph_hash = htab_create (10, hash_node, eq_node, NULL);
|
||||
VARRAY_TREE_INIT (known_fns, 32, "known_fns");
|
||||
}
|
||||
|
||||
slot =
|
||||
(struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, id,
|
||||
htab_hash_pointer (id), 0);
|
||||
if (!slot)
|
||||
return NULL;
|
||||
return *slot;
|
||||
}
|
||||
|
||||
/* Create edge from CALLER to CALLEE in the cgraph. */
|
||||
|
||||
static struct cgraph_edge *
|
||||
@ -194,6 +222,28 @@ cgraph_remove_node (node)
|
||||
/* Do not free the structure itself so the walk over chain can continue. */
|
||||
}
|
||||
|
||||
/* Notify finalize_compilation_unit that given node is reachable
|
||||
or needed. */
|
||||
void
|
||||
cgraph_mark_needed_node (node, needed)
|
||||
struct cgraph_node *node;
|
||||
int needed;
|
||||
{
|
||||
if (needed)
|
||||
{
|
||||
node->needed = 1;
|
||||
}
|
||||
if (!node->reachable)
|
||||
{
|
||||
node->reachable = 1;
|
||||
if (DECL_SAVED_TREE (node->decl))
|
||||
{
|
||||
node->aux = cgraph_nodes_queue;
|
||||
cgraph_nodes_queue = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Record call from CALLER to CALLEE */
|
||||
|
||||
|
@ -100,6 +100,7 @@ struct cgraph_edge
|
||||
extern struct cgraph_node *cgraph_nodes;
|
||||
extern int cgraph_n_nodes;
|
||||
extern bool cgraph_global_info_ready;
|
||||
extern struct cgraph_node *cgraph_nodes_queue;
|
||||
|
||||
/* In cgraph.c */
|
||||
void dump_cgraph PARAMS ((FILE *));
|
||||
@ -107,6 +108,7 @@ void cgraph_remove_call PARAMS ((tree, tree));
|
||||
void cgraph_remove_node PARAMS ((struct cgraph_node *));
|
||||
struct cgraph_edge *cgraph_record_call PARAMS ((tree, tree));
|
||||
struct cgraph_node *cgraph_node PARAMS ((tree decl));
|
||||
struct cgraph_node *cgraph_node_for_identifier PARAMS ((tree id));
|
||||
bool cgraph_calls_p PARAMS ((tree, tree));
|
||||
struct cgraph_local_info *cgraph_local_info PARAMS ((tree));
|
||||
struct cgraph_global_info *cgraph_global_info PARAMS ((tree));
|
||||
|
113
gcc/cgraphunit.c
113
gcc/cgraphunit.c
@ -55,7 +55,29 @@ cgraph_finalize_function (decl, body)
|
||||
|
||||
node->decl = decl;
|
||||
|
||||
node->local.can_inline_once = tree_inlinable_function_p (decl, 1);
|
||||
if (/* Externally visible functions must be output. The exception are
|
||||
COMDAT functions that must be output only when they are needed.
|
||||
Similarly are handled defered functions and
|
||||
external functions (GCC extension "extern inline") */
|
||||
(TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
|
||||
/* ??? Constructors and destructors not called otherwise can be inlined
|
||||
into single construction/destruction function per section to save some
|
||||
resources. For now just mark it as reachable. */
|
||||
|| DECL_STATIC_CONSTRUCTOR (decl)
|
||||
|| DECL_STATIC_DESTRUCTOR (decl)
|
||||
/* Function whose name is output to the assembler file must be produced.
|
||||
It is possible to assemble the name later after finalizing the function
|
||||
and the fact is noticed in assemble_name then. */
|
||||
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
|
||||
{
|
||||
cgraph_mark_needed_node (node, 1);
|
||||
}
|
||||
|
||||
if (!node->needed && !DECL_COMDAT (node->decl))
|
||||
node->local.can_inline_once = tree_inlinable_function_p (decl, 1);
|
||||
else
|
||||
node->local.can_inline_once = 0;
|
||||
if (flag_inline_trees)
|
||||
node->local.inline_many = tree_inlinable_function_p (decl, 0);
|
||||
else
|
||||
@ -64,33 +86,6 @@ cgraph_finalize_function (decl, body)
|
||||
(*debug_hooks->deferred_inline_function) (decl);
|
||||
}
|
||||
|
||||
static struct cgraph_node *queue = NULL;
|
||||
|
||||
/* Notify finalize_compilation_unit that given node is reachable
|
||||
or needed. */
|
||||
|
||||
void
|
||||
cgraph_mark_needed_node (node, needed)
|
||||
struct cgraph_node *node;
|
||||
int needed;
|
||||
{
|
||||
if (needed)
|
||||
{
|
||||
if (DECL_SAVED_TREE (node->decl))
|
||||
announce_function (node->decl);
|
||||
node->needed = 1;
|
||||
}
|
||||
if (!node->reachable)
|
||||
{
|
||||
node->reachable = 1;
|
||||
if (DECL_SAVED_TREE (node->decl))
|
||||
{
|
||||
node->aux = queue;
|
||||
queue = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk tree and record all calls. Called via walk_tree. */
|
||||
static tree
|
||||
record_call_1 (tp, walk_subtrees, data)
|
||||
@ -108,15 +103,8 @@ record_call_1 (tp, walk_subtrees, data)
|
||||
}
|
||||
else if (TREE_CODE (*tp) == CALL_EXPR)
|
||||
{
|
||||
/* We cannot use get_callee_fndecl here because it actually tries
|
||||
too hard to get the function declaration, looking for indirect
|
||||
references and stripping NOPS. As a result, get_callee_fndecl
|
||||
finds calls that shouldn't be in the call graph. */
|
||||
|
||||
tree decl = TREE_OPERAND (*tp, 0);
|
||||
if (TREE_CODE (decl) == ADDR_EXPR)
|
||||
decl = TREE_OPERAND (decl, 0);
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
tree decl = get_callee_fndecl (*tp);
|
||||
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
|
||||
{
|
||||
if (DECL_BUILT_IN (decl))
|
||||
return NULL;
|
||||
@ -156,40 +144,31 @@ cgraph_finalize_compilation_unit ()
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *edge;
|
||||
|
||||
/* Collect entry points to the unit. */
|
||||
|
||||
if (!quiet_flag)
|
||||
fprintf (stderr, "\n\nUnit entry points:");
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
tree decl = node->decl;
|
||||
|
||||
if (!DECL_SAVED_TREE (decl))
|
||||
continue;
|
||||
if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
|
||||
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
|
||||
{
|
||||
/* This function can be called from outside this compliation
|
||||
unit, so it most definitely is needed. */
|
||||
cgraph_mark_needed_node (node, 1);
|
||||
}
|
||||
fprintf (stderr, "\n\nInitial entry points:");
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
if (node->needed && DECL_SAVED_TREE (node->decl))
|
||||
announce_function (node->decl);
|
||||
}
|
||||
|
||||
/* Propagate reachability flag and lower representation of all reachable
|
||||
functions. In the future, lowering will introduce new functions and
|
||||
new entry points on the way (by template instantiation and virtual
|
||||
method table generation for instance). */
|
||||
while (queue)
|
||||
while (cgraph_nodes_queue)
|
||||
{
|
||||
tree decl = queue->decl;
|
||||
tree decl = cgraph_nodes_queue->decl;
|
||||
|
||||
node = cgraph_nodes_queue;
|
||||
cgraph_nodes_queue = cgraph_nodes_queue->aux;
|
||||
|
||||
node = queue;
|
||||
queue = queue->aux;
|
||||
if (node->lowered || !node->reachable || !DECL_SAVED_TREE (decl))
|
||||
abort ();
|
||||
|
||||
if (lang_hooks.callgraph.lower_function)
|
||||
(*lang_hooks.callgraph.lower_function) (decl);
|
||||
|
||||
/* At the moment frontend automatically emits all nested functions. */
|
||||
if (node->nested)
|
||||
{
|
||||
@ -200,9 +179,6 @@ cgraph_finalize_compilation_unit ()
|
||||
cgraph_mark_needed_node (node2, 0);
|
||||
}
|
||||
|
||||
if (lang_hooks.callgraph.lower_function)
|
||||
(*lang_hooks.callgraph.lower_function) (decl);
|
||||
|
||||
/* First kill forward declaration so reverse inling works properly. */
|
||||
cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
|
||||
|
||||
@ -213,6 +189,15 @@ cgraph_finalize_compilation_unit ()
|
||||
}
|
||||
node->lowered = true;
|
||||
}
|
||||
/* Collect entry points to the unit. */
|
||||
|
||||
if (!quiet_flag)
|
||||
{
|
||||
fprintf (stderr, "\n\nUnit entry points:");
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
if (node->needed && DECL_SAVED_TREE (node->decl))
|
||||
announce_function (node->decl);
|
||||
}
|
||||
|
||||
if (!quiet_flag)
|
||||
fprintf (stderr, "\n\nReclaiming functions:");
|
||||
@ -248,7 +233,8 @@ cgraph_mark_functions_to_output ()
|
||||
&& (node->needed
|
||||
|| (!node->local.inline_many && !node->global.inline_once
|
||||
&& node->reachable)
|
||||
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|
||||
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
|
||||
&& !TREE_ASM_WRITTEN (decl) && !node->origin
|
||||
&& !DECL_EXTERNAL (decl))
|
||||
node->output = 1;
|
||||
@ -331,7 +317,7 @@ cgraph_expand_functions ()
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
node->aux = NULL;
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
if (node->output && !node->aux)
|
||||
if (!node->aux)
|
||||
{
|
||||
node2 = node;
|
||||
if (!node->callers)
|
||||
@ -400,6 +386,7 @@ cgraph_mark_local_functions ()
|
||||
{
|
||||
node->local.local = (!node->needed
|
||||
&& DECL_SAVED_TREE (node->decl)
|
||||
&& !DECL_COMDAT (node->decl)
|
||||
&& !TREE_PUBLIC (node->decl));
|
||||
if (node->local.local)
|
||||
announce_function (node->decl);
|
||||
|
12
gcc/varasm.c
12
gcc/varasm.c
@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "tm_p.h"
|
||||
#include "debug.h"
|
||||
#include "target.h"
|
||||
#include "cgraph.h"
|
||||
|
||||
#ifdef XCOFF_DEBUGGING_INFO
|
||||
#include "xcoffout.h" /* Needed for external data
|
||||
@ -1742,7 +1743,16 @@ assemble_name (file, name)
|
||||
|
||||
id = maybe_get_identifier (real_name);
|
||||
if (id)
|
||||
TREE_SYMBOL_REFERENCED (id) = 1;
|
||||
{
|
||||
if (!TREE_SYMBOL_REFERENCED (id)
|
||||
&& !cgraph_global_info_ready)
|
||||
{
|
||||
struct cgraph_node *node = cgraph_node_for_identifier (id);
|
||||
if (node)
|
||||
cgraph_mark_needed_node (node, 1);
|
||||
}
|
||||
TREE_SYMBOL_REFERENCED (id) = 1;
|
||||
}
|
||||
|
||||
if (name[0] == '*')
|
||||
fputs (&name[1], file);
|
||||
|
Loading…
Reference in New Issue
Block a user