OSDN Git Service

2010-03-18 Martin Jambor <mjambor@suse.cz>
[pf3gnuchains/gcc-fork.git] / gcc / cgraphunit.c
index fcb96b2..b91e218 100644 (file)
@@ -382,6 +382,7 @@ cgraph_process_new_functions (void)
   tree fndecl;
   struct cgraph_node *node;
 
+  varpool_analyze_pending_decls ();
   /*  Note that this queue may grow as its being processed, as the new
       functions may generate new ones.  */
   while (cgraph_new_nodes)
@@ -437,6 +438,7 @@ cgraph_process_new_functions (void)
          break;
        }
       cgraph_call_function_insertion_hooks (node);
+      varpool_analyze_pending_decls ();
     }
   return output;
 }
@@ -607,6 +609,24 @@ verify_cgraph_node (struct cgraph_node *node)
       error ("Inline clone is needed");
       error_found = true;
     }
+  for (e = node->indirect_calls; e; e = e->next_callee)
+    {
+      if (e->aux)
+       {
+         error ("aux field set for indirect edge from %s",
+                identifier_to_locale (cgraph_node_name (e->caller)));
+         error_found = true;
+       }
+      if (!e->indirect_unknown_callee
+         || !e->indirect_info)
+       {
+         error ("An indirect edge from %s is not marked as indirect or has "
+                "associated indirect_info, the corresponding statement is: ",
+                identifier_to_locale (cgraph_node_name (e->caller)));
+         debug_gimple_stmt (e->call_stmt);
+         error_found = true;
+       }
+    }
   for (e = node->callers; e; e = e->next_caller)
     {
       if (e->count < 0)
@@ -714,6 +734,32 @@ verify_cgraph_node (struct cgraph_node *node)
       error ("double linked list of clones corrupted");
       error_found = true;
     }
