summaryrefslogtreecommitdiff
path: root/gcc/lto-symtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/lto-symtab.c')
-rw-r--r--gcc/lto-symtab.c113
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));