aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2003-06-24 18:50:29 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2003-06-24 16:50:29 +0000
commite69529cd536c79f1849f271e230e0b61fede7b84 (patch)
tree6d104fc83b2d07c080d44ba705184072c8821bf6
parent6df5158a36cb2b8c5f6642f0208648c1ea2d5786 (diff)
downloadgcc-e69529cd536c79f1849f271e230e0b61fede7b84.zip
gcc-e69529cd536c79f1849f271e230e0b61fede7b84.tar.gz
gcc-e69529cd536c79f1849f271e230e0b61fede7b84.tar.bz2
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
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/cgraph.c153
-rw-r--r--gcc/cgraph.h27
-rw-r--r--gcc/cgraphunit.c7
-rw-r--r--gcc/toplev.c19
-rw-r--r--gcc/varasm.c6
6 files changed, 227 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7be7d42..49b6a24 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 b5753a1..0f34373 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 d29e190d..de35a0d 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 9fc5dd0..47390b9 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 defb5af..c36bb6b 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 fdfa022..73abd5e 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;
}