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