static bool lto_symtab_resolve_can_prevail_p (symtab_node e) { if (!lto_symtab_symbol_p (e)) return false; /* The C++ frontend ends up neither setting TREE_STATIC nor DECL_EXTERNAL on virtual methods but only TREE_PUBLIC. So do not reject !TREE_STATIC here but only DECL_EXTERNAL. */ if (DECL_EXTERNAL (e->symbol.decl)) return false; return e->symbol.definition; }
void lto_symtab_merge_symbols (void) { symtab_node node; if (!flag_ltrans) { 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->symbol.next_sharing_asm_name && !node->symbol.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; if (!node->symbol.analyzed && node->symbol.alias_target) { symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target); gcc_assert (node->symbol.weakref); if (tgt) symtab_resolve_alias (node, tgt); } node->symbol.aux = NULL; if (!(cnode = dyn_cast <cgraph_node> (node)) || !cnode->clone_of || cnode->clone_of->symbol.decl != cnode->symbol.decl) { if (cnode && DECL_BUILT_IN (node->symbol.decl) && (cnode2 = cgraph_get_node (node->symbol.decl)) && cnode2 != cnode) lto_cgraph_replace_node (cnode2, cnode); symtab_insert_node_to_hashtable ((symtab_node)node); } } }
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; }
static void lto_symtab_merge_decls_1 (symtab_node first) { symtab_node e, prevailing; bool diagnosed_p = false; if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n", symtab_node_asm_name (first)); for (e = first; e; e = e->symbol.next_sharing_asm_name) if (TREE_PUBLIC (e->symbol.decl)) dump_symtab_node (cgraph_dump_file, e); } /* Compute the symbol resolutions. This is a no-op when using the linker plugin and resolution was decided by the linker. */ prevailing = lto_symtab_resolve_symbols (first); /* If there's not a prevailing symbol yet it's an external reference. Happens a lot during ltrans. Choose the first symbol with a cgraph or a varpool node. */ if (!prevailing) { prevailing = first; /* For variables chose with a priority variant with vnode attached (i.e. from unit where external declaration of variable is actually used). When there are multiple variants, chose one with size. This is needed for C++ typeinfos, for example in lto/20081204-1 there are typeifos in both units, just one of them do have size. */ if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL) { for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name) if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl)) && COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl)) && lto_symtab_symbol_p (e)) prevailing = e; } /* For variables prefer the non-builtin if one is available. */ else if (TREE_CODE (prevailing->symbol.decl) == FUNCTION_DECL) { for (e = first; e; e = e->symbol.next_sharing_asm_name) if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL && !DECL_BUILT_IN (e->symbol.decl) && lto_symtab_symbol_p (e)) { prevailing = e; break; } } } symtab_prevail_in_asm_name_hash (prevailing); /* Diagnose mismatched objects. */ for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name) { if (TREE_CODE (prevailing->symbol.decl) == TREE_CODE (e->symbol.decl)) continue; if (!lto_symtab_symbol_p (e)) continue; switch (TREE_CODE (prevailing->symbol.decl)) { case VAR_DECL: gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL); error_at (DECL_SOURCE_LOCATION (e->symbol.decl), "variable %qD redeclared as function", prevailing->symbol.decl); break; case FUNCTION_DECL: gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL); error_at (DECL_SOURCE_LOCATION (e->symbol.decl), "function %qD redeclared as variable", prevailing->symbol.decl); break; default: gcc_unreachable (); } diagnosed_p = true; } if (diagnosed_p) inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl), "previously declared here"); /* Merge the chain to the single prevailing decl and diagnose mismatches. */ lto_symtab_merge_decls_2 (prevailing, diagnosed_p); if (cgraph_dump_file) { fprintf (cgraph_dump_file, "After resolution:\n"); for (e = prevailing; e; e = e->symbol.next_sharing_asm_name) dump_symtab_node (cgraph_dump_file, e); } }
static symtab_node lto_symtab_resolve_symbols (symtab_node first) { symtab_node e; symtab_node prevailing = NULL; /* Always set e->node so that edges are updated to reflect decl merging. */ for (e = first; e; e = e->symbol.next_sharing_asm_name) if (lto_symtab_symbol_p (e) && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP || e->symbol.resolution == LDPR_PREVAILING_DEF)) { prevailing = e; break; } /* If the chain is already resolved there is nothing else to do. */ if (prevailing) { /* Assert it's the only one. */ for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name) if (lto_symtab_symbol_p (e) && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP || e->symbol.resolution == LDPR_PREVAILING_DEF)) fatal_error ("multiple prevailing defs for %qE", DECL_NAME (prevailing->symbol.decl)); return prevailing; } /* Find the single non-replaceable prevailing symbol and diagnose ODR violations. */ for (e = first; e; e = e->symbol.next_sharing_asm_name) { if (!lto_symtab_resolve_can_prevail_p (e)) continue; /* If we have a non-replaceable definition it prevails. */ if (!lto_symtab_resolve_replaceable_p (e)) { if (prevailing) { error_at (DECL_SOURCE_LOCATION (e->symbol.decl), "%qD has already been defined", e->symbol.decl); inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl), "previously defined here"); } prevailing = e; } } if (prevailing) return prevailing; /* Do a second round choosing one from the replaceable prevailing decls. */ for (e = first; e; e = e->symbol.next_sharing_asm_name) { if (!lto_symtab_resolve_can_prevail_p (e)) continue; /* Choose the first function that can prevail as prevailing. */ if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL) { prevailing = e; break; } /* From variables that can prevail choose the largest one. */ if (!prevailing || tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl), DECL_SIZE (e->symbol.decl)) /* When variables are equivalent try to chose one that has useful DECL_INITIAL. This makes sense for keyed vtables that are DECL_EXTERNAL but initialized. In units that do not need them we replace the initializer by error_mark_node to conserve memory. We know that the vtable is keyed outside the LTO unit - otherwise the keyed instance would prevail. We still can preserve useful info in the initializer. */ || (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl) && (DECL_INITIAL (e->symbol.decl) && DECL_INITIAL (e->symbol.decl) != error_mark_node) && (!DECL_INITIAL (prevailing->symbol.decl) || DECL_INITIAL (prevailing->symbol.decl) == error_mark_node))) prevailing = e; } return prevailing; }
static void lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p) { symtab_node *prevailing; symtab_node *e; vec<tree> mismatches = vNULL; unsigned i; tree decl; bool tbaa_p = false; /* Nothing to do for a single entry. */ prevailing = first; if (!prevailing->next_sharing_asm_name) return; /* Try to merge each entry with the prevailing one. */ symtab_node *last_prevailing = prevailing, *next; for (e = prevailing->next_sharing_asm_name; e; e = next) { next = e->next_sharing_asm_name; /* Skip non-LTO symbols and symbols whose declaration we already visited. */ if (lto_symtab_prevailing_decl (e->decl) != e->decl || !lto_symtab_symbol_p (e) || e->decl == prevailing->decl) continue; if (!lto_symtab_merge (prevailing, e) && !diagnosed_p && !DECL_ARTIFICIAL (e->decl)) mismatches.safe_push (e->decl); symtab_node *this_prevailing; for (this_prevailing = prevailing; ; this_prevailing = this_prevailing->next_sharing_asm_name) { if (this_prevailing->decl != e->decl && lto_symtab_merge_p (this_prevailing->decl, e->decl)) break; if (this_prevailing == last_prevailing) { this_prevailing = NULL; break; } } if (this_prevailing) lto_symtab_prevail_decl (this_prevailing->decl, e->decl); /* Maintain LRU list: relink the new prevaililng symbol just after previaling node in the chain and update last_prevailing. Since the number of possible declarations of a given symbol is small, this should be faster than building a hash. */ else if (e == prevailing->next_sharing_asm_name) last_prevailing = e; else { if (e->next_sharing_asm_name) e->next_sharing_asm_name->previous_sharing_asm_name = e->previous_sharing_asm_name; e->previous_sharing_asm_name->next_sharing_asm_name = e->next_sharing_asm_name; e->previous_sharing_asm_name = prevailing; e->next_sharing_asm_name = prevailing->next_sharing_asm_name; prevailing->next_sharing_asm_name->previous_sharing_asm_name = e; prevailing->next_sharing_asm_name = e; if (last_prevailing == prevailing) last_prevailing = e; } } if (mismatches.is_empty ()) return; /* Diagnose all mismatched re-declarations. */ FOR_EACH_VEC_ELT (mismatches, i, decl) { int level = warn_type_compatibility_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl), DECL_COMDAT (decl)); if (level) { bool diag = false; if (level & 2) diag = warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wodr, "%qD violates the C++ One Definition Rule ", decl); if (!diag && (level & 1)) diag = warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wlto_type_mismatch, "type of %qD does not match original " "declaration", decl); if (diag) { warn_types_mismatch (TREE_TYPE (prevailing->decl), TREE_TYPE (decl), DECL_SOURCE_LOCATION (prevailing->decl), DECL_SOURCE_LOCATION (decl)); if ((level & 4) && !TREE_READONLY (prevailing->decl)) tbaa_p = true; } diagnosed_p |= diag; } else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl)) && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl)) { diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wlto_type_mismatch, "alignment of %qD is bigger than " "original declaration", decl); } else diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wlto_type_mismatch, "size of %qD differ from the size of " "original declaration", decl); }
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; }