Makefile.in (cgraph.o): Depend on output.h, not depend on tree-inline.h
* Makefile.in (cgraph.o): Depend on output.h, not depend on tree-inline.h * cgraph.c: Do not include tree-inline.h; include output.h (known_fns): Rename to ... (known_decls): ... this one; update all uses. (cgraph_varpool_hash): New static variable. (cgraph_varpool_n_nodes, cgraph_varpool_nodes_queue): New global variables. (cgraph_varpool_hash_node, eq_cgraph_varpool_node, cgraph_varpool_node, cgraph_varpool_node_for_identifier, cgraph_varpool_mark_needed_node, cgraph_varpool_finalize_decl, cgraph_varpool_assemble_pending_decls): New functions. * cgraph.h (cgraph_varpool_node): New structure. (cgraph_varpool_n_nodes, cgraph_varpool_nodes_queue): Declare. (cgraph_varpool_node, cgraph_varpool_node_for_identifier, cgraph_varpool_finalize_decl, cgraph_varpool_mark_needed_node, cgraph_varpool_asemble_pending_decls): Declare. * cgraphunit.c (record_call_1): Notice variable references. (cgraph_finalize_compilation_unit): Assemble pending variables. * toplev.c (wrapup_global_declarations): Use varpool. (compile_file): Assemble pending declarations. (rest_of_decl_compilation): Use varpool in unit-at-a-time mode. * varasm.c (assemble_name): Notice varpool references. From-SVN: r68426
This commit is contained in:
parent
6df5158a36
commit
e69529cd53
6 changed files with 227 additions and 11 deletions
|
@ -1,3 +1,29 @@
|
|||
Tue Jun 24 18:49:33 CEST 2003 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* Makefile.in (cgraph.o): Depend on output.h, not depend on
|
||||
tree-inline.h
|
||||
* cgraph.c: Do not include tree-inline.h; include output.h
|
||||
(known_fns): Rename to ...
|
||||
(known_decls): ... this one; update all uses.
|
||||
(cgraph_varpool_hash): New static variable.
|
||||
(cgraph_varpool_n_nodes, cgraph_varpool_nodes_queue): New global
|
||||
variables.
|
||||
(cgraph_varpool_hash_node, eq_cgraph_varpool_node, cgraph_varpool_node,
|
||||
cgraph_varpool_node_for_identifier, cgraph_varpool_mark_needed_node,
|
||||
cgraph_varpool_finalize_decl, cgraph_varpool_assemble_pending_decls):
|
||||
New functions.
|
||||
* cgraph.h (cgraph_varpool_node): New structure.
|
||||
(cgraph_varpool_n_nodes, cgraph_varpool_nodes_queue): Declare.
|
||||
(cgraph_varpool_node, cgraph_varpool_node_for_identifier,
|
||||
cgraph_varpool_finalize_decl, cgraph_varpool_mark_needed_node,
|
||||
cgraph_varpool_asemble_pending_decls): Declare.
|
||||
* cgraphunit.c (record_call_1): Notice variable references.
|
||||
(cgraph_finalize_compilation_unit): Assemble pending variables.
|
||||
* toplev.c (wrapup_global_declarations): Use varpool.
|
||||
(compile_file): Assemble pending declarations.
|
||||
(rest_of_decl_compilation): Use varpool in unit-at-a-time mode.
|
||||
* varasm.c (assemble_name): Notice varpool references.
|
||||
|
||||
Tue Jun 24 13:52:11 CEST 2003 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* langhooks-def.h (LANG_HOOKS_PREPARE_ASSEMBLE_VARIABLE): New macro.
|
||||
|
|
153
gcc/cgraph.c
153
gcc/cgraph.c
|
@ -24,7 +24,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "tree-inline.h"
|
||||
#include "langhooks.h"
|
||||
#include "hashtab.h"
|
||||
#include "toplev.h"
|
||||
|
@ -34,13 +33,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
#include "target.h"
|
||||
#include "cgraph.h"
|
||||
#include "varray.h"
|
||||
#include "output.h"
|
||||
|
||||
/* The known declarations must not get garbage collected. Callgraph
|
||||
datastructures should not get saved via PCH code since this would
|
||||
make it difficult to extend into intra-module optimizer later. So
|
||||
we store only the references into the array to prevent gabrage
|
||||
collector from deleting live data. */
|
||||
static GTY(()) varray_type known_fns;
|
||||
static GTY(()) varray_type known_decls;
|
||||
|
||||
/* Hash table used to convert declarations into nodes. */
|
||||
static htab_t cgraph_hash = 0;
|
||||
|
@ -57,6 +57,15 @@ int cgraph_n_nodes;
|
|||
/* Set when whole unit has been analyzed so we can access global info. */
|
||||
bool cgraph_global_info_ready = false;
|
||||
|
||||
/* Hash table used to convert declarations into nodes. */
|
||||
static htab_t cgraph_varpool_hash = 0;
|
||||
|
||||
/* Queue of cgraph nodes scheduled to be lowered and output. */
|
||||
struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
|
||||
|
||||
/* Number of nodes in existence. */
|
||||
int cgraph_varpool_n_nodes;
|
||||
|
||||
static struct cgraph_edge *create_edge PARAMS ((struct cgraph_node *,
|
||||
struct cgraph_node *));
|
||||
static void cgraph_remove_edge PARAMS ((struct cgraph_node *, struct cgraph_node *));
|
||||
|
@ -99,7 +108,7 @@ cgraph_node (decl)
|
|||
if (!cgraph_hash)
|
||||
{
|
||||
cgraph_hash = htab_create (10, hash_node, eq_node, NULL);
|
||||
VARRAY_TREE_INIT (known_fns, 32, "known_fns");
|
||||
VARRAY_TREE_INIT (known_decls, 32, "known_decls");
|
||||
}
|
||||
|
||||
slot =
|
||||
|
@ -125,7 +134,7 @@ cgraph_node (decl)
|
|||
node->next_nested = node->origin->nested;
|
||||
node->origin->nested = node;
|
||||
}
|
||||
VARRAY_PUSH_TREE (known_fns, decl);
|
||||
VARRAY_PUSH_TREE (known_decls, decl);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -140,10 +149,7 @@ cgraph_node_for_identifier (id)
|
|||
abort ();
|
||||
|
||||
if (!cgraph_hash)
|
||||
{
|
||||
cgraph_hash = htab_create (10, hash_node, eq_node, NULL);
|
||||
VARRAY_TREE_INIT (known_fns, 32, "known_fns");
|
||||
}
|
||||
return NULL;
|
||||
|
||||
slot =
|
||||
(struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, id,
|
||||
|
@ -356,4 +362,135 @@ dump_cgraph (f)
|
|||
}
|
||||
}
|
||||
|
||||
/* Returns a hash code for P. */
|
||||
|
||||
static hashval_t
|
||||
cgraph_varpool_hash_node (const PTR p)
|
||||
{
|
||||
return (hashval_t)
|
||||
htab_hash_pointer (DECL_ASSEMBLER_NAME
|
||||
(((struct cgraph_varpool_node *) p)->decl));
|
||||
}
|
||||
|
||||
/* Returns non-zero if P1 and P2 are equal. */
|
||||
|
||||
static int
|
||||
eq_cgraph_varpool_node (const PTR p1, const PTR p2)
|
||||
{
|
||||
return ((DECL_ASSEMBLER_NAME (((struct cgraph_varpool_node *) p1)->decl)) ==
|
||||
(tree) p2);
|
||||
}
|
||||
|
||||
/* 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 *node;
|
||||
struct cgraph_varpool_node **slot;
|
||||
|
||||
if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
|
||||
abort ();
|
||||
|
||||
if (!cgraph_varpool_hash)
|
||||
{
|
||||
cgraph_varpool_hash = htab_create (10, cgraph_varpool_hash_node, eq_cgraph_varpool_node, NULL);
|
||||
VARRAY_TREE_INIT (known_decls, 32, "known_decls");
|
||||
}
|
||||
|
||||
slot =
|
||||
(struct cgraph_varpool_node **) htab_find_slot_with_hash (cgraph_varpool_hash,
|
||||
DECL_ASSEMBLER_NAME (decl),
|
||||
htab_hash_pointer
|
||||
(DECL_ASSEMBLER_NAME
|
||||
(decl)), 1);
|
||||
if (*slot)
|
||||
return *slot;
|
||||
node = xcalloc (sizeof (*node), 1);
|
||||
node->decl = decl;
|
||||
cgraph_varpool_n_nodes++;
|
||||
*slot = node;
|
||||
VARRAY_PUSH_TREE (known_decls, decl);
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Try to find existing function for identifier ID. */
|
||||
struct cgraph_varpool_node *
|
||||
cgraph_varpool_node_for_identifier (tree id)
|
||||
{
|
||||
struct cgraph_varpool_node **slot;
|
||||
|
||||
if (TREE_CODE (id) != IDENTIFIER_NODE)
|
||||
abort ();
|
||||
|
||||
if (!cgraph_varpool_hash)
|
||||
return NULL;
|
||||
|
||||
slot =
|
||||
(struct cgraph_varpool_node **) htab_find_slot_with_hash (cgraph_varpool_hash, id,
|
||||
htab_hash_pointer (id), 0);
|
||||
if (!slot)
|
||||
return NULL;
|
||||
return *slot;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
node->aux = cgraph_varpool_nodes_queue;
|
||||
cgraph_varpool_nodes_queue = node;
|
||||
}
|
||||
node->needed = 1;
|
||||
}
|
||||
|
||||
void
|
||||
cgraph_varpool_finalize_decl (tree decl)
|
||||
{
|
||||
struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
|
||||
|
||||
if (node->needed && !node->finalized)
|
||||
{
|
||||
node->aux = cgraph_varpool_nodes_queue;
|
||||
cgraph_varpool_nodes_queue = node;
|
||||
}
|
||||
node->finalized = true;
|
||||
|
||||
if (/* Externally visible variables must be output. The exception are
|
||||
COMDAT functions that must be output only when they are needed. */
|
||||
(TREE_PUBLIC (decl) && !DECL_COMDAT (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_varpool_mark_needed_node (node);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
cgraph_varpool_assemble_pending_decls ()
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
while (cgraph_varpool_nodes_queue)
|
||||
{
|
||||
tree decl = cgraph_varpool_nodes_queue->decl;
|
||||
struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
|
||||
|
||||
cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->aux;
|
||||
if (!TREE_ASM_WRITTEN (decl))
|
||||
{
|
||||
assemble_variable (decl, 0, 1, 0);
|
||||
changed = true;
|
||||
}
|
||||
node->aux = NULL;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
#include "gt-cgraph.h"
|
||||
|
|
27
gcc/cgraph.h
27
gcc/cgraph.h
|
@ -97,11 +97,32 @@ struct cgraph_edge
|
|||
struct cgraph_edge *next_callee;
|
||||
};
|
||||
|
||||
/* The cgraph_varpool data strutcture.
|
||||
Each static variable decl has assigned cgraph_varpool_node. */
|
||||
|
||||
struct cgraph_varpool_node
|
||||
{
|
||||
tree decl;
|
||||
void *aux;
|
||||
|
||||
/* Set when function must be output - it is externally visible
|
||||
or it's address is taken. */
|
||||
bool needed;
|
||||
/* Set once it has been finalized so we consider it to be output. */
|
||||
bool finalized;
|
||||
/* Set when function is scheduled to be assembled. */
|
||||
bool output;
|
||||
};
|
||||
|
||||
extern struct cgraph_node *cgraph_nodes;
|
||||
extern int cgraph_n_nodes;
|
||||
extern bool cgraph_global_info_ready;
|
||||
extern struct cgraph_node *cgraph_nodes_queue;
|
||||
|
||||
extern int cgraph_varpool_n_nodes;
|
||||
extern struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
|
||||
|
||||
|
||||
/* In cgraph.c */
|
||||
void dump_cgraph PARAMS ((FILE *));
|
||||
void cgraph_remove_call PARAMS ((tree, tree));
|
||||
|
@ -114,6 +135,12 @@ struct cgraph_local_info *cgraph_local_info PARAMS ((tree));
|
|||
struct cgraph_global_info *cgraph_global_info PARAMS ((tree));
|
||||
struct cgraph_rtl_info *cgraph_rtl_info PARAMS ((tree));
|
||||
|
||||
struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
|
||||
struct cgraph_varpool_node *cgraph_varpool_node_for_identifier (tree id);
|
||||
void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
|
||||
void cgraph_varpool_finalize_decl (tree);
|
||||
bool cgraph_varpool_assemble_pending_decls (void);
|
||||
|
||||
/* In cgraphunit.c */
|
||||
void cgraph_finalize_function PARAMS ((tree, tree));
|
||||
void cgraph_finalize_compilation_unit PARAMS ((void));
|
||||
|
|
|
@ -93,9 +93,11 @@ record_call_1 (tp, walk_subtrees, data)
|
|||
int *walk_subtrees;
|
||||
void *data;
|
||||
{
|
||||
if (TREE_CODE (*tp) == VAR_DECL && TREE_STATIC (*tp))
|
||||
cgraph_varpool_mark_needed_node (cgraph_varpool_node (*tp));
|
||||
/* Record dereferences to the functions. This makes the functions
|
||||
reachable unconditionally. */
|
||||
if (TREE_CODE (*tp) == ADDR_EXPR)
|
||||
else if (TREE_CODE (*tp) == ADDR_EXPR)
|
||||
{
|
||||
tree decl = TREE_OPERAND (*tp, 0);
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
|
@ -144,6 +146,8 @@ cgraph_finalize_compilation_unit ()
|
|||
struct cgraph_node *node;
|
||||
struct cgraph_edge *edge;
|
||||
|
||||
cgraph_varpool_assemble_pending_decls ();
|
||||
|
||||
if (!quiet_flag)
|
||||
{
|
||||
fprintf (stderr, "\n\nInitial entry points:");
|
||||
|
@ -188,6 +192,7 @@ cgraph_finalize_compilation_unit ()
|
|||
cgraph_mark_needed_node (edge->callee, 0);
|
||||
}
|
||||
node->lowered = true;
|
||||
cgraph_varpool_assemble_pending_decls ();
|
||||
}
|
||||
/* Collect entry points to the unit. */
|
||||
|
||||
|
|
19
gcc/toplev.c
19
gcc/toplev.c
|
@ -1897,7 +1897,14 @@ wrapup_global_declarations (tree *vec, int len)
|
|||
{
|
||||
bool needed = 1;
|
||||
|
||||
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|
||||
if (flag_unit_at_a_time
|
||||
&& cgraph_varpool_node (decl)->finalized)
|
||||
needed = 0;
|
||||
else if (flag_unit_at_a_time
|
||||
&& (TREE_USED (decl)
|
||||
|| TREE_USED (DECL_ASSEMBLER_NAME (decl))))
|
||||
/* needed */;
|
||||
else if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|
||||
/* needed */;
|
||||
else if (DECL_COMDAT (decl))
|
||||
needed = 0;
|
||||
|
@ -2069,6 +2076,8 @@ compile_file (void)
|
|||
|
||||
(*lang_hooks.decls.final_write_globals)();
|
||||
|
||||
cgraph_varpool_assemble_pending_decls ();
|
||||
|
||||
/* This must occur after the loop to output deferred functions.
|
||||
Else the coverage initializer would not be emitted if all the
|
||||
functions in this compilation unit were deferred. */
|
||||
|
@ -2169,7 +2178,13 @@ rest_of_decl_compilation (tree decl,
|
|||
/* Don't output anything when a tentative file-scope definition
|
||||
is seen. But at end of compilation, do output code for them. */
|
||||
if (at_end || !DECL_DEFER_OUTPUT (decl))
|
||||
assemble_variable (decl, top_level, at_end, 0);
|
||||
{
|
||||
if (flag_unit_at_a_time && TREE_CODE (decl) != FUNCTION_DECL
|
||||
&& top_level)
|
||||
cgraph_varpool_finalize_decl (decl);
|
||||
else
|
||||
assemble_variable (decl, top_level, at_end, 0);
|
||||
}
|
||||
|
||||
#ifdef ASM_FINISH_DECLARE_OBJECT
|
||||
if (decl == last_assemble_variable_decl)
|
||||
|
|
|
@ -1751,8 +1751,14 @@ assemble_name (file, name)
|
|||
&& !cgraph_global_info_ready)
|
||||
{
|
||||
struct cgraph_node *node = cgraph_node_for_identifier (id);
|
||||
struct cgraph_varpool_node *vnode;
|
||||
|
||||
if (node)
|
||||
cgraph_mark_needed_node (node, 1);
|
||||
|
||||
vnode = cgraph_varpool_node_for_identifier (id);
|
||||
if (vnode)
|
||||
cgraph_varpool_mark_needed_node (vnode);
|
||||
}
|
||||
TREE_SYMBOL_REFERENCED (id) = 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue