OSDN Git Service

2004-07-16 Frank Ch. Eigler <fche@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / cgraphunit.c
index c079e40..79d5553 100644 (file)
@@ -168,6 +168,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "rtl.h"
 #include "tree-inline.h"
 #include "langhooks.h"
 #include "hashtab.h"
@@ -467,7 +468,9 @@ cgraph_create_edges (struct cgraph_node *node, tree body)
 
 static bool error_found;
 
-/* Callbrack of verify_cgraph_node.  Check that all call_exprs have cgraph nodes.  */
+/* Callbrack of verify_cgraph_node.  Check that all call_exprs have cgraph
+   nodes.  */
+
 static tree
 verify_cgraph_node_1 (tree *tp, int *walk_subtrees, void *data)
 {
@@ -501,12 +504,12 @@ verify_cgraph_node_1 (tree *tp, int *walk_subtrees, void *data)
          error_found = true;
        }
     }
+
   /* Save some cycles by not walking types and declaration as we
      won't find anything useful there anyway.  */
   if (DECL_P (*tp) || TYPE_P (*tp))
-    {
-      *walk_subtrees = 0;
-    }
+    *walk_subtrees = 0;
+
   return NULL_TREE;
 }
 
@@ -804,7 +807,6 @@ cgraph_expand_function (struct cgraph_node *node)
     {
       DECL_SAVED_TREE (node->decl) = NULL;
       DECL_STRUCT_FUNCTION (node->decl) = NULL;
-      DECL_ARGUMENTS (node->decl) = NULL;
       DECL_INITIAL (node->decl) = error_mark_node;
     }
 }
@@ -965,7 +967,6 @@ cgraph_remove_unreachable_nodes (void)
                    {
                      DECL_SAVED_TREE (node->decl) = NULL;
                      DECL_STRUCT_FUNCTION (node->decl) = NULL;
-                     DECL_ARGUMENTS (node->decl) = NULL;
                      DECL_INITIAL (node->decl) = error_mark_node;
                    }
                  while (node->callees)
@@ -1020,7 +1021,7 @@ cgraph_estimate_growth (struct cgraph_node *node)
 
 /* E is expected to be an edge being inlined.  Clone destination node of
    the edge and redirect it to the new clone.
-   DUPLICATE is used for bookeeping on whether we are actually creating new
+   DUPLICATE is used for bookkeeping on whether we are actually creating new
    clones or re-using node originally representing out-of-line function call.
    */
 void
@@ -1071,22 +1072,14 @@ cgraph_mark_inline_edge (struct cgraph_edge *e)
   e->inline_failed = NULL;
 
   if (!e->callee->global.inlined && flag_unit_at_a_time)
-    {
-      void **slot;
-      if (!cgraph_inline_hash)
-        cgraph_inline_hash = htab_create_ggc (42, htab_hash_pointer,
-                                             htab_eq_pointer, NULL);
-      slot = htab_find_slot (cgraph_inline_hash,
-                            DECL_ASSEMBLER_NAME (e->callee->decl), INSERT);
-      *slot = DECL_ASSEMBLER_NAME (e->callee->decl);
-    }
+    DECL_POSSIBLY_INLINED (e->callee->decl) = true;
   e->callee->global.inlined = true;
 
   cgraph_clone_inlined_nodes (e, true);
 
   what = e->callee;
 
-  /* Now update size of caller and all functions caller is inlined into. */
+  /* Now update size of caller and all functions caller is inlined into.  */
   for (;e && !e->inline_failed; e = e->caller->callers)
     {
       old_insns = e->caller->global.insns;
@@ -1199,7 +1192,7 @@ cgraph_recursive_inlining_p (struct cgraph_node *to,
     recursive = what->decl == to->global.inlined_to->decl;
   else
     recursive = what->decl == to->decl;
-  /* Marking recursive function inlinine has sane semantic and thus we should
+  /* Marking recursive function inline has sane semantic and thus we should
      not warn on it.  */
   if (recursive && reason)
     *reason = (what->local.disregard_inline_limits
@@ -1490,7 +1483,7 @@ cgraph_decide_inlining (void)
       if (cgraph_dump_file)
        fprintf (cgraph_dump_file,
                 "\nConsidering %s %i insns (always inline)\n",
-                cgraph_node_name (e->callee), e->callee->global.insns);
+                cgraph_node_name (node), node->global.insns);
       old_insns = overall_insns;
       for (e = node->callers; e; e = next)
        {
@@ -1504,8 +1497,8 @@ cgraph_decide_inlining (void)
          if (cgraph_dump_file)
            fprintf (cgraph_dump_file, 
                     " Inlined into %s which now has %i insns.\n",
-                    cgraph_node_name (node->callees->caller),
-                    node->callees->caller->global.insns);
+                    cgraph_node_name (e->caller),
+                    e->caller->global.insns);
        }
       if (cgraph_dump_file)
        fprintf (cgraph_dump_file, 
@@ -1793,3 +1786,66 @@ cgraph_optimize (void)
     }
 #endif
 }
+
+/* Generate and emit a static constructor or destructor.  WHICH must be
+   one of 'I' or 'D'.  BODY should be a STATEMENT_LIST containing 
+   GENERIC statements.  */
+
+void
+cgraph_build_static_cdtor (char which, tree body, int priority)
+{
+  static int counter = 0;
+  char which_buf[16];
+  tree decl, name;
+
+  sprintf (which_buf, "%c_%d", which, counter++);
+  name = get_file_function_name_long (which_buf);
+
+  decl = build_decl (FUNCTION_DECL, name,
+                    build_function_type (void_type_node, void_list_node));
+  current_function_decl = decl;
+
+  DECL_RESULT (decl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+  allocate_struct_function (decl);
+
+  TREE_STATIC (decl) = 1;
+  TREE_USED (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
+  DECL_SAVED_TREE (decl) = body;
+  TREE_PUBLIC (decl) = ! targetm.have_ctors_dtors;
+  DECL_UNINLINABLE (decl) = 1;
+
+  DECL_INITIAL (decl) = make_node (BLOCK);
+  TREE_USED (DECL_INITIAL (decl)) = 1;
+
+  DECL_SOURCE_LOCATION (decl) = input_location;
+  cfun->function_end_locus = input_location;
+
+  if (which == 'I')
+    DECL_STATIC_CONSTRUCTOR (decl) = 1;
+  else if (which == 'D')
+    DECL_STATIC_DESTRUCTOR (decl) = 1;
+  else
+    abort ();
+
+  gimplify_function_tree (decl);
+
+  /* ??? We will get called LATE in the compilation process.  */
+  if (cgraph_global_info_ready)
+    tree_rest_of_compilation (decl, false);
+  else
+    cgraph_finalize_function (decl, 0);
+  
+  if (targetm.have_ctors_dtors)
+    {
+      void (*fn) (rtx, int);
+
+      if (which == 'I')
+       fn = targetm.asm_out.constructor;
+      else
+       fn = targetm.asm_out.destructor;
+      fn (XEXP (DECL_RTL (decl), 0), priority);
+    }
+}