+  if (node->same_comdat_group)
+    {
+      struct cgraph_node *n = node->same_comdat_group;
+
+      if (!DECL_ONE_ONLY (node->decl))
+       {
+         error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
+         error_found = true;
+       }
+      if (n == node)
+       {
+         error ("node is alone in a comdat group");
+         error_found = true;
+       }
+      do
+       {
+         if (!n->same_comdat_group)
+           {
+             error ("same_comdat_group is not a circular list");
+             error_found = true;
+             break;
+           }
+         n = n->same_comdat_group;
+       }
+      while (n != node);
+    }
 
   if (node->analyzed && gimple_has_body_p (node->decl)
       && !TREE_ASM_WRITTEN (node->decl)
@@ -733,10 +779,10 @@ verify_cgraph_node (struct cgraph_node *node)
                  gsi_next (&gsi))
              {
                gimple stmt = gsi_stmt (gsi);
-               tree decl;
-               if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
+               if (is_gimple_call (stmt))
                  {
                    struct cgraph_edge *e = cgraph_edge (node, stmt);
+                   tree decl = gimple_call_fndecl (stmt);
                    if (e)
                      {
                        if (e->aux)
@@ -745,25 +791,40 @@ verify_cgraph_node (struct cgraph_node *node)
                            debug_gimple_stmt (stmt);
                            error_found = true;
                          }
-                       if (e->callee->same_body_alias)
+                       if (!e->indirect_unknown_callee)
                          {
-                           error ("edge points to same body alias:");
-                           debug_tree (e->callee->decl);
-                           error_found = true;
+                           if (e->callee->same_body_alias)
+                             {
+                               error ("edge points to same body alias:");
+                               debug_tree (e->callee->decl);
+                               error_found = true;
+                             }
+                           else if (!node->global.inlined_to
+                                    && !e->callee->global.inlined_to
+                                    && decl
+                                    && !clone_of_p (cgraph_node (decl),
+                                                    e->callee))
+                             {
+                               error ("edge points to wrong declaration:");
+                               debug_tree (e->callee->decl);
+                               fprintf (stderr," Instead of:");
+                               debug_tree (decl);
+                               error_found = true;
+                             }
                          }
                        else if (!node->global.inlined_to
                                 && !e->callee->global.inlined_to
                                 && !clone_of_p (cgraph_node (decl), e->callee))
                          {
-                           error ("edge points to wrong declaration:");
-                           debug_tree (e->callee->decl);
-                           fprintf (stderr," Instead of:");
-                           debug_tree (decl);
+                           error ("an indirect edge with unknown callee "
+                                  "corresponding to a call_stmt with "
+                                  "a known declaration:");
                            error_found = true;
+                           debug_gimple_stmt (e->call_stmt);
                          }
                        e->aux = (void *)1;
                      }
-                   else
+                   else if (decl)
                      {
                        error ("missing callgraph edge for call stmt:");
                        debug_gimple_stmt (stmt);
@@ -779,7 +840,7 @@ verify_cgraph_node (struct cgraph_node *node)
 
       for (e = node->callees; e; e = e->next_callee)
        {
-         if (!e->aux && !e->indirect_call)
+         if (!e->aux)
            {
              error ("edge %s->%s has no corresponding call_stmt",
                     identifier_to_locale (cgraph_node_name (e->caller)),
@@ -789,6 +850,17 @@ verify_cgraph_node (struct cgraph_node *node)
            }
          e->aux = 0;
        }
+      for (e = node->indirect_calls; e; e = e->next_callee)
+       {
+         if (!e->aux)
+           {
+             error ("an indirect edge from %s has no corresponding call_stmt",
+                    identifier_to_locale (cgraph_node_name (e->caller)));
+             debug_gimple_stmt (e->call_stmt);
+             error_found = true;
+           }
+         e->aux = 0;
+       }
     }
   if (error_found)
     {
@@ -889,11 +961,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
     {
       tree decl = node->decl;
       if (DECL_PRESERVE_P (decl))
-       {
-         mark_decl_referenced (decl);
-         if (node->local.finalized)
-            cgraph_mark_needed_node (node);
-       }
+       cgraph_mark_needed_node (node);
       if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
        {
          if (! TREE_PUBLIC (node->decl))
@@ -909,7 +977,6 @@ process_function_and_variable_attributes (struct cgraph_node *first,
       tree decl = vnode->decl;
       if (DECL_PRESERVE_P (decl))
        {
-         mark_decl_referenced (decl);
          vnode->force_output = true;
          if (vnode->finalized)
            varpool_mark_needed_node (vnode);
@@ -1131,6 +1198,7 @@ cgraph_mark_functions_to_output (void)
       if (node->analyzed
          && !node->global.inlined_to
          && (node->needed || node->reachable_from_other_partition
+             || node->address_taken
              || (e && node->reachable))
          && !TREE_ASM_WRITTEN (decl)
          && !DECL_EXTERNAL (decl))
@@ -1531,7 +1599,6 @@ assemble_thunk (struct cgraph_node *node)
       cgraph_remove_same_body_alias (node);
       /* Since we want to emit the thunk, we explicitly mark its name as
         referenced.  */
-      mark_decl_referenced (thunk_fndecl);
       cgraph_add_new_function (thunk_fndecl, true);
       bitmap_obstack_release (NULL);
     }
@@ -1796,11 +1863,19 @@ ipa_passes (void)
       execute_ipa_summary_passes
        ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
     }
+
+  /* Some targets need to handle LTO assembler output specially.  */
+  if (flag_generate_lto)
+    targetm.asm_out.lto_start ();
+
   execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
 
   if (!in_lto_p)
     ipa_write_summaries ();
 
+  if (flag_generate_lto)
+    targetm.asm_out.lto_end ();
+
   if (!flag_ltrans)
     execute_ipa_pass_list (all_regular_ipa_passes);
   invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
@@ -2269,7 +2344,6 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
 
   gsi = gsi_for_stmt (e->call_stmt);
   gsi_replace (&gsi, new_stmt, true);
-  update_stmt (new_stmt);
 
   /* Update EH information too, just in case.  */
   maybe_clean_or_replace_eh_stmt (e->call_stmt, new_stmt);
@@ -2352,9 +2426,8 @@ cgraph_materialize_all_clones (void)
                        }
                    }
                  cgraph_materialize_clone (node);
+                 stabilized = false;
                }
-             else
-               stabilized = false;
            }
        }
     }
@@ -2373,7 +2446,6 @@ cgraph_materialize_all_clones (void)
         push_cfun (DECL_STRUCT_FUNCTION (node->decl));
        for (e = node->callees; e; e = e->next_callee)
          cgraph_redirect_edge_call_stmt_to_callee (e);
-       gcc_assert (!need_ssa_update_p (cfun));
        pop_cfun ();
        current_function_decl = NULL;
 #ifdef ENABLE_CHECKING