Example #1
0
DEBUG_FUNCTION void
verify_symtab_node (symtab_node node)
{
  if (seen_error ())
    return;

  timevar_push (TV_CGRAPH_VERIFY);
  if (symtab_function_p (node))
    verify_cgraph_node (cgraph (node));
  else
    if (verify_symtab_base (node))
      {
        dump_symtab_node (stderr, node);
        internal_error ("verify_symtab_node failed");
      }
  timevar_pop (TV_CGRAPH_VERIFY);
}
Example #2
0
static struct cgraph_node *
save_inline_function_body (struct cgraph_node *node)
{
  struct cgraph_node *first_clone, *n;

  if (dump_file)
    fprintf (dump_file, "\nSaving body of %s for later reuse\n",
	     cgraph_node_name (node));
 
  gcc_assert (node == cgraph_get_node (node->symbol.decl));

  /* first_clone will be turned into real function.  */
  first_clone = node->clones;
  first_clone->symbol.decl = copy_node (node->symbol.decl);
  symtab_insert_node_to_hashtable ((symtab_node) first_clone);
  gcc_assert (first_clone == cgraph_get_node (first_clone->symbol.decl));

  /* Now reshape the clone tree, so all other clones descends from
     first_clone.  */
  if (first_clone->next_sibling_clone)
    {
      for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
        n->clone_of = first_clone;
      n->clone_of = first_clone;
      n->next_sibling_clone = first_clone->clones;
      if (first_clone->clones)
        first_clone->clones->prev_sibling_clone = n;
      first_clone->clones = first_clone->next_sibling_clone;
      first_clone->next_sibling_clone->prev_sibling_clone = NULL;
      first_clone->next_sibling_clone = NULL;
      gcc_assert (!first_clone->prev_sibling_clone);
    }
  first_clone->clone_of = NULL;

  /* Now node in question has no clones.  */
  node->clones = NULL;

  /* Inline clones share decl with the function they are cloned
     from.  Walk the whole clone tree and redirect them all to the
     new decl.  */
  if (first_clone->clones)
    for (n = first_clone->clones; n != first_clone;)
      {
        gcc_assert (n->symbol.decl == node->symbol.decl);
	n->symbol.decl = first_clone->symbol.decl;
	if (n->clones)
	  n = n->clones;
	else if (n->next_sibling_clone)
	  n = n->next_sibling_clone;
	else
	  {
	    while (n != first_clone && !n->next_sibling_clone)
	      n = n->clone_of;
	    if (n != first_clone)
	      n = n->next_sibling_clone;
	  }
      }

  /* Copy the OLD_VERSION_NODE function tree to the new version.  */
  tree_function_versioning (node->symbol.decl, first_clone->symbol.decl,
			    NULL, true, NULL, false,
			    NULL, NULL);

  /* The function will be short lived and removed after we inline all the clones,
     but make it internal so we won't confuse ourself.  */
  DECL_EXTERNAL (first_clone->symbol.decl) = 0;
  DECL_COMDAT_GROUP (first_clone->symbol.decl) = NULL_TREE;
  TREE_PUBLIC (first_clone->symbol.decl) = 0;
  DECL_COMDAT (first_clone->symbol.decl) = 0;
  first_clone->ipa_transforms_to_apply.release ();

  /* When doing recursive inlining, the clone may become unnecessary.
     This is possible i.e. in the case when the recursive function is proved to be
     non-throwing and the recursion happens only in the EH landing pad.
     We can not remove the clone until we are done with saving the body.
     Remove it now.  */
  if (!first_clone->callers)
    {
      cgraph_remove_node_and_inline_clones (first_clone, NULL);
      first_clone = NULL;
    }
#ifdef ENABLE_CHECKING
  else
    verify_cgraph_node (first_clone);
#endif
  return first_clone;
}