diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-24 16:50:29 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-24 16:50:29 +0000 |
commit | 229dcfae7711b67773c56d5cf0d29b49d8ccafe3 (patch) | |
tree | 6d104fc83b2d07c080d44ba705184072c8821bf6 | |
parent | e4f430b5f97fabfc71b51faa4d28914bf1292edb (diff) | |
download | gcc-229dcfae7711b67773c56d5cf0d29b49d8ccafe3.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68426 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/cgraph.c | 153 | ||||
-rw-r--r-- | gcc/cgraph.h | 27 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 7 | ||||
-rw-r--r-- | gcc/toplev.c | 19 | ||||
-rw-r--r-- | gcc/varasm.c | 6 |
6 files changed, 227 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7be7d42dc5d..49b6a2474ce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index b5753a12831..0f34373128d 100644 --- a/gcc/cgraph.c +++ b/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" diff --git a/gcc/cgraph.h b/gcc/cgraph.h index d29e190dbfd..de35a0dbbdc 100644 --- a/gcc/cgraph.h +++ b/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)); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 9fc5dd036b0..47390b970c4 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -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. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index defb5afebc8..c36bb6b45f6 100644 --- a/gcc/toplev.c +++ b/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) diff --git a/gcc/varasm.c b/gcc/varasm.c index fdfa0227341..73abd5edc8d 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -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; } |