/* Vector to keep track of external variables we've seen so far. */
VEC(tree,gc) *lto_global_var_decls;
-/* Symbol table entry. */
-
-struct GTY(()) lto_symtab_entry_def
-{
- /* The symbol table entry key, an IDENTIFIER. */
- tree id;
- /* The symbol table entry, a DECL. */
- tree decl;
- /* The cgraph node if decl is a function decl. Filled in during the
- merging process. */
- struct cgraph_node *node;
- /* The varpool node if decl is a variable decl. Filled in during the
- merging process. */
- struct varpool_node *vnode;
- /* LTO file-data and symbol resolution for this decl. */
- struct lto_file_decl_data * GTY((skip (""))) file_data;
- enum ld_plugin_symbol_resolution resolution;
- /* True when resolution was guessed and not read from the file. */
- bool guessed;
- /* Pointer to the next entry with the same key. Before decl merging
- this links all symbols from the different TUs. After decl merging
- this links merged but incompatible decls, thus all prevailing ones
- remaining. */
- struct lto_symtab_entry_def *next;
-};
-typedef struct lto_symtab_entry_def *lto_symtab_entry_t;
-
-/* A poor man's symbol table. This hashes identifier to prevailing DECL
- if there is one. */
-
-static GTY ((if_marked ("lto_symtab_entry_marked_p"),
- param_is (struct lto_symtab_entry_def)))
- htab_t lto_symtab_identifiers;
-
-/* Free symtab hashtable. */
-
-void
-lto_symtab_free (void)
-{
- htab_delete (lto_symtab_identifiers);
- lto_symtab_identifiers = NULL;
-}
-
-/* Return the hash value of an lto_symtab_entry_t object pointed to by P. */
-
-static hashval_t
-lto_symtab_entry_hash (const void *p)
-{
- const struct lto_symtab_entry_def *base =
- (const struct lto_symtab_entry_def *) p;
- return IDENTIFIER_HASH_VALUE (base->id);
-}
-
-/* Return non-zero if P1 and P2 points to lto_symtab_entry_def structs
- corresponding to the same symbol. */
-
-static int
-lto_symtab_entry_eq (const void *p1, const void *p2)
+/* Return true if the resolution was guessed and not obtained from
+ the file. */
+static inline bool
+resolution_guessed_p (symtab_node node)
{
- const struct lto_symtab_entry_def *base1 =
- (const struct lto_symtab_entry_def *) p1;
- const struct lto_symtab_entry_def *base2 =
- (const struct lto_symtab_entry_def *) p2;
- return (base1->id == base2->id);
+ return node->symbol.aux != NULL;
}
-/* Returns non-zero if P points to an lto_symtab_entry_def struct that needs
- to be marked for GC. */
-
-static int
-lto_symtab_entry_marked_p (const void *p)
+/* Set guessed flag for NODE. */
+static inline void
+set_resolution_guessed (symtab_node node, bool value)
{
- const struct lto_symtab_entry_def *base =
- (const struct lto_symtab_entry_def *) p;
-
- /* Keep this only if the common IDENTIFIER_NODE of the symtab chain
- is marked which it will be if at least one of the DECLs in the
- chain is marked. */
- return ggc_marked_p (base->id);
-}
-
-/* Lazily initialize resolution hash tables. */
-
-static void
-lto_symtab_maybe_init_hash_table (void)
-{
- if (lto_symtab_identifiers)
- return;
-
- lto_symtab_identifiers =
- htab_create_ggc (1021, lto_symtab_entry_hash,
- lto_symtab_entry_eq, NULL);
+ node->symbol.aux = (void *)(size_t)value;
}
/* Registers DECL with the LTO symbol table as having resolution RESOLUTION
ld_plugin_symbol_resolution_t resolution,
struct lto_file_decl_data *file_data)
{
- lto_symtab_entry_t new_entry;
- void **slot;
+ symtab_node node;
/* Check that declarations reaching this function do not have
properties inconsistent with having external linkage. If any of
if (TREE_CODE (decl) == FUNCTION_DECL)
gcc_assert (!DECL_ABSTRACT (decl));
- new_entry = ggc_alloc_cleared_lto_symtab_entry_def ();
- new_entry->id = (*targetm.asm_out.mangle_assembler_name)
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- new_entry->decl = decl;
- new_entry->resolution = resolution;
- new_entry->file_data = file_data;
-
- lto_symtab_maybe_init_hash_table ();
- slot = htab_find_slot (lto_symtab_identifiers, new_entry, INSERT);
- new_entry->next = (lto_symtab_entry_t) *slot;
- *slot = new_entry;
-}
-
-/* Get the lto_symtab_entry_def struct associated with ID
- if there is one. */
-
-static lto_symtab_entry_t
-lto_symtab_get (tree id)
-{
- struct lto_symtab_entry_def temp;
- void **slot;
-
- lto_symtab_maybe_init_hash_table ();
- temp.id = id;
- slot = htab_find_slot (lto_symtab_identifiers, &temp, NO_INSERT);
- return slot ? (lto_symtab_entry_t) *slot : NULL;
-}
-
-/* Get the linker resolution for DECL. */
-
-enum ld_plugin_symbol_resolution
-lto_symtab_get_resolution (tree decl)
-{
- lto_symtab_entry_t e;
-
- gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-
- e = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
- while (e && e->decl != decl)
- e = e->next;
- if (!e)
- return LDPR_UNKNOWN;
-
- return e->resolution;
+ node = symtab_get_node (decl);
+ if (node)
+ {
+ node->symbol.resolution = resolution;
+ gcc_assert (node->symbol.lto_file_data == file_data);
+ gcc_assert (!resolution_guessed_p (node));
+ }
}
-
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
all edges and removing the old node. */
should be emitted. */
static bool
-lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
+lto_symtab_merge (symtab_node prevailing, symtab_node entry)
{
- tree prevailing_decl = prevailing->decl;
- tree decl = entry->decl;
+ tree prevailing_decl = prevailing->symbol.decl;
+ tree decl = entry->symbol.decl;
tree prevailing_type, type;
+ if (prevailing_decl == decl)
+ return true;
+
/* Merge decl state in both directions, we may still end up using
the new decl. */
TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
entry. */
static bool
-lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
+lto_symtab_resolve_replaceable_p (symtab_node e)
{
- if (DECL_EXTERNAL (e->decl)
- || DECL_COMDAT (e->decl)
- || DECL_ONE_ONLY (e->decl)
- || DECL_WEAK (e->decl))
+ if (DECL_EXTERNAL (e->symbol.decl)
+ || DECL_COMDAT (e->symbol.decl)
+ || DECL_ONE_ONLY (e->symbol.decl)
+ || DECL_WEAK (e->symbol.decl))
return true;
- if (TREE_CODE (e->decl) == VAR_DECL)
- return (DECL_COMMON (e->decl)
- || (!flag_no_common && !DECL_INITIAL (e->decl)));
+ if (TREE_CODE (e->symbol.decl) == VAR_DECL)
+ return (DECL_COMMON (e->symbol.decl)
+ || (!flag_no_common && !DECL_INITIAL (e->symbol.decl)));
return false;
}
/* Return true if the symtab entry E can be the prevailing one. */
static bool
-lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
+lto_symtab_resolve_can_prevail_p (symtab_node e)
{
+ if (!symtab_real_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->decl))
+ if (DECL_EXTERNAL (e->symbol.decl))
return false;
/* For functions we need a non-discarded body. */
- if (TREE_CODE (e->decl) == FUNCTION_DECL)
- return (e->node && e->node->analyzed);
+ if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
+ return (cgraph (e)->analyzed);
- else if (TREE_CODE (e->decl) == VAR_DECL)
- {
- if (!e->vnode)
- return false;
- return e->vnode->finalized;
- }
+ else if (TREE_CODE (e->symbol.decl) == VAR_DECL)
+ return varpool (e)->finalized;
gcc_unreachable ();
}
their resolutions. */
static void
-lto_symtab_resolve_symbols (void **slot)
+lto_symtab_resolve_symbols (symtab_node first)
{
- lto_symtab_entry_t e;
- lto_symtab_entry_t prevailing = NULL;
+ symtab_node e;
+ symtab_node prevailing = NULL;
/* Always set e->node so that edges are updated to reflect decl merging. */
- for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
- {
- if (TREE_CODE (e->decl) == FUNCTION_DECL)
- e->node = cgraph_get_node (e->decl);
- else if (TREE_CODE (e->decl) == VAR_DECL)
- e->vnode = varpool_get_node (e->decl);
- if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
- || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || e->resolution == LDPR_PREVAILING_DEF)
- prevailing = e;
- }
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ if (symtab_real_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;
/* If the chain is already resolved there is nothing else to do. */
if (prevailing)
/* Find the single non-replaceable prevailing symbol and
diagnose ODR violations. */
- for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
{
if (!lto_symtab_resolve_can_prevail_p (e))
{
- e->resolution = LDPR_RESOLVED_IR;
- e->guessed = true;
+ e->symbol.resolution = LDPR_RESOLVED_IR;
+ set_resolution_guessed (e, true);
continue;
}
/* Set a default resolution - the final prevailing one will get
adjusted later. */
- e->resolution = LDPR_PREEMPTED_IR;
- e->guessed = true;
+ e->symbol.resolution = LDPR_PREEMPTED_IR;
+ set_resolution_guessed (e, true);
if (!lto_symtab_resolve_replaceable_p (e))
{
if (prevailing)
{
- error_at (DECL_SOURCE_LOCATION (e->decl),
- "%qD has already been defined", e->decl);
- inform (DECL_SOURCE_LOCATION (prevailing->decl),
+ 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;
goto found;
/* Do a second round choosing one from the replaceable prevailing decls. */
- for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
{
- if (e->resolution != LDPR_PREEMPTED_IR)
+ if (e->symbol.resolution != LDPR_PREEMPTED_IR
+ || !symtab_real_symbol_p (e))
continue;
/* Choose the first function that can prevail as prevailing. */
- if (TREE_CODE (e->decl) == FUNCTION_DECL)
+ 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->decl),
- DECL_SIZE (e->decl))
+ || 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 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->decl) == DECL_SIZE (e->decl)
- && (DECL_INITIAL (e->decl)
- && DECL_INITIAL (e->decl) != error_mark_node)
- && (!DECL_INITIAL (prevailing->decl)
- || DECL_INITIAL (prevailing->decl) == error_mark_node)))
+ || (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;
}
variables IRONLY, which are indeed PREVAILING_DEF in
resolution file. These variables still need manual
externally_visible attribute. */
- prevailing->resolution = LDPR_PREVAILING_DEF_IRONLY;
- prevailing->guessed = true;
+ prevailing->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
+ set_resolution_guessed (prevailing, true);
}
/* Merge all decls in the symbol table chain to the prevailing decl and
do not issue further diagnostics.*/
static void
-lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
+lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
{
- lto_symtab_entry_t prevailing, e;
+ symtab_node prevailing, e;
VEC(tree, heap) *mismatches = NULL;
unsigned i;
tree decl;
/* Nothing to do for a single entry. */
- prevailing = (lto_symtab_entry_t) *slot;
- if (!prevailing->next)
+ prevailing = first;
+ if (!prevailing->symbol.next_sharing_asm_name)
return;
/* Try to merge each entry with the prevailing one. */
- for (e = prevailing->next; e; e = e->next)
+ for (e = prevailing->symbol.next_sharing_asm_name;
+ e; e = e->symbol.next_sharing_asm_name)
{
if (!lto_symtab_merge (prevailing, e)
&& !diagnosed_p)
- VEC_safe_push (tree, heap, mismatches, e->decl);
+ VEC_safe_push (tree, heap, mismatches, e->symbol.decl);
}
if (VEC_empty (tree, mismatches))
return;
/* Diagnose all mismatched re-declarations. */
FOR_EACH_VEC_ELT (tree, mismatches, i, decl)
{
- if (!types_compatible_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl)))
+ if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl),
+ TREE_TYPE (decl)))
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
"type of %qD does not match original "
"declaration", decl);
- else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl))
- && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))
+ else if ((DECL_USER_ALIGN (prevailing->symbol.decl)
+ && DECL_USER_ALIGN (decl))
+ && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl))
{
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
"alignment of %qD is bigger than "
}
}
if (diagnosed_p)
- inform (DECL_SOURCE_LOCATION (prevailing->decl),
+ inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
"previously declared here");
VEC_free (tree, heap, mismatches);
/* Helper to process the decl chain for the symbol table entry *SLOT. */
-static int
-lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+static void
+lto_symtab_merge_decls_1 (symtab_node first)
{
- lto_symtab_entry_t e, prevailing;
+ 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)
+ dump_symtab_node (cgraph_dump_file, e);
+ }
+
/* Compute the symbol resolutions. This is a no-op when using the
- linker plugin. */
- lto_symtab_resolve_symbols (slot);
+ linker plugin and resolution was decided by the linker. */
+ lto_symtab_resolve_symbols (first);
/* Find the prevailing decl. */
- for (prevailing = (lto_symtab_entry_t) *slot;
+ for (prevailing = first;
prevailing
- && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY
- && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
- && prevailing->resolution != LDPR_PREVAILING_DEF;
- prevailing = prevailing->next)
+ && (!symtab_real_symbol_p (prevailing)
+ || (prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY
+ && prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
+ && prevailing->symbol.resolution != LDPR_PREVAILING_DEF));
+ prevailing = prevailing->symbol.next_sharing_asm_name)
;
/* Assert it's the only one. */
if (prevailing)
- for (e = prevailing->next; e; e = e->next)
- {
- if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
- || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || e->resolution == LDPR_PREVAILING_DEF)
- fatal_error ("multiple prevailing defs for %qE",
- DECL_NAME (prevailing->decl));
- }
+ for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name)
+ if (symtab_real_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));
/* 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 = (lto_symtab_entry_t) *slot;
- /* For functions choose one with a cgraph node. */
- if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
- while (!prevailing->node
- && prevailing->next)
- prevailing = prevailing->next;
+ prevailing = first;
/* For variables chose with a priority variant with vnode
attached (i.e. from unit where external declaration of
variable is actually used).
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->decl) == VAR_DECL)
+ if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
{
- for (e = prevailing->next; e; e = e->next)
- if ((!prevailing->vnode && e->vnode)
- || ((prevailing->vnode != NULL) == (e->vnode != NULL)
- && !COMPLETE_TYPE_P (TREE_TYPE (prevailing->decl))
- && COMPLETE_TYPE_P (TREE_TYPE (e->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)))
prevailing = e;
}
}
- /* Move it first in the list. */
- if ((lto_symtab_entry_t) *slot != prevailing)
- {
- for (e = (lto_symtab_entry_t) *slot; e->next != prevailing; e = e->next)
- ;
- e->next = prevailing->next;
- prevailing->next = (lto_symtab_entry_t) *slot;
- *slot = (void *) prevailing;
- }
+ symtab_prevail_in_asm_name_hash (prevailing);
/* Record the prevailing variable. */
- if (TREE_CODE (prevailing->decl) == VAR_DECL)
- VEC_safe_push (tree, gc, lto_global_var_decls, prevailing->decl);
+ if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
+ VEC_safe_push (tree, gc, lto_global_var_decls,
+ prevailing->symbol.decl);
/* Diagnose mismatched objects. */
- for (e = prevailing->next; e; e = e->next)
+ for (e = prevailing->symbol.next_sharing_asm_name;
+ e; e = e->symbol.next_sharing_asm_name)
{
- if (TREE_CODE (prevailing->decl) == TREE_CODE (e->decl))
+ if (TREE_CODE (prevailing->symbol.decl)
+ == TREE_CODE (e->symbol.decl))
continue;
- switch (TREE_CODE (prevailing->decl))
+ switch (TREE_CODE (prevailing->symbol.decl))
{
case VAR_DECL:
- gcc_assert (TREE_CODE (e->decl) == FUNCTION_DECL);
- error_at (DECL_SOURCE_LOCATION (e->decl),
- "variable %qD redeclared as function", prevailing->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->decl) == VAR_DECL);
- error_at (DECL_SOURCE_LOCATION (e->decl),
- "function %qD redeclared as variable", prevailing->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:
diagnosed_p = true;
}
if (diagnosed_p)
- inform (DECL_SOURCE_LOCATION (prevailing->decl),
+ 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 (slot, diagnosed_p);
+ lto_symtab_merge_decls_2 (first, diagnosed_p);
+
+ if (cgraph_dump_file)
+ {
+ fprintf (cgraph_dump_file, "After resolution:\n");
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ dump_symtab_node (cgraph_dump_file, e);
+ }
/* Store resolution decision into the callgraph.
In LTRANS don't overwrite information we stored into callgraph at
PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP.
First one would disable some whole program optimizations, while
ther second would imply to many whole program assumptions. */
- if (prevailing->node && !flag_ltrans && !prevailing->guessed)
- prevailing->node->symbol.resolution = prevailing->resolution;
- else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed)
- prevailing->vnode->symbol.resolution = prevailing->resolution;
- return 1;
+ if (resolution_guessed_p (prevailing))
+ prevailing->symbol.resolution = LDPR_UNKNOWN;
+ return;
}
/* Resolve and merge all symbol table chains to a prevailing decl. */
void
lto_symtab_merge_decls (void)
{
- lto_symtab_maybe_init_hash_table ();
- htab_traverse (lto_symtab_identifiers, lto_symtab_merge_decls_1, NULL);
+ symtab_node node;
+
+ /* In ltrans mode we read merged cgraph, we do not really need to care
+ about resolving symbols again, we only need to replace duplicated declarations
+ read from the callgraph and from function sections. */
+ if (flag_ltrans)
+ return;
+
+ /* Populate assembler name hash. */
+ symtab_initialize_asm_name_hash ();
+
+ FOR_EACH_SYMBOL (node)
+ if (TREE_PUBLIC (node->symbol.decl)
+ && node->symbol.next_sharing_asm_name
+ && !node->symbol.previous_sharing_asm_name)
+ lto_symtab_merge_decls_1 (node);
}
/* Helper to process the decl chain for the symbol table entry *SLOT. */
-static int
-lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+static void
+lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing)
{
- lto_symtab_entry_t e, prevailing = (lto_symtab_entry_t) *slot;
-
- if (!prevailing->next)
- return 1;
+ symtab_node e, next;
/* Replace the cgraph node of each entry with the prevailing one. */
- for (e = prevailing->next; e; e = e->next)
+ for (e = prevailing->symbol.next_sharing_asm_name; e;
+ e = next)
{
- if (e->node != NULL)
- {
- /* 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)
- {
- if (!prevailing->vnode)
- {
- prevailing->vnode = varpool_node (prevailing->decl);
- prevailing->vnode->alias = true;
- }
- lto_varpool_replace_node (e->vnode, prevailing->vnode);
- }
- }
+ next = e->symbol.next_sharing_asm_name;
- /* Drop all but the prevailing decl from the symtab. */
- prevailing->next = NULL;
+ if (!symtab_real_symbol_p (e))
+ continue;
+ if (symtab_function_p (e))
+ lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
+ if (symtab_variable_p (e))
+ lto_varpool_replace_node (varpool (e), varpool (prevailing));
+ }
- return 1;
+ return;
}
/* Merge cgraph nodes according to the symbol merging done by
void
lto_symtab_merge_cgraph_nodes (void)
{
- struct cgraph_node *node;
+ struct cgraph_node *cnode;
struct varpool_node *vnode;
- lto_symtab_maybe_init_hash_table ();
- htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
+ symtab_node node;
+
+ /* Populate assembler name hash. */
+ symtab_initialize_asm_name_hash ();
- FOR_EACH_FUNCTION (node)
- if ((node->thunk.thunk_p || node->alias)
- && node->thunk.alias)
- node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
+ if (!flag_ltrans)
+ FOR_EACH_SYMBOL (node)
+ if (TREE_PUBLIC (node->symbol.decl)
+ && node->symbol.next_sharing_asm_name
+ && !node->symbol.previous_sharing_asm_name)
+ lto_symtab_merge_cgraph_nodes_1 (node);
+
+ FOR_EACH_FUNCTION (cnode)
+ {
+ if ((cnode->thunk.thunk_p || cnode->alias)
+ && cnode->thunk.alias)
+ cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias);
+ cnode->symbol.aux = NULL;
+ }
FOR_EACH_VARIABLE (vnode)
- if (vnode->alias_of)
- vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
+ {
+ if (vnode->alias_of)
+ vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
+ vnode->symbol.aux = NULL;
+ }
}
/* Given the decl DECL, return the prevailing decl with the same name. */
tree
lto_symtab_prevailing_decl (tree decl)
{
- lto_symtab_entry_t ret;
+ symtab_node ret;
/* Builtins and local symbols are their own prevailing decl. */
if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
/* Walk through the list of candidates and return the one we merged to. */
- ret = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
+ ret = symtab_node_for_asm (DECL_ASSEMBLER_NAME (decl));
if (!ret)
- return NULL_TREE;
+ return decl;
- return ret->decl;
+ return ret->symbol.decl;
}
-
-#include "gt-lto-symtab.h"