summaryrefslogtreecommitdiff
path: root/gcc/lto-symtab.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-05 14:05:54 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-05 14:05:54 +0000
commitfd193bcd4b2ed21bbc003bb85c23db5e0d31e572 (patch)
tree666c7b939b006e039aeec82b1397690b52070e18 /gcc/lto-symtab.c
parent09d0041cb92d96d749a3a5d5dfab78de3100d9d9 (diff)
downloadgcc-fd193bcd4b2ed21bbc003bb85c23db5e0d31e572.tar.gz
2009-10-05 Richard Guenther <rguenther@suse.de>
PR lto/41552 PR lto/41487 * lto-symtab.c (struct lto_symtab_base_def): Remove. (struct lto_symtab_identifier_def): Likewise. (struct lto_symtab_decl_def): Likewise. (struct lto_symtab_entry_def): New. (lto_symtab_identifier_t): Rename to ... (lto_symtab_entry_t): ... this. (lto_symtab_decls): Remove. (lto_symtab_base_hash): Rename to ... (lto_symtab_entry_hash): ... this. (lto_symtab_base_eq): Rename to ... (lto_symtab_entry_eq): ... this. (lto_symtab_base_marked_p): Rename to ... (lto_symtab_entry_marked_p): ... this. (lto_symtab_identifier_marked_p): Remove. (lto_symtab_decl_marked_p): Likewise. (lto_symtab_maybe_init_hash_tables): Rename to ... (lto_symtab_maybe_init_hash_table): ... this. (lto_symtab_set_resolution_and_file_data): Remove. (lto_symtab_register_decl): New function. (lto_symtab_get_identifier): Remove. (lto_symtab_get): New function. (lto_symtab_get_resolution): Adjust. (lto_symtab_get_identifier_decl): Remove. (lto_symtab_set_identifier_decl): Likewise. (lto_symtab_merge_decl): Rename to ... (lto_symtab_merge): ... this. Rewrite. (lto_symtab_merge_var): Remove. (lto_symtab_merge_fn): Likewise. (lto_symtab_prevailing_decl): Adjust. (lto_cgraph_replace_node): New function. (lto_symtab_merge_decls_2): Likewise. (lto_symtab_merge_decls_1): Likewise. (lto_symtab_fixup_var_decls): Likewise. (lto_symtab_resolve_symbols): Likewise. (lto_symtab_merge_decls): Likewise. (lto_symtab_prevailing_decl): Adjust. (lto_symtab_get_symtab_def): Remove. (lto_symtab_get_file_data): Likewise. (lto_symtab_clear_resolution): Adjust. (lto_symtab_clear_resolution): Likewise. * lto-cgraph.c (input_edge): Do not merge cgraph nodes here. (input_cgraph_1): Likewise. * lto-streamer-in.c (get_resolution): Do not provide fake symbol resolutions here. (deferred_global_decls): Remove. (lto_register_deferred_decls_in_symtab): Likewise. (lto_register_var_decl_in_symtab): Change signature, register variable via lto_symtab_register_decl. (lto_register_function_decl_in_symtab): Likewise. (lto_read_tree): Adjust. * lto-streamer.h (lto_register_deferred_decls_in_symtab): Remove. (lto_symtab_merge_var): Likewise. (lto_symtab_merge_fn): Likewise. (lto_symtab_register_decl): Declare. (lto_symtab_merge_decls): Likewise. lto/ * lto.c (lto_read_decls): Do not register deferred decls. (read_cgraph_and_symbols): Delay symbol and cgraph merging until after reading the IPA summaries. * g++.dg/lto/20091002-1_0.C: Adjust flags. * g++.dg/lto/20091004-1_0.C: New testcase. * g++.dg/lto/20091004-1_1.C: Likewise. * g++.dg/lto/20091004-2_0.C: Likewise. * g++.dg/lto/20091004-2_1.C: Likewise. * g++.dg/lto/20091004-3_0.C: Likewise. * g++.dg/lto/20091004-3_1.C: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152450 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/lto-symtab.c')
-rw-r--r--gcc/lto-symtab.c646
1 files changed, 365 insertions, 281 deletions
diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c
index 90a200fc735..85e3c6c9f93 100644
--- a/gcc/lto-symtab.c
+++ b/gcc/lto-symtab.c
@@ -33,114 +33,80 @@ along with GCC; see the file COPYING3. If not see
/* Vector to keep track of external variables we've seen so far. */
VEC(tree,gc) *lto_global_var_decls;
-/* Base type for resolution map. It maps NODE to resolution. */
+/* Symbol table entry. */
-struct GTY(()) lto_symtab_base_def
+struct GTY(()) lto_symtab_entry_def
{
- /* Key is either an IDENTIFIER or a DECL. */
- tree node;
-};
-typedef struct lto_symtab_base_def *lto_symtab_base_t;
-
-struct GTY(()) lto_symtab_identifier_def
-{
- struct lto_symtab_base_def base;
+ /* The symbol table entry key, an IDENTIFIER. */
+ tree id;
+ /* The symbol table entry, a DECL. */
tree decl;
-};
-typedef struct lto_symtab_identifier_def *lto_symtab_identifier_t;
-
-struct GTY(()) lto_symtab_decl_def
-{
- struct lto_symtab_base_def base;
- enum ld_plugin_symbol_resolution resolution;
+ /* LTO file-data and symbol resolution for this decl. */
struct lto_file_decl_data * GTY((skip (""))) file_data;
+ enum ld_plugin_symbol_resolution resolution;
+ /* 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_decl_def *lto_symtab_decl_t;
+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_identifier_marked_p"),
- param_is (struct lto_symtab_identifier_def)))
+static GTY ((if_marked ("lto_symtab_entry_marked_p"),
+ param_is (struct lto_symtab_entry_def)))
htab_t lto_symtab_identifiers;
-static GTY ((if_marked ("lto_symtab_decl_marked_p"),
- param_is (struct lto_symtab_decl_def)))
- htab_t lto_symtab_decls;
-
-/* Return the hash value of an lto_symtab_base_t object pointed to by P. */
+/* Return the hash value of an lto_symtab_entry_t object pointed to by P. */
static hashval_t
-lto_symtab_base_hash (const void *p)
+lto_symtab_entry_hash (const void *p)
{
- const struct lto_symtab_base_def *base =
- (const struct lto_symtab_base_def*) p;
- return htab_hash_pointer (base->node);
+ const struct lto_symtab_entry_def *base =
+ (const struct lto_symtab_entry_def *) p;
+ return htab_hash_pointer (base->id);
}
-/* Return non-zero if P1 and P2 points to lto_symtab_base_def structs
- corresponding to the same tree node. */
+/* Return non-zero if P1 and P2 points to lto_symtab_entry_def structs
+ corresponding to the same symbol. */
static int
-lto_symtab_base_eq (const void *p1, const void *p2)
+lto_symtab_entry_eq (const void *p1, const void *p2)
{
- const struct lto_symtab_base_def *base1 =
- (const struct lto_symtab_base_def *) p1;
- const struct lto_symtab_base_def *base2 =
- (const struct lto_symtab_base_def *) p2;
- return (base1->node == base2->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);
}
-/* Returns non-zero if P points to an lto_symtab_base_def struct that needs
+/* Returns non-zero if P points to an lto_symtab_entry_def struct that needs
to be marked for GC. */
static int
-lto_symtab_base_marked_p (const void *p)
+lto_symtab_entry_marked_p (const void *p)
{
- const struct lto_symtab_base_def *base =
- (const struct lto_symtab_base_def *) p;
+ const struct lto_symtab_entry_def *base =
+ (const struct lto_symtab_entry_def *) p;
- /* Keep this only if the key node is marked. */
- return ggc_marked_p (base->node);
-}
-
-/* Returns non-zero if P points to an lto_symtab_identifier_def struct that
- needs to be marked for GC. */
-
-static int
-lto_symtab_identifier_marked_p (const void *p)
-{
- return lto_symtab_base_marked_p (p);
-}
-
-/* Returns non-zero if P points to an lto_symtab_decl_def struct that needs
- to be marked for GC. */
-
-static int
-lto_symtab_decl_marked_p (const void *p)
-{
- return lto_symtab_base_marked_p (p);
+ /* Keep this only if the decl or the chain is marked. */
+ return (ggc_marked_p (base->decl)
+ || (base->next && ggc_marked_p (base->next)));
}
-#define lto_symtab_identifier_eq lto_symtab_base_eq
-#define lto_symtab_identifier_hash lto_symtab_base_hash
-#define lto_symtab_decl_eq lto_symtab_base_eq
-#define lto_symtab_decl_hash lto_symtab_base_hash
-
/* Lazily initialize resolution hash tables. */
static void
-lto_symtab_maybe_init_hash_tables (void)
+lto_symtab_maybe_init_hash_table (void)
{
- if (!lto_symtab_identifiers)
- {
- lto_symtab_identifiers =
- htab_create_ggc (1021, lto_symtab_identifier_hash,
- lto_symtab_identifier_eq, NULL);
- lto_symtab_decls =
- htab_create_ggc (1021, lto_symtab_decl_hash,
- lto_symtab_decl_eq, NULL);
- }
+ if (lto_symtab_identifiers)
+ return;
+
+ lto_symtab_identifiers =
+ htab_create_ggc (1021, lto_symtab_entry_hash,
+ lto_symtab_entry_eq, NULL);
}
/* Returns true iff the union of ATTRIBUTES_1 and ATTRIBUTES_2 can be
@@ -465,237 +431,366 @@ lto_symtab_compatible (tree old_decl, tree new_decl)
return true;
}
+/* Registers DECL with the LTO symbol table as having resolution RESOLUTION
+ and read from FILE_DATA. */
-/* Marks decl DECL as having resolution RESOLUTION. */
-
-static void
-lto_symtab_set_resolution_and_file_data (tree decl,
- ld_plugin_symbol_resolution_t
- resolution,
- struct lto_file_decl_data *file_data)
+void
+lto_symtab_register_decl (tree decl,
+ ld_plugin_symbol_resolution_t resolution,
+ struct lto_file_decl_data *file_data)
{
- lto_symtab_decl_t new_entry;
+ lto_symtab_entry_t new_entry;
void **slot;
- gcc_assert (decl);
-
- gcc_assert (TREE_PUBLIC (decl));
- gcc_assert (TREE_CODE (decl) != FUNCTION_DECL || !DECL_ABSTRACT (decl));
-
- new_entry = GGC_CNEW (struct lto_symtab_decl_def);
- new_entry->base.node = decl;
+ /* Check that declarations reaching this function do not have
+ properties inconsistent with having external linkage. If any of
+ these asertions fail, then the object file reader has failed to
+ detect these cases and issue appropriate error messages. */
+ gcc_assert (decl
+ && TREE_PUBLIC (decl)
+ && (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL)
+ && DECL_ASSEMBLER_NAME_SET_P (decl));
+ if (TREE_CODE (decl) == VAR_DECL)
+ gcc_assert (!(DECL_EXTERNAL (decl) && DECL_INITIAL (decl)));
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ gcc_assert (!DECL_ABSTRACT (decl));
+
+ new_entry = GGC_CNEW (struct lto_symtab_entry_def);
+ new_entry->id = DECL_ASSEMBLER_NAME (decl);
+ new_entry->decl = decl;
new_entry->resolution = resolution;
new_entry->file_data = file_data;
- lto_symtab_maybe_init_hash_tables ();
- slot = htab_find_slot (lto_symtab_decls, new_entry, INSERT);
- gcc_assert (!*slot);
+ 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_identifier_def struct associated with ID
- if there is one. If there is none and INSERT_P is true, create
- a new one. */
+/* Get the lto_symtab_entry_def struct associated with ID
+ if there is one. */
-static lto_symtab_identifier_t
-lto_symtab_get_identifier (tree id, bool insert_p)
+static lto_symtab_entry_t
+lto_symtab_get (tree id)
{
- struct lto_symtab_identifier_def temp;
- lto_symtab_identifier_t symtab_id;
+ struct lto_symtab_entry_def temp;
void **slot;
- lto_symtab_maybe_init_hash_tables ();
- temp.base.node = id;
- slot = htab_find_slot (lto_symtab_identifiers, &temp,
- insert_p ? INSERT : NO_INSERT);
- if (insert_p)
- {
- if (*slot)
- return (lto_symtab_identifier_t) *slot;
- else
- {
- symtab_id = GGC_CNEW (struct lto_symtab_identifier_def);
- symtab_id->base.node = id;
- *slot = symtab_id;
- return symtab_id;
- }
- }
- else
- return slot ? (lto_symtab_identifier_t) *slot : NULL;
+ 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;
}
-/* Return the DECL associated with an IDENTIFIER ID or return NULL_TREE
- if there is none. */
+/* Get the linker resolution for DECL. */
-static tree
-lto_symtab_get_identifier_decl (tree id)
+enum ld_plugin_symbol_resolution
+lto_symtab_get_resolution (tree decl)
{
- lto_symtab_identifier_t symtab_id = lto_symtab_get_identifier (id, false);
- return symtab_id ? symtab_id->decl : NULL_TREE;
-}
+ lto_symtab_entry_t e;
-/* SET the associated DECL of an IDENTIFIER ID to be DECL. */
+ gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-static void
-lto_symtab_set_identifier_decl (tree id, tree decl)
-{
- lto_symtab_identifier_t symtab_id = lto_symtab_get_identifier (id, true);
- symtab_id->decl = decl;
+ e = lto_symtab_get (DECL_ASSEMBLER_NAME (decl));
+ while (e && e->decl != decl)
+ e = e->next;
+ if (!e)
+ return LDPR_UNKNOWN;
+
+ return e->resolution;
}
-/* Common helper function for merging variable and function declarations.
- NEW_DECL is the newly found decl. RESOLUTION is the decl's resolution
- provided by the linker. */
+/* Replace the cgraph node OLD_NODE with NEW_NODE in the cgraph, merging
+ all edges and removing the old node. */
static void
-lto_symtab_merge_decl (tree new_decl,
- enum ld_plugin_symbol_resolution resolution,
- struct lto_file_decl_data *file_data)
+lto_cgraph_replace_node (struct cgraph_node *old_node,
+ struct cgraph_node *new_node)
{
- tree old_decl;
- tree name;
- ld_plugin_symbol_resolution_t old_resolution;
-
- gcc_assert (TREE_CODE (new_decl) == VAR_DECL
- || TREE_CODE (new_decl) == FUNCTION_DECL);
-
- gcc_assert (TREE_PUBLIC (new_decl));
-
- gcc_assert (DECL_LANG_SPECIFIC (new_decl) == NULL);
-
- /* Check that declarations reaching this function do not have
- properties inconsistent with having external linkage. If any of
- these asertions fail, then the object file reader has failed to
- detect these cases and issue appropriate error messages. */
- if (TREE_CODE (new_decl) == VAR_DECL)
- gcc_assert (!(DECL_EXTERNAL (new_decl) && DECL_INITIAL (new_decl)));
+ struct cgraph_edge *e, *next;
+
+ /* Merge node flags. */
+ if (old_node->needed)
+ cgraph_mark_needed_node (new_node);
+ if (old_node->reachable)
+ cgraph_mark_reachable_node (new_node);
+ if (old_node->address_taken)
+ cgraph_mark_address_taken_node (new_node);
+
+ /* Redirect all incoming edges. */
+ for (e = old_node->callers; e; e = next)
+ {
+ next = e->next_caller;
+ cgraph_redirect_edge_callee (e, new_node);
+ }
- /* Remember the resolution of this symbol. */
- lto_symtab_set_resolution_and_file_data (new_decl, resolution, file_data);
+ /* There are not supposed to be any outgoing edges from a node we
+ replace. Still this can happen for multiple instances of weak
+ functions.
+ ??? For now do what the old code did. Do not create edges for them. */
+ for (e = old_node->callees; e; e = next)
+ {
+ next = e->next_callee;
+ cgraph_remove_edge (e);
+ }
- /* Ensure DECL_ASSEMBLER_NAME will not set assembler name. */
- gcc_assert (DECL_ASSEMBLER_NAME_SET_P (new_decl));
+ /* Finally remove the replaced node. */
+ cgraph_remove_node (old_node);
+}
- /* Retrieve the previous declaration. */
- name = DECL_ASSEMBLER_NAME (new_decl);
- old_decl = lto_symtab_get_identifier_decl (name);
+/* Merge two variable or function symbol table entries ENTRY1 and ENTRY2.
+ Return the prevailing one or NULL if a merge is not possible. */
- /* If there was no previous declaration, then there is nothing to
- merge. */
- if (!old_decl)
- {
- lto_symtab_set_identifier_decl (name, new_decl);
- VEC_safe_push (tree, gc, lto_global_var_decls, new_decl);
- return;
- }
+static lto_symtab_entry_t
+lto_symtab_merge (lto_symtab_entry_t entry1, lto_symtab_entry_t entry2)
+{
+ tree old_decl = entry1->decl;
+ tree new_decl = entry2->decl;
+ ld_plugin_symbol_resolution_t old_resolution = entry1->resolution;
+ ld_plugin_symbol_resolution_t new_resolution = entry2->resolution;
+ struct cgraph_node *old_node = NULL;
+ struct cgraph_node *new_node = NULL;
/* Give ODR violation errors. */
- old_resolution = lto_symtab_get_resolution (old_decl);
- if (resolution == LDPR_PREVAILING_DEF
- || resolution == LDPR_PREVAILING_DEF_IRONLY)
+ if (new_resolution == LDPR_PREVAILING_DEF
+ || new_resolution == LDPR_PREVAILING_DEF_IRONLY)
{
if ((old_resolution == LDPR_PREVAILING_DEF
|| old_resolution == LDPR_PREVAILING_DEF_IRONLY)
- && (old_resolution != resolution || flag_no_common))
+ && (old_resolution != new_resolution || flag_no_common))
{
error_at (DECL_SOURCE_LOCATION (new_decl),
"%qD has already been defined", new_decl);
inform (DECL_SOURCE_LOCATION (old_decl),
"previously defined here");
- return;
+ return NULL;
}
}
- /* The linker may ask us to combine two incompatible symbols.
- Find a decl we can merge with or chain it in the list of decls
- for that symbol. */
- while (old_decl
- && !lto_symtab_compatible (old_decl, new_decl))
- old_decl = (tree) DECL_LANG_SPECIFIC (old_decl);
- if (!old_decl)
- {
- old_decl = lto_symtab_get_identifier_decl (name);
- while (DECL_LANG_SPECIFIC (old_decl) != NULL)
- old_decl = (tree) DECL_LANG_SPECIFIC (old_decl);
- DECL_LANG_SPECIFIC (old_decl) = (struct lang_decl *) new_decl;
- return;
- }
+ /* The linker may ask us to combine two incompatible symbols. */
+ if (!lto_symtab_compatible (old_decl, new_decl))
+ return NULL;
+
+ if (TREE_CODE (old_decl) == FUNCTION_DECL)
+ old_node = cgraph_get_node (old_decl);
+ if (TREE_CODE (new_decl) == FUNCTION_DECL)
+ new_node = cgraph_get_node (new_decl);
/* Merge decl state in both directions, we may still end up using
the new decl. */
TREE_ADDRESSABLE (old_decl) |= TREE_ADDRESSABLE (new_decl);
TREE_ADDRESSABLE (new_decl) |= TREE_ADDRESSABLE (old_decl);
- gcc_assert (resolution != LDPR_UNKNOWN
- && resolution != LDPR_UNDEF
+ gcc_assert (new_resolution != LDPR_UNKNOWN
+ && new_resolution != LDPR_UNDEF
&& old_resolution != LDPR_UNKNOWN
&& old_resolution != LDPR_UNDEF);
- if (resolution == LDPR_PREVAILING_DEF
- || resolution == LDPR_PREVAILING_DEF_IRONLY)
+ if (new_resolution == LDPR_PREVAILING_DEF
+ || new_resolution == LDPR_PREVAILING_DEF_IRONLY
+ || (!old_node && new_node))
{
- tree decl;
- gcc_assert (old_resolution == LDPR_PREEMPTED_IR
+ gcc_assert ((!old_node && new_node)
+ || old_resolution == LDPR_PREEMPTED_IR
|| old_resolution == LDPR_RESOLVED_IR
- || (old_resolution == resolution && !flag_no_common));
- DECL_LANG_SPECIFIC (new_decl) = DECL_LANG_SPECIFIC (old_decl);
- DECL_LANG_SPECIFIC (old_decl) = NULL;
- decl = lto_symtab_get_identifier_decl (name);
- if (decl == old_decl)
- {
- lto_symtab_set_identifier_decl (name, new_decl);
- return;
- }
- while ((tree) DECL_LANG_SPECIFIC (decl) != old_decl)
- decl = (tree) DECL_LANG_SPECIFIC (decl);
- DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) new_decl;
- return;
+ || (old_resolution == new_resolution && !flag_no_common));
+ if (old_node)
+ lto_cgraph_replace_node (old_node, new_node);
+ /* Choose new_decl, entry2. */
+ return entry2;
}
- if (resolution == LDPR_PREEMPTED_REG
- || resolution == LDPR_RESOLVED_EXEC
- || resolution == LDPR_RESOLVED_DYN)
+ if (new_resolution == LDPR_PREEMPTED_REG
+ || new_resolution == LDPR_RESOLVED_EXEC
+ || new_resolution == LDPR_RESOLVED_DYN)
gcc_assert (old_resolution == LDPR_PREEMPTED_REG
|| old_resolution == LDPR_RESOLVED_EXEC
|| old_resolution == LDPR_RESOLVED_DYN);
- if (resolution == LDPR_PREEMPTED_IR
- || resolution == LDPR_RESOLVED_IR)
+ if (new_resolution == LDPR_PREEMPTED_IR
+ || new_resolution == LDPR_RESOLVED_IR)
gcc_assert (old_resolution == LDPR_PREVAILING_DEF
|| old_resolution == LDPR_PREVAILING_DEF_IRONLY
|| old_resolution == LDPR_PREEMPTED_IR
|| old_resolution == LDPR_RESOLVED_IR);
- return;
+ if (new_node)
+ lto_cgraph_replace_node (new_node, old_node);
+
+ /* Choose old_decl, entry1. */
+ return entry1;
}
+/* Resolve the symbol with the candidates in the chain *SLOT and store
+ their resolutions. */
-/* Merge the VAR_DECL NEW_VAR with resolution RESOLUTION with any previous
- declaration with the same name. */
+static void
+lto_symtab_resolve_symbols (void **slot)
+{
+ lto_symtab_entry_t e = (lto_symtab_entry_t) *slot;
-void
-lto_symtab_merge_var (tree new_var, enum ld_plugin_symbol_resolution resolution)
+ /* If the chain is already resolved there is nothing to do. */
+ if (e->resolution != LDPR_UNKNOWN)
+ return;
+
+ /* This is a poor mans resolver. */
+ for (; e; e = e->next)
+ {
+ gcc_assert (e->resolution == LDPR_UNKNOWN);
+ if (DECL_EXTERNAL (e->decl)
+ || (TREE_CODE (e->decl) == FUNCTION_DECL
+ && !cgraph_get_node (e->decl)))
+ e->resolution = LDPR_RESOLVED_IR;
+ else
+ {
+ if (TREE_READONLY (e->decl))
+ e->resolution = LDPR_PREVAILING_DEF_IRONLY;
+ else
+ e->resolution = LDPR_PREVAILING_DEF;
+ }
+ }
+}
+
+/* Merge one symbol table chain to a (set of) prevailing decls. */
+
+static void
+lto_symtab_merge_decls_2 (void **slot)
+{
+ lto_symtab_entry_t e2, e1;
+
+ /* Nothing to do for a single entry. */
+ e1 = (lto_symtab_entry_t) *slot;
+ if (!e1->next)
+ return;
+
+ /* Try to merge each entry with each other entry. In case of a
+ single prevailing decl this is linear. */
+restart:
+ for (; e1; e1 = e1->next)
+ for (e2 = e1->next; e2; e2 = e2->next)
+ {
+ lto_symtab_entry_t prevailing = lto_symtab_merge (e1, e2);
+ if (prevailing == e1)
+ {
+ lto_symtab_entry_t tmp = prevailing;
+ while (tmp->next != e2)
+ tmp = tmp->next;
+ tmp->next = e2->next;
+ e2->next = NULL;
+ e2 = tmp;
+ }
+ else if (prevailing == e2)
+ {
+ lto_symtab_entry_t tmp = (lto_symtab_entry_t) *slot;
+ if (tmp == e1)
+ {
+ *slot = e1->next;
+ tmp = e1->next;
+ }
+ else
+ {
+ while (tmp->next != e1)
+ tmp = tmp->next;
+ tmp->next = e1->next;
+ }
+ e1->next = NULL;
+ e1 = tmp;
+ goto restart;
+ }
+ }
+}
+
+/* Fixup the chain of prevailing variable decls *SLOT that are commonized
+ during link-time. */
+
+static void
+lto_symtab_fixup_var_decls (void **slot)
+{
+ lto_symtab_entry_t e = (lto_symtab_entry_t) *slot;
+ tree size = bitsize_zero_node;
+
+ /* Find the largest prevailing decl and move it to the front of the chain.
+ This is the decl we will output as representative for the common
+ section. */
+ size = bitsize_zero_node;
+ if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || e->resolution == LDPR_PREVAILING_DEF)
+ size = DECL_SIZE (e->decl);
+ for (; e->next;)
+ {
+ lto_symtab_entry_t next = e->next;
+ if ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || next->resolution == LDPR_PREVAILING_DEF)
+ && tree_int_cst_lt (size, DECL_SIZE (next->decl)))
+ {
+ size = DECL_SIZE (next->decl);
+ e->next = next->next;
+ next->next = (lto_symtab_entry_t) *slot;
+ *slot = next;
+ }
+ else
+ e = next;
+ }
+
+ /* Mark everything apart from the first var as written out. */
+ e = (lto_symtab_entry_t) *slot;
+ for (e = e->next; e; e = e->next)
+ TREE_ASM_WRITTEN (e->decl) = true;
+}
+
+/* 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)
{
- lto_symtab_merge_decl (new_var, resolution, NULL);
+ lto_symtab_entry_t e;
+
+ /* Compute the symbol resolutions. */
+ lto_symtab_resolve_symbols (slot);
+
+ /* 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 a (hopefully) single prevailing decl. */
+ lto_symtab_merge_decls_2 (slot);
+
+ /* ??? Ideally we should delay all diagnostics until this point to
+ avoid duplicates. */
+
+ /* All done for FUNCTION_DECLs. */
+ e = (lto_symtab_entry_t) *slot;
+ if (TREE_CODE (e->decl) == FUNCTION_DECL)
+ return 1;
+
+ /* Fixup variables in case there are multiple prevailing ones. */
+ if (e->next)
+ lto_symtab_fixup_var_decls (slot);
+
+ /* Insert all variable decls into the global variable decl vector. */
+ for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
+ VEC_safe_push (tree, gc, lto_global_var_decls, e->decl);
+
+ return 1;
}
-/* Merge the FUNCTION_DECL NEW_FN with resolution RESOLUTION with any previous
- declaration with the same name. */
+/* Resolve and merge all symbol table chains to a prevailing decl. */
void
-lto_symtab_merge_fn (tree new_fn, enum ld_plugin_symbol_resolution resolution,
- struct lto_file_decl_data *file_data)
+lto_symtab_merge_decls (void)
{
- lto_symtab_merge_decl (new_fn, resolution, file_data);
+ lto_symtab_maybe_init_hash_table ();
+ htab_traverse (lto_symtab_identifiers, lto_symtab_merge_decls_1, NULL);
}
+
/* Given the decl DECL, return the prevailing decl with the same name. */
tree
lto_symtab_prevailing_decl (tree decl)
{
- tree ret;
- gcc_assert (decl);
+ lto_symtab_entry_t ret;
/* Builtins and local symbols are their own prevailing decl. */
if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
@@ -709,74 +804,35 @@ lto_symtab_prevailing_decl (tree 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_identifier_decl (DECL_ASSEMBLER_NAME (decl));
- if (!ret
- || DECL_LANG_SPECIFIC (ret) == NULL)
- return ret;
+ ret = lto_symtab_get (DECL_ASSEMBLER_NAME (decl));
+ if (!ret)
+ return NULL_TREE;
+
+ /* If there is only one candidate return it. */
+ if (ret->next == NULL)
+ return ret->decl;
/* If there are multiple decls to choose from find the one we merged
with and return that. */
while (ret)
{
- if (gimple_types_compatible_p (TREE_TYPE (decl), TREE_TYPE (ret)))
- return ret;
+ if (gimple_types_compatible_p (TREE_TYPE (decl), TREE_TYPE (ret->decl)))
+ return ret->decl;
- ret = (tree) DECL_LANG_SPECIFIC (ret);
+ ret = ret->next;
}
gcc_unreachable ();
}
-/* Return the hash table entry of DECL. */
-
-static struct lto_symtab_decl_def *
-lto_symtab_get_symtab_def (tree decl)
-{
- struct lto_symtab_decl_def temp, *symtab_decl;
- void **slot;
-
- gcc_assert (decl);
-
- lto_symtab_maybe_init_hash_tables ();
- temp.base.node = decl;
- slot = htab_find_slot (lto_symtab_decls, &temp, NO_INSERT);
- gcc_assert (slot && *slot);
- symtab_decl = (struct lto_symtab_decl_def*) *slot;
- return symtab_decl;
-}
-
-/* Return the resolution of DECL. */
-
-enum ld_plugin_symbol_resolution
-lto_symtab_get_resolution (tree decl)
-{
- gcc_assert (decl);
-
- if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
- return LDPR_PREVAILING_DEF_IRONLY;
-
- /* FIXME lto: There should be no DECL_ABSTRACT in the middle end. */
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT (decl))
- return LDPR_PREVAILING_DEF_IRONLY;
-
- return lto_symtab_get_symtab_def (decl)->resolution;
-}
-
-/* Return the file of DECL. */
-
-struct lto_file_decl_data *
-lto_symtab_get_file_data (tree decl)
-{
- return lto_symtab_get_symtab_def (decl)->file_data;
-}
-
/* Remove any storage used to store resolution of DECL. */
void
lto_symtab_clear_resolution (tree decl)
{
- struct lto_symtab_decl_def temp;
- gcc_assert (decl);
+ struct lto_symtab_entry_def temp;
+ lto_symtab_entry_t head;
+ void **slot;
if (!TREE_PUBLIC (decl))
return;
@@ -785,9 +841,37 @@ lto_symtab_clear_resolution (tree decl)
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT (decl))
return;
- lto_symtab_maybe_init_hash_tables ();
- temp.base.node = decl;
- htab_remove_elt (lto_symtab_decls, &temp);
+ gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
+
+ lto_symtab_maybe_init_hash_table ();
+ temp.id = DECL_ASSEMBLER_NAME (decl);
+ slot = htab_find_slot (lto_symtab_identifiers, &temp, NO_INSERT);
+ if (!*slot)
+ return;
+
+ head = (lto_symtab_entry_t) *slot;
+ if (head->decl == decl)
+ {
+ if (head->next)
+ {
+ *slot = head->next;
+ head->next = NULL;
+ }
+ else
+ htab_remove_elt (lto_symtab_identifiers, &temp);
+ }
+ else
+ {
+ lto_symtab_entry_t e;
+ while (head->next && head->next->decl != decl)
+ head = head->next;
+ if (head->next)
+ {
+ e = head->next;
+ head->next = e->next;
+ e->next = NULL;
+ }
+ }
}
#include "gt-lto-symtab.h"