#include "tree.h"
#include "gimple.h"
#include "ggc.h"
-#include "lambda.h" /* gcd */
#include "hashtab.h"
#include "plugin-api.h"
#include "lto-streamer.h"
struct cgraph_node *prevailing_node)
{
struct cgraph_edge *e, *next;
- bool no_aliases_please = false;
bool compatible_p;
if (cgraph_dump_file)
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)))));
}
- if (prevailing_node->same_body_alias)
- {
- if (prevailing_node->thunk.thunk_p)
- no_aliases_please = true;
- prevailing_node = prevailing_node->same_body;
- }
-
/* Merge node flags. */
if (node->needed)
cgraph_mark_needed_node (prevailing_node);
/* Redirect all incoming edges. */
compatible_p
- = gimple_types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->decl)),
- TREE_TYPE (TREE_TYPE (node->decl)), GTC_DIAG);
+ = 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;
/* Redirect incomming references. */
ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
- /* If we have aliases, redirect them to the prevailing node. */
- if (!node->same_body_alias && node->same_body)
- {
- struct cgraph_node *alias, *last;
- /* We prevail aliases/tunks by a thunk. This is doable but
- would need thunk combination. Hopefully no ABI changes will
- every be crazy enough. */
- gcc_assert (!no_aliases_please);
-
- for (alias = node->same_body; alias; alias = alias->next)
- {
- last = alias;
- gcc_assert (alias->same_body_alias);
- alias->same_body = prevailing_node;
- alias->thunk.alias = prevailing_node->decl;
- }
- last->next = prevailing_node->same_body;
- /* Node with aliases is prevailed by alias.
- We could handle this, but combining thunks together will be tricky.
- Hopefully this does not happen. */
- if (prevailing_node->same_body)
- prevailing_node->same_body->previous = last;
- prevailing_node->same_body = node->same_body;
- node->same_body = NULL;
- }
-
/* Finally remove the replaced node. */
- if (node->same_body_alias)
- cgraph_remove_same_body_alias (node);
- else
- cgraph_remove_node (node);
+ cgraph_remove_node (node);
}
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
varpool_mark_needed_node (prevailing_node);
}
- /* Relink aliases. */
- if (vnode->extra_name && !vnode->alias)
- {
- struct varpool_node *alias, *last;
- for (alias = vnode->extra_name;
- alias; alias = alias->next)
- {
- last = alias;
- alias->extra_name = prevailing_node;
- }
-
- if (prevailing_node->extra_name)
- {
- last->next = prevailing_node->extra_name;
- prevailing_node->extra_name->prev = last;
- }
- prevailing_node->extra_name = vnode->extra_name;
- vnode->extra_name = NULL;
- }
gcc_assert (!vnode->finalized || prevailing_node->finalized);
gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
- /* When replacing by an alias, the references goes to the original
- variable. */
- if (prevailing_node->alias && prevailing_node->extra_name)
- prevailing_node = prevailing_node->extra_name;
ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list);
/* Be sure we can garbage collect the initializer. */
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- if (!gimple_types_compatible_p (TREE_TYPE (prevailing_decl),
- TREE_TYPE (decl), GTC_DIAG))
+ if (!types_compatible_p (TREE_TYPE (prevailing_decl),
+ TREE_TYPE (decl)))
/* If we don't have a merged type yet...sigh. The linker
wouldn't complain if the types were mismatched, so we
probably shouldn't either. Just use the type from
prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl));
type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
- /* We have to register and fetch canonical types here as the global
- fixup process didn't yet run. */
- prevailing_type = gimple_register_type (prevailing_type);
- type = gimple_register_type (type);
- if (!gimple_types_compatible_p (prevailing_type, type, GTC_DIAG))
+ if (!types_compatible_p (prevailing_type, type))
{
if (COMPLETE_TYPE_P (type))
return false;
if (TREE_CODE (tem1) != TREE_CODE (tem2))
return false;
- if (!gimple_types_compatible_p (gimple_register_type (tem1),
- gimple_register_type (tem2),
- GTC_DIAG))
+ if (!types_compatible_p (tem1, tem2))
return false;
}
/* For functions we need a non-discarded body. */
if (TREE_CODE (e->decl) == FUNCTION_DECL)
- return (e->node
- && (e->node->analyzed
- || (e->node->same_body_alias && e->node->same_body->analyzed)));
+ return (e->node && e->node->analyzed);
- /* A variable should have a size. */
else if (TREE_CODE (e->decl) == VAR_DECL)
{
if (!e->vnode)
return false;
- if (e->vnode->finalized)
- return true;
- return e->vnode->alias && e->vnode->extra_name->finalized;
+ return e->vnode->finalized;
}
gcc_unreachable ();
for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
{
if (TREE_CODE (e->decl) == FUNCTION_DECL)
- e->node = cgraph_get_node_or_alias (e->decl);
+ e->node = cgraph_get_node (e->decl);
else if (TREE_CODE (e->decl) == VAR_DECL)
e->vnode = varpool_get_node (e->decl);
}
}
/* Merge all decls in the symbol table chain to the prevailing decl and
- issue diagnostics about type mismatches. */
+ issue diagnostics about type mismatches. If DIAGNOSED_P is true
+ do not issue further diagnostics.*/
static void
-lto_symtab_merge_decls_2 (void **slot)
+lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
{
lto_symtab_entry_t prevailing, e;
VEC(tree, heap) *mismatches = NULL;
unsigned i;
tree decl;
- bool diagnosed_p = false;
/* Nothing to do for a single entry. */
prevailing = (lto_symtab_entry_t) *slot;
/* Try to merge each entry with the prevailing one. */
for (e = prevailing->next; e; e = e->next)
{
- if (!lto_symtab_merge (prevailing, e))
+ if (!lto_symtab_merge (prevailing, e)
+ && !diagnosed_p)
VEC_safe_push (tree, heap, mismatches, e->decl);
}
if (VEC_empty (tree, mismatches))
/* Diagnose all mismatched re-declarations. */
FOR_EACH_VEC_ELT (tree, mismatches, i, decl)
{
- if (!gimple_types_compatible_p (TREE_TYPE (prevailing->decl),
- TREE_TYPE (decl), GTC_DIAG))
+ if (!types_compatible_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl)))
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
"type of %qD does not match original "
"declaration", decl);
inform (DECL_SOURCE_LOCATION (prevailing->decl),
"previously declared here");
- /* Register and adjust types of the entries. */
- for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
- TREE_TYPE (e->decl) = gimple_register_type (TREE_TYPE (e->decl));
-
/* Merge the chain to the single prevailing decl and diagnose
mismatches. */
- lto_symtab_merge_decls_2 (slot);
-
- /* Drop all but the prevailing decl from the symtab. */
- if (TREE_CODE (prevailing->decl) != FUNCTION_DECL
- && TREE_CODE (prevailing->decl) != VAR_DECL)
- prevailing->next = NULL;
+ lto_symtab_merge_decls_2 (slot, diagnosed_p);
/* Store resolution decision into the callgraph.
In LTRANS don't overwrite information we stored into callgraph at
for (e = prevailing->next; e; e = e->next)
{
if (e->node != NULL)
- lto_cgraph_replace_node (e->node, prevailing->node);
+ {
+ /* In case we prevail funcion by an alias, we can run into case
+ that the alias has no cgraph node attached, since it was
+ previously unused. Create the node. */
+ if (!prevailing->node)
+ {
+ prevailing->node = cgraph_create_node (prevailing->decl);
+ prevailing->node->alias = true;
+ }
+ lto_cgraph_replace_node (e->node, prevailing->node);
+ }
if (e->vnode != NULL)
- lto_varpool_replace_node (e->vnode, prevailing->vnode);
+ {
+ if (!prevailing->vnode)
+ {
+ prevailing->vnode = varpool_node (prevailing->decl);
+ prevailing->vnode->alias = true;
+ }
+ lto_varpool_replace_node (e->vnode, prevailing->vnode);
+ }
}
/* Drop all but the prevailing decl from the symtab. */
void
lto_symtab_merge_cgraph_nodes (void)
{
+ struct cgraph_node *node;
+ struct varpool_node *vnode;
lto_symtab_maybe_init_hash_table ();
htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
+
+ for (node = cgraph_nodes; node; node = node->next)
+ if ((node->thunk.thunk_p || node->alias)
+ && node->thunk.alias)
+ node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
+ for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+ if (vnode->alias_of)
+ vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
}
/* Given the decl DECL, return the prevailing decl with the same name. */