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:
Jan Hubicka 2003-06-24 18:50:29 +02:00 committed by Jan Hubicka
parent 6df5158a36
commit e69529cd53
6 changed files with 227 additions and 11 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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