diff options
Diffstat (limited to 'gcc/lto-symtab.c')
-rw-r--r-- | gcc/lto-symtab.c | 113 |
1 files changed, 33 insertions, 80 deletions
diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c index 6c433f42731..257280cb970 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -235,9 +235,6 @@ lto_symtab_symbol_p (symtab_node e) { if (!TREE_PUBLIC (e->symbol.decl) && !DECL_EXTERNAL (e->symbol.decl)) return false; - /* weakrefs are really static variables that are made external by a hack. */ - if (lookup_attribute ("weakref", DECL_ATTRIBUTES (e->symbol.decl))) - return false; return symtab_real_symbol_p (e); } @@ -542,7 +539,7 @@ lto_symtab_merge_decls (void) /* Helper to process the decl chain for the symbol table entry *SLOT. */ static void -lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing) +lto_symtab_merge_symbols_1 (symtab_node prevailing) { symtab_node e, next; @@ -568,88 +565,49 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing) lto_symtab_merge_decls. */ void -lto_symtab_merge_cgraph_nodes (void) +lto_symtab_merge_symbols (void) { - struct cgraph_node *cnode; - struct varpool_node *vnode; symtab_node node; - /* Populate assembler name hash. */ - symtab_initialize_asm_name_hash (); - if (!flag_ltrans) - 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_cgraph_nodes_1 (node); - - FOR_EACH_FUNCTION (cnode) { - /* Resolve weakrefs to symbol defined in other unit. */ - if (!cnode->symbol.analyzed && cnode->thunk.alias && !DECL_P (cnode->thunk.alias)) + 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) { - symtab_node node = symtab_node_for_asm (cnode->thunk.alias); - if (node && is_a <cgraph_node> (node)) + cgraph_node *cnode, *cnode2; + if (!node->symbol.analyzed && node->symbol.alias_target) { - struct cgraph_node *n; - - for (n = cgraph (node); n && n->symbol.alias; - n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL) - if (n == cnode) - { - error ("function %q+D part of alias cycle", cnode->symbol.decl); - cnode->symbol.alias = false; - break; - } - if (cnode->symbol.alias) - { - cgraph_create_function_alias (cnode->symbol.decl, node->symbol.decl); - ipa_record_reference ((symtab_node)cnode, (symtab_node)node, - IPA_REF_ALIAS, NULL); - cnode->symbol.analyzed = true; - } + symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target); + gcc_assert (node->symbol.weakref); + if (tgt) + symtab_resolve_alias (node, tgt); } - else if (node) - error ("%q+D alias in between function and variable is not supported", cnode->symbol.decl); - } - if ((cnode->thunk.thunk_p || cnode->symbol.alias) - && cnode->thunk.alias && DECL_P (cnode->thunk.alias)) - cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias); - cnode->symbol.aux = NULL; - } - FOR_EACH_VARIABLE (vnode) - { - /* Resolve weakrefs to symbol defined in other unit. */ - if (!vnode->symbol.analyzed && vnode->alias_of && !DECL_P (vnode->alias_of)) - { - symtab_node node = symtab_node_for_asm (vnode->alias_of); - if (node && is_a <cgraph_node> (node)) + node->symbol.aux = NULL; + + if (!(cnode = dyn_cast <cgraph_node> (node)) + || !cnode->clone_of + || cnode->clone_of->symbol.decl != cnode->symbol.decl) { - struct varpool_node *n; - - for (n = varpool (node); n && n->symbol.alias; - n = n->symbol.analyzed ? varpool_alias_target (n) : NULL) - if (n == vnode) - { - error ("function %q+D part of alias cycle", vnode->symbol.decl); - vnode->symbol.alias = false; - break; - } - if (vnode->symbol.alias) - { - varpool_create_variable_alias (vnode->symbol.decl, node->symbol.decl); - ipa_record_reference ((symtab_node)vnode, (symtab_node)node, - IPA_REF_ALIAS, NULL); - vnode->symbol.analyzed = true; - } + 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); } - else if (node) - error ("%q+D alias in between function and variable is not supported", vnode->symbol.decl); } - if (vnode->symbol.alias && DECL_P (vnode->alias_of)) - vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of); - vnode->symbol.aux = NULL; } } @@ -673,11 +631,6 @@ lto_symtab_prevailing_decl (tree decl) if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) return decl; - /* As an anoying special cases weakrefs are really static variables with - EXTERNAL flag. */ - if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) - return decl; - /* Ensure DECL_ASSEMBLER_NAME will not set assembler name. */ gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); |