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); }
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; }