OSDN Git Service

gcc/fortran:
[pf3gnuchains/gcc-fork.git] / gcc / cgraphunit.c
index 13079a2..ac8472f 100644 (file)
@@ -168,6 +168,75 @@ static void cgraph_output_pending_asms (void);
 
 static FILE *cgraph_dump_file;
 
+static GTY (()) tree static_ctors;
+static GTY (()) tree static_dtors;
+
+/* When target does not have ctors and dtors, we call all constructor
+   and destructor by special initialization/destruction function
+   recognized by collect2.  
+   
+   When we are going to build this function, collect all constructors and
+   destructors and turn them into normal functions.  */
+
+static void
+record_cdtor_fn (tree fndecl)
+{
+  if (targetm.have_ctors_dtors)
+    return;
+
+  if (DECL_STATIC_CONSTRUCTOR (fndecl))
+    {
+      static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+      DECL_STATIC_CONSTRUCTOR (fndecl) = 0;
+      cgraph_mark_reachable_node (cgraph_node (fndecl));
+    }
+  if (DECL_STATIC_DESTRUCTOR (fndecl))
+    {
+      static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
+      DECL_STATIC_DESTRUCTOR (fndecl) = 0;
+      cgraph_mark_reachable_node (cgraph_node (fndecl));
+    }
+}
+
+/* Synthesize a function which calls all the global ctors or global
+   dtors in this file.  This is only used for targets which do not
+   support .ctors/.dtors sections.  */
+static void
+build_cdtor (int method_type, tree cdtors)
+{
+  tree body = 0;
+
+  if (!cdtors)
+    return;
+
+  for (; cdtors; cdtors = TREE_CHAIN (cdtors))
+    append_to_statement_list (build_function_call_expr (TREE_VALUE (cdtors), 0),
+                             &body);
+
+  cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
+}
+
+/* Generate functions to call static constructors and destructors
+   for targets that do not support .ctors/.dtors sections.  These
+   functions have magic names which are detected by collect2.  */
+
+static void
+cgraph_build_cdtor_fns (void)
+{
+  if (!targetm.have_ctors_dtors)
+    {
+      build_cdtor ('I', static_ctors); 
+      static_ctors = NULL_TREE;
+      build_cdtor ('D', static_dtors); 
+      static_dtors = NULL_TREE;
+    }
+  else
+    {
+      gcc_assert (!static_ctors);
+      gcc_assert (!static_dtors);
+    }
+}
+
 /* Determine if function DECL is needed.  That is, visible to something
    either outside this translation unit, something magic in the system
    configury, or (if not doing unit-at-a-time) to something we havn't
@@ -458,6 +527,7 @@ cgraph_finalize_function (tree decl, bool nested)
   node->decl = decl;
   node->local.finalized = true;
   node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
+  record_cdtor_fn (node->decl);
   if (node->nested)
     lower_nested_functions (decl);
   gcc_assert (!node->nested);
@@ -690,20 +760,8 @@ cgraph_analyze_function (struct cgraph_node *node)
   current_function_decl = decl;
   push_cfun (DECL_STRUCT_FUNCTION (decl));
   cgraph_lower_function (node);
+  node->analyzed = true;
 
-  node->local.estimated_self_stack_size = estimated_stack_frame_size ();
-  node->global.estimated_stack_size = node->local.estimated_self_stack_size;
-  node->global.stack_frame_offset = 0;
-  node->local.inlinable = tree_inlinable_function_p (decl);
-  if (!flag_unit_at_a_time)
-    node->local.self_insns = estimate_num_insns (decl, &eni_inlining_weights);
-  if (node->local.inlinable)
-    node->local.disregard_inline_limits
-      = lang_hooks.tree_inlining.disregard_inline_limits (decl);
-  if (flag_really_no_inline && !node->local.disregard_inline_limits)
-    node->local.inlinable = 0;
-  /* Inlining characteristics are maintained by the cgraph_mark_inline.  */
-  node->global.insns = node->local.self_insns;
   if (!flag_unit_at_a_time)
     {
       bitmap_obstack_initialize (NULL);
@@ -714,7 +772,6 @@ cgraph_analyze_function (struct cgraph_node *node)
       bitmap_obstack_release (NULL);
     }
 
-  node->analyzed = true;
   pop_cfun ();
   current_function_decl = NULL;
 }
@@ -1222,6 +1279,10 @@ cgraph_optimize (void)
 #ifdef ENABLE_CHECKING
   verify_cgraph ();
 #endif
+
+  /* Call functions declared with the "constructor" or "destructor"
+     attribute.  */
+  cgraph_build_cdtor_fns ();
   if (!flag_unit_at_a_time)
     {
       cgraph_assemble_pending_functions ();
@@ -1572,3 +1633,5 @@ save_inline_function_body (struct cgraph_node *node)
 #endif
   return first_clone;
 }
+
+#include "gt-cgraphunit.h"