コード例 #1
0
ファイル: lto-symtab.c プロジェクト: chinabin/gcc-tiny
static void
lto_cgraph_replace_node (struct cgraph_node *node,
			 struct cgraph_node *prevailing_node)
{
  struct cgraph_edge *e, *next;
  bool compatible_p;

  if (symtab->dump_file)
    {
      fprintf (symtab->dump_file, "Replacing cgraph node %s/%i by %s/%i"
 	       " for symbol %s\n",
	       node->name (), node->order,
	       prevailing_node->name (),
	       prevailing_node->order,
	       IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name)
		 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)))));
    }

  /* Merge node flags.  */
  if (node->force_output)
    prevailing_node->mark_force_output ();
  if (node->forced_by_abi)
    prevailing_node->forced_by_abi = true;
  if (node->address_taken)
    {
      gcc_assert (!prevailing_node->global.inlined_to);
      prevailing_node->mark_address_taken ();
    }
  if (node->definition && prevailing_node->definition
      && DECL_COMDAT (node->decl) && DECL_COMDAT (prevailing_node->decl))
    prevailing_node->merged_comdat = true;

  /* Redirect all incoming edges.  */
  compatible_p
    = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->decl)),
			  TREE_TYPE (TREE_TYPE (node->decl)));
  for (e = node->callers; e; e = next)
    {
      next = e->next_caller;
      e->redirect_callee (prevailing_node);
      /* If there is a mismatch between the supposed callee return type and
	 the real one do not attempt to inline this function.
	 ???  We really need a way to match function signatures for ABI
	 compatibility and perform related promotions at inlining time.  */
      if (!compatible_p)
	e->call_stmt_cannot_inline_p = 1;
    }
  /* Redirect incomming references.  */
  prevailing_node->clone_referring (node);

  /* Fix instrumentation references.  */
  if (node->instrumented_version)
    {
      gcc_assert (node->instrumentation_clone
		  == prevailing_node->instrumentation_clone);
      node->instrumented_version->instrumented_version = prevailing_node;
      if (!prevailing_node->instrumented_version)
	prevailing_node->instrumented_version = node->instrumented_version;
      /* Need to reset node->instrumented_version to NULL,
	 otherwise node removal code would reset
	 node->instrumented_version->instrumented_version.  */
      node->instrumented_version = NULL;
    }

  lto_free_function_in_decl_state_for_node (node);

  if (node->decl != prevailing_node->decl)
    node->release_body ();

  /* Finally remove the replaced node.  */
  node->remove ();
}
コード例 #2
0
ファイル: lto-symtab.c プロジェクト: KangDroid/gcc
static void
lto_symtab_merge_symbols_1 (symtab_node *prevailing)
{
  symtab_node *e;
  symtab_node *next;

  prevailing->decl->decl_with_vis.symtab_node = prevailing;

  /* Replace the cgraph node of each entry with the prevailing one.  */
  for (e = prevailing->next_sharing_asm_name; e;
       e = next)
    {
      next = e->next_sharing_asm_name;

      if (!lto_symtab_symbol_p (e))
	continue;
      cgraph_node *ce = dyn_cast <cgraph_node *> (e);
      symtab_node *to = symtab_node::get (lto_symtab_prevailing_decl (e->decl));

      /* No matter how we are going to deal with resolution, we will ultimately
	 use prevailing definition.  */
      if (ce)
          ipa_merge_profiles (dyn_cast<cgraph_node *> (prevailing),
			      dyn_cast<cgraph_node *> (e));

      /* If we decided to replace the node by TO, do it.  */
      if (e != to)
	{
	  if (ce)
	    lto_cgraph_replace_node (ce, dyn_cast<cgraph_node *> (to));
	  else if (varpool_node *ve = dyn_cast <varpool_node *> (e))
	    lto_varpool_replace_node (ve, dyn_cast<varpool_node *> (to));
	}
      /* Watch out for duplicated symbols for a given declaration.  */
      else if (!e->transparent_alias
	       || !e->definition || e->get_alias_target () != to)
	{
	  /* We got a new declaration we do not want to merge.  In this case
	     get rid of the existing definition and create a transparent
	     alias.  */
	  if (ce)
	    {
	      lto_free_function_in_decl_state_for_node (ce);
	      if (!ce->weakref)
	        ce->release_body ();
	      ce->reset ();
	      symtab->call_cgraph_removal_hooks (ce);
	    }
	  else
	    {
	      DECL_INITIAL (e->decl) = error_mark_node;
	      if (e->lto_file_data)
		{
		  lto_free_function_in_decl_state_for_node (e);
		  e->lto_file_data = NULL;
		}
	      symtab->call_varpool_removal_hooks (dyn_cast<varpool_node *> (e));
	    }
	  e->remove_all_references ();
	  e->analyzed = e->body_removed = false;
	  e->resolve_alias (prevailing, true);
	  gcc_assert (e != prevailing);
	}
    }

  return;
}