Makefile.in (cgraph.o): Depend on output.h, not depend on tree-inline.h
authorJan Hubicka <jh@suse.cz>
Tue, 24 Jun 2003 16:50:29 +0000 (18:50 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 24 Jun 2003 16:50:29 +0000 (16:50 +0000)
* 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

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/toplev.c
gcc/varasm.c

index 7be7d42dc5d6b8e531ba727eaef0c81170313213..49b6a2474ce492f2c8514f681bdcfa5b68b995c9 100644 (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.
index b5753a12831dbd651d9e4a3fa958aa9f8c175468..0f34373128d411bed8ea2fbfbd2c1ccffbf3a193 100644 (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"
index d29e190dbfd86c7c203422f99e2096a34768ecd5..de35a0dbbdc4d6bc544b4764b2585eb5953bb90b 100644 (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));
index 9fc5dd036b039f6e7f907bc2b1273c982a234111..47390b970c44b8b2da93033265a2ecac64f14c6b 100644 (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.  */
 
index defb5afebc85a7c05b66c48a76c48e738943eefe..c36bb6b45f67bc13f26f14bba4edad8b930e4289 100644 (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)
index fdfa02273418219f9572370c2093c1fb732a348a..73abd5edc8daeefa9b11bd0ef6e3abd717e0912f 100644 (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;
     }