OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cgraphbuild.c
index c63b5af..8bf8830 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph construction.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "ipa-utils.h"
 #include "except.h"
+#include "ipa-inline.h"
 
 /* Context of record_reference.  */
 struct record_reference_ctx
@@ -53,6 +54,12 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
   tree decl;
   struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
 
+  t = canonicalize_constructor_val (t);
+  if (!t)
+    t = *tp;
+  else if (t != *tp)
+    *tp = t;
+
   switch (TREE_CODE (t))
     {
     case VAR_DECL:
@@ -67,10 +74,10 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
       decl = get_base_var (*tp);
       if (TREE_CODE (decl) == FUNCTION_DECL)
        {
+         struct cgraph_node *node = cgraph_get_create_node (decl);
          if (!ctx->only_vars)
-         cgraph_mark_address_taken_node (cgraph_node (decl));
-         ipa_record_reference (NULL, ctx->varpool_node,
-                               cgraph_node (decl), NULL,
+           cgraph_mark_address_taken_node (node);
+         ipa_record_reference (NULL, ctx->varpool_node, node, NULL,
                                IPA_REF_ADDR, NULL);
        }
 
@@ -80,8 +87,6 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
          if (lang_hooks.callgraph.analyze_expr)
            lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
          varpool_mark_needed_node (vnode);
-         if (vnode->alias && vnode->extra_name)
-           vnode = vnode->extra_name;
          ipa_record_reference (NULL, ctx->varpool_node,
                                NULL, vnode,
                                IPA_REF_ADDR, NULL);
@@ -141,6 +146,15 @@ record_eh_tables (struct cgraph_node *node, struct function *fun)
 {
   eh_region i;
 
+  if (DECL_FUNCTION_PERSONALITY (node->decl))
+    {
+      struct cgraph_node *per_node;
+
+      per_node = cgraph_get_create_node (DECL_FUNCTION_PERSONALITY (node->decl));
+      ipa_record_reference (node, NULL, per_node, NULL, IPA_REF_ADDR, NULL);
+      cgraph_mark_address_taken_node (per_node);
+    }
+
   i = fun->eh->region_tree;
   if (!i)
     return;
@@ -196,16 +210,7 @@ reset_inline_failed (struct cgraph_node *node)
   for (e = node->callers; e; e = e->next_caller)
     {
       e->callee->global.inlined_to = NULL;
-      if (!node->analyzed)
-       e->inline_failed = CIF_BODY_NOT_AVAILABLE;
-      else if (node->local.redefined_extern_inline)
-       e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
-      else if (!node->local.inlinable)
-       e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
-      else if (e->call_stmt_cannot_inline_p)
-       e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
-      else
-       e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+      initialize_inline_failed (e);
     }
 }
 
@@ -234,35 +239,29 @@ compute_call_stmt_bb_frequency (tree decl, basic_block bb)
 /* Mark address taken in STMT.  */
 
 static bool
-mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
-             void *data ATTRIBUTE_UNUSED)
+mark_address (gimple stmt, tree addr, void *data)
 {
+  addr = get_base_address (addr);
   if (TREE_CODE (addr) == FUNCTION_DECL)
     {
-      struct cgraph_node *node = cgraph_node (addr);
+      struct cgraph_node *node = cgraph_get_create_node (addr);
       cgraph_mark_address_taken_node (node);
       ipa_record_reference ((struct cgraph_node *)data, NULL,
                            node, NULL,
                            IPA_REF_ADDR, stmt);
     }
-  else
+  else if (addr && TREE_CODE (addr) == VAR_DECL
+          && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
     {
-      addr = get_base_address (addr);
-      if (addr && TREE_CODE (addr) == VAR_DECL
-         && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
-       {
-         struct varpool_node *vnode = varpool_node (addr);
-         int walk_subtrees;
+      struct varpool_node *vnode = varpool_node (addr);
+      int walk_subtrees;
 
-         if (lang_hooks.callgraph.analyze_expr)
-           lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
-         varpool_mark_needed_node (vnode);
-         if (vnode->alias && vnode->extra_name)
-           vnode = vnode->extra_name;
-         ipa_record_reference ((struct cgraph_node *)data, NULL,
-                               NULL, vnode,
-                               IPA_REF_ADDR, stmt);
-       }
+      if (lang_hooks.callgraph.analyze_expr)
+       lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
+      varpool_mark_needed_node (vnode);
+      ipa_record_reference ((struct cgraph_node *)data, NULL,
+                           NULL, vnode,
+                           IPA_REF_ADDR, stmt);
     }
 
   return false;
@@ -271,12 +270,21 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
 /* Mark load of T.  */
 
 static bool
-mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
-          void *data ATTRIBUTE_UNUSED)
+mark_load (gimple stmt, tree t, void *data)
 {
   t = get_base_address (t);
-  if (TREE_CODE (t) == VAR_DECL
-      && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
+  if (t && TREE_CODE (t) == FUNCTION_DECL)
+    {
+      /* ??? This can happen on platforms with descriptors when these are
+        directly manipulated in the code.  Pretend that it's an address.  */
+      struct cgraph_node *node = cgraph_get_create_node (t);
+      cgraph_mark_address_taken_node (node);
+      ipa_record_reference ((struct cgraph_node *)data, NULL,
+                           node, NULL,
+                           IPA_REF_ADDR, stmt);
+    }
+  else if (t && TREE_CODE (t) == VAR_DECL
+          && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
     {
       struct varpool_node *vnode = varpool_node (t);
       int walk_subtrees;
@@ -284,8 +292,6 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
       if (lang_hooks.callgraph.analyze_expr)
        lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
       varpool_mark_needed_node (vnode);
-      if (vnode->alias && vnode->extra_name)
-       vnode = vnode->extra_name;
       ipa_record_reference ((struct cgraph_node *)data, NULL,
                            NULL, vnode,
                            IPA_REF_LOAD, stmt);
@@ -296,11 +302,10 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
 /* Mark store of T.  */
 
 static bool
-mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
-           void *data ATTRIBUTE_UNUSED)
+mark_store (gimple stmt, tree t, void *data)
 {
   t = get_base_address (t);
-  if (TREE_CODE (t) == VAR_DECL
+  if (t && TREE_CODE (t) == VAR_DECL
       && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
     {
       struct varpool_node *vnode = varpool_node (t);
@@ -309,11 +314,9 @@ mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
       if (lang_hooks.callgraph.analyze_expr)
        lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
       varpool_mark_needed_node (vnode);
-      if (vnode->alias && vnode->extra_name)
-       vnode = vnode->extra_name;
       ipa_record_reference ((struct cgraph_node *)data, NULL,
                            NULL, vnode,
-                           IPA_REF_STORE, NULL);
+                           IPA_REF_STORE, stmt);
      }
   return false;
 }
@@ -325,10 +328,11 @@ static unsigned int
 build_cgraph_edges (void)
 {
   basic_block bb;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   struct pointer_set_t *visited_nodes = pointer_set_create ();
   gimple_stmt_iterator gsi;
-  tree step;
+  tree decl;
+  unsigned ix;
 
   /* Create the callgraph edges and record the nodes referenced by the function.
      body.  */
@@ -345,14 +349,12 @@ build_cgraph_edges (void)
                                                         bb);
              decl = gimple_call_fndecl (stmt);
              if (decl)
-               cgraph_create_edge (node, cgraph_node (decl), stmt,
-                                   bb->count, freq,
-                                   bb->loop_depth);
+               cgraph_create_edge (node, cgraph_get_create_node (decl),
+                                   stmt, bb->count, freq);
              else
                cgraph_create_indirect_edge (node, stmt,
                                             gimple_call_flags (stmt),
-                                            bb->count, freq,
-                                            bb->loop_depth);
+                                            bb->count, freq);
            }
          walk_stmt_load_store_addr_ops (stmt, node, mark_load,
                                         mark_store, mark_address);
@@ -360,16 +362,19 @@ build_cgraph_edges (void)
              && gimple_omp_parallel_child_fn (stmt))
            {
              tree fn = gimple_omp_parallel_child_fn (stmt);
-             cgraph_mark_needed_node (cgraph_node (fn));
+             ipa_record_reference (node, NULL, cgraph_get_create_node (fn),
+                                   NULL, IPA_REF_ADDR, stmt);
            }
          if (gimple_code (stmt) == GIMPLE_OMP_TASK)
            {
              tree fn = gimple_omp_task_child_fn (stmt);
              if (fn)
-               cgraph_mark_needed_node (cgraph_node (fn));
+               ipa_record_reference (node, NULL, cgraph_get_create_node (fn),
+                                     NULL, IPA_REF_ADDR, stmt);
              fn = gimple_omp_task_copy_fn (stmt);
              if (fn)
-               cgraph_mark_needed_node (cgraph_node (fn));
+               ipa_record_reference (node, NULL, cgraph_get_create_node (fn),
+                                     NULL, IPA_REF_ADDR, stmt);
            }
        }
       for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -378,15 +383,10 @@ build_cgraph_edges (void)
    }
 
   /* Look for initializers of constant variables and private statics.  */
-  for (step = cfun->local_decls;
-       step;
-       step = TREE_CHAIN (step))
-    {
-      tree decl = TREE_VALUE (step);
-      if (TREE_CODE (decl) == VAR_DECL
-         && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
-       varpool_finalize_decl (decl);
-    }
+  FOR_EACH_LOCAL_DECL (cfun, ix, decl)
+    if (TREE_CODE (decl) == VAR_DECL
+       && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
+      varpool_finalize_decl (decl);
   record_eh_tables (node, cfun);
 
   pointer_set_destroy (visited_nodes);
@@ -437,7 +437,7 @@ unsigned int
 rebuild_cgraph_edges (void)
 {
   basic_block bb;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   gimple_stmt_iterator gsi;
 
   cgraph_node_remove_callees (node);
@@ -458,14 +458,12 @@ rebuild_cgraph_edges (void)
                                                         bb);
              decl = gimple_call_fndecl (stmt);
              if (decl)
-               cgraph_create_edge (node, cgraph_node (decl), stmt,
-                                   bb->count, freq,
-                                   bb->loop_depth);
+               cgraph_create_edge (node, cgraph_get_create_node (decl), stmt,
+                                   bb->count, freq);
              else
                cgraph_create_indirect_edge (node, stmt,
                                             gimple_call_flags (stmt),
-                                            bb->count, freq,
-                                            bb->loop_depth);
+                                            bb->count, freq);
            }
          walk_stmt_load_store_addr_ops (stmt, node, mark_load,
                                         mark_store, mark_address);
@@ -488,7 +486,7 @@ void
 cgraph_rebuild_references (void)
 {
   basic_block bb;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   gimple_stmt_iterator gsi;
 
   ipa_remove_all_references (&node->ref_list);
@@ -522,7 +520,7 @@ struct gimple_opt_pass pass_rebuild_cgraph_edges =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  TV_NONE,                             /* tv_id */
+  TV_CGRAPH,                           /* tv_id */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -535,7 +533,7 @@ struct gimple_opt_pass pass_rebuild_cgraph_edges =
 static unsigned int
 remove_cgraph_callee_edges (void)
 {
-  cgraph_node_remove_callees (cgraph_node (current_function_decl));
+  cgraph_node_remove_callees (cgraph_get_node (current_function_decl));
   return 0;
 }