static void lto_symtab_merge_symbols_1 (symtab_node prevailing) { symtab_node e, next; /* Replace the cgraph node of each entry with the prevailing one. */ for (e = prevailing->symbol.next_sharing_asm_name; e; e = next) { next = e->symbol.next_sharing_asm_name; if (!lto_symtab_symbol_p (e)) continue; cgraph_node *ce = dyn_cast <cgraph_node> (e); if (ce && !DECL_BUILT_IN (e->symbol.decl)) lto_cgraph_replace_node (ce, cgraph (prevailing)); if (varpool_node *ve = dyn_cast <varpool_node> (e)) lto_varpool_replace_node (ve, varpool (prevailing)); } return; }
void lto_symtab_merge_symbols (void) { symtab_node *node; if (!flag_ltrans) { symtab->symtab_initialize_asm_name_hash (); /* Do the actual merging. At this point we invalidate hash translating decls into symtab nodes because after removing one of duplicate decls the hash is not correcly updated to the ohter dupliate. */ FOR_EACH_SYMBOL (node) if (lto_symtab_symbol_p (node) && node->next_sharing_asm_name && !node->previous_sharing_asm_name) lto_symtab_merge_symbols_1 (node); /* Resolve weakref aliases whose target are now in the compilation unit. also re-populate the hash translating decls into symtab nodes*/ FOR_EACH_SYMBOL (node) { cgraph_node *cnode, *cnode2; varpool_node *vnode; symtab_node *node2; if (!node->analyzed && node->alias_target) { symtab_node *tgt = symtab_node::get_for_asmname (node->alias_target); gcc_assert (node->weakref); if (tgt) node->resolve_alias (tgt, true); } /* If the symbol was preempted outside IR, see if we want to get rid of the definition. */ if (node->analyzed && !DECL_EXTERNAL (node->decl) && (node->resolution == LDPR_PREEMPTED_REG || node->resolution == LDPR_RESOLVED_IR || node->resolution == LDPR_RESOLVED_EXEC || node->resolution == LDPR_RESOLVED_DYN)) { DECL_EXTERNAL (node->decl) = 1; /* If alias to local symbol was preempted by external definition, we know it is not pointing to the local symbol. Remove it. */ if (node->alias && !node->weakref && !node->transparent_alias && node->get_alias_target ()->binds_to_current_def_p ()) { node->alias = false; node->remove_all_references (); node->definition = false; node->analyzed = false; node->cpp_implicit_alias = false; } else if (!node->alias && node->definition && node->get_availability () <= AVAIL_INTERPOSABLE) { if ((cnode = dyn_cast <cgraph_node *> (node)) != NULL) cnode->reset (); else { node->analyzed = node->definition = false; node->remove_all_references (); } } } if (!(cnode = dyn_cast <cgraph_node *> (node)) || !cnode->clone_of || cnode->clone_of->decl != cnode->decl) { /* Builtins are not merged via decl merging. It is however possible that tree merging unified the declaration. We do not want duplicate entries in symbol table. */ if (cnode && DECL_BUILT_IN (node->decl) && (cnode2 = cgraph_node::get (node->decl)) && cnode2 != cnode) lto_cgraph_replace_node (cnode2, cnode); /* The user defined assembler variables are also not unified by their symbol name (since it is irrelevant), but we need to unify symbol nodes if tree merging occurred. */ if ((vnode = dyn_cast <varpool_node *> (node)) && DECL_HARD_REGISTER (vnode->decl) && (node2 = symtab_node::get (vnode->decl)) && node2 != node) lto_varpool_replace_node (dyn_cast <varpool_node *> (node2), vnode); /* Abstract functions may have duplicated cgraph nodes attached; remove them. */ else if (cnode && DECL_ABSTRACT_P (cnode->decl) && (cnode2 = cgraph_node::get (node->decl)) && cnode2 != cnode) cnode2->remove (); node->decl->decl_with_vis.symtab_node = node; } } }
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; }