mirror of git://gcc.gnu.org/git/gcc.git
symtab.c (insert_to_assembler_name_hash): Do not insert register vars.
* symtab.c (insert_to_assembler_name_hash): Do not insert register vars. (unlink_from_assembler_name_hash): NULL out pointers of unlinked var. (symtab_prevail_in_asm_name_hash): New. (symtab_initialize_asm_name_hash): Break out from ... (symtab_node_for_asm): ... here. (dump_symtab_base): Dump LTO file data. (verify_symtab_base): Register vars are not in symtab. * cgraph.h (symtab_initialize_asm_name_hash, symtab_prevail_in_asm_name_hash): New functions. (symtab_real_symbol_p): New inline. * lto-symtab.c: Do not include gt-lto-symtab.h. (lto_symtab_entry_def): Remove. (lto_symtab_entry_t): Remove. (lto_symtab_identifiers): Remove. (lto_symtab_free): Remove. (lto_symtab_entry_hash): Remove. (lto_symtab_entry_eq): Remove. (lto_symtab_entry_marked_p): Remove. (lto_symtab_maybe_init_hash_table): Remove. (resolution_guessed_p, set_resolution_guessed): New functions. (lto_symtab_register_decl): Only set resolution info. (lto_symtab_get, lto_symtab_get_resolution): Remove. (lto_symtab_merge): Reorg to work across symtab; do nothing if decls are same. (lto_symtab_resolve_replaceable_p): Reorg to work on symtab. (lto_symtab_resolve_can_prevail_p): Likewise; only real symbols can prevail. (lto_symtab_resolve_symbols): Reorg to work on symtab. (lto_symtab_merge_decls_2): Likewise. (lto_symtab_merge_decls_1): Likewise; add debug dumps. (lto_symtab_merge_decls): Likewise; do not merge at ltrans stage. (lto_symtab_merge_cgraph_nodes_1): Reorg to work on symtab. (lto_symtab_merge_cgraph_nodes): Likewise; do not merge at ltrans stage. (lto_symtab_prevailing_decl): Rewrite to lookup into symtab. * lto-streaer.h (lto_symtab_free): Remove. * lto-cgraph.c (add_references): Cleanup. * varpool.c (varpool_assemble_decl): Skip hard regs. * lto.c (lto_materialize_function): Update confused comment. (read_cgraph_and_symbols): Do not free symtab. From-SVN: r191466
This commit is contained in:
parent
9745abfd1c
commit
b5493fb2fa
|
|
@ -1,3 +1,45 @@
|
||||||
|
2012-09-19 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
* symtab.c (insert_to_assembler_name_hash): Do not insert
|
||||||
|
register vars.
|
||||||
|
(unlink_from_assembler_name_hash): NULL out pointers of unlinked
|
||||||
|
var.
|
||||||
|
(symtab_prevail_in_asm_name_hash): New.
|
||||||
|
(symtab_initialize_asm_name_hash): Break out from ...
|
||||||
|
(symtab_node_for_asm): ... here.
|
||||||
|
(dump_symtab_base): Dump LTO file data.
|
||||||
|
(verify_symtab_base): Register vars are not in symtab.
|
||||||
|
* cgraph.h (symtab_initialize_asm_name_hash,
|
||||||
|
symtab_prevail_in_asm_name_hash): New functions.
|
||||||
|
(symtab_real_symbol_p): New inline.
|
||||||
|
* lto-symtab.c: Do not include gt-lto-symtab.h.
|
||||||
|
(lto_symtab_entry_def): Remove.
|
||||||
|
(lto_symtab_entry_t): Remove.
|
||||||
|
(lto_symtab_identifiers): Remove.
|
||||||
|
(lto_symtab_free): Remove.
|
||||||
|
(lto_symtab_entry_hash): Remove.
|
||||||
|
(lto_symtab_entry_eq): Remove.
|
||||||
|
(lto_symtab_entry_marked_p): Remove.
|
||||||
|
(lto_symtab_maybe_init_hash_table): Remove.
|
||||||
|
(resolution_guessed_p, set_resolution_guessed): New functions.
|
||||||
|
(lto_symtab_register_decl): Only set resolution info.
|
||||||
|
(lto_symtab_get, lto_symtab_get_resolution): Remove.
|
||||||
|
(lto_symtab_merge): Reorg to work across symtab; do nothing if decls
|
||||||
|
are same.
|
||||||
|
(lto_symtab_resolve_replaceable_p): Reorg to work on symtab.
|
||||||
|
(lto_symtab_resolve_can_prevail_p): Likewise; only real symbols can
|
||||||
|
prevail.
|
||||||
|
(lto_symtab_resolve_symbols): Reorg to work on symtab.
|
||||||
|
(lto_symtab_merge_decls_2): Likewise.
|
||||||
|
(lto_symtab_merge_decls_1): Likewise; add debug dumps.
|
||||||
|
(lto_symtab_merge_decls): Likewise; do not merge at ltrans stage.
|
||||||
|
(lto_symtab_merge_cgraph_nodes_1): Reorg to work on symtab.
|
||||||
|
(lto_symtab_merge_cgraph_nodes): Likewise; do not merge at ltrans stage.
|
||||||
|
(lto_symtab_prevailing_decl): Rewrite to lookup into symtab.
|
||||||
|
* lto-streaer.h (lto_symtab_free): Remove.
|
||||||
|
* lto-cgraph.c (add_references): Cleanup.
|
||||||
|
* varpool.c (varpool_assemble_decl): Skip hard regs.
|
||||||
|
|
||||||
2012-09-19 Richard Guenther <rguenther@suse.de>
|
2012-09-19 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
PR other/53316
|
PR other/53316
|
||||||
|
|
|
||||||
25
gcc/cgraph.h
25
gcc/cgraph.h
|
|
@ -704,6 +704,8 @@ bool varpool_for_node_and_aliases (struct varpool_node *,
|
||||||
bool (*) (struct varpool_node *, void *),
|
bool (*) (struct varpool_node *, void *),
|
||||||
void *, bool);
|
void *, bool);
|
||||||
void varpool_add_new_variable (tree);
|
void varpool_add_new_variable (tree);
|
||||||
|
void symtab_initialize_asm_name_hash (void);
|
||||||
|
void symtab_prevail_in_asm_name_hash (symtab_node node);
|
||||||
|
|
||||||
/* Return true when NODE is function. */
|
/* Return true when NODE is function. */
|
||||||
static inline bool
|
static inline bool
|
||||||
|
|
@ -1309,4 +1311,27 @@ cgraph_mark_force_output_node (struct cgraph_node *node)
|
||||||
gcc_checking_assert (!node->global.inlined_to);
|
gcc_checking_assert (!node->global.inlined_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true when the symbol is real symbol, i.e. it is not inline clone
|
||||||
|
or extern function kept around just for inlining. */
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
symtab_real_symbol_p (symtab_node node)
|
||||||
|
{
|
||||||
|
struct cgraph_node *cnode;
|
||||||
|
struct ipa_ref *ref;
|
||||||
|
|
||||||
|
if (!symtab_function_p (node))
|
||||||
|
return true;
|
||||||
|
cnode = cgraph (node);
|
||||||
|
if (cnode->global.inlined_to)
|
||||||
|
return false;
|
||||||
|
if (cnode->abstract_and_needed)
|
||||||
|
return false;
|
||||||
|
/* We keep virtual clones in symtab. */
|
||||||
|
if (!cnode->analyzed
|
||||||
|
|| DECL_EXTERNAL (cnode->symbol.decl))
|
||||||
|
return (cnode->callers
|
||||||
|
|| ipa_ref_list_referring_iterate (&cnode->symbol.ref_list, 0, ref));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif /* GCC_CGRAPH_H */
|
#endif /* GCC_CGRAPH_H */
|
||||||
|
|
|
||||||
|
|
@ -668,10 +668,7 @@ add_references (lto_symtab_encoder_t encoder,
|
||||||
if (symtab_function_p (ref->referred))
|
if (symtab_function_p (ref->referred))
|
||||||
add_node_to (encoder, ipa_ref_node (ref), false);
|
add_node_to (encoder, ipa_ref_node (ref), false);
|
||||||
else
|
else
|
||||||
{
|
lto_symtab_encoder_encode (encoder, ref->referred);
|
||||||
struct varpool_node *vnode = ipa_ref_varpool_node (ref);
|
|
||||||
lto_symtab_encoder_encode (encoder, (symtab_node)vnode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find all symbols we want to stream into given partition and insert them
|
/* Find all symbols we want to stream into given partition and insert them
|
||||||
|
|
|
||||||
|
|
@ -866,7 +866,6 @@ extern void lto_symtab_merge_decls (void);
|
||||||
extern void lto_symtab_merge_cgraph_nodes (void);
|
extern void lto_symtab_merge_cgraph_nodes (void);
|
||||||
extern tree lto_symtab_prevailing_decl (tree decl);
|
extern tree lto_symtab_prevailing_decl (tree decl);
|
||||||
extern enum ld_plugin_symbol_resolution lto_symtab_get_resolution (tree decl);
|
extern enum ld_plugin_symbol_resolution lto_symtab_get_resolution (tree decl);
|
||||||
extern void lto_symtab_free (void);
|
|
||||||
extern GTY(()) VEC(tree,gc) *lto_global_var_decls;
|
extern GTY(()) VEC(tree,gc) *lto_global_var_decls;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
510
gcc/lto-symtab.c
510
gcc/lto-symtab.c
|
|
@ -32,98 +32,19 @@ along with GCC; see the file COPYING3. If not see
|
||||||
/* Vector to keep track of external variables we've seen so far. */
|
/* Vector to keep track of external variables we've seen so far. */
|
||||||
VEC(tree,gc) *lto_global_var_decls;
|
VEC(tree,gc) *lto_global_var_decls;
|
||||||
|
|
||||||
/* Symbol table entry. */
|
/* Return true if the resolution was guessed and not obtained from
|
||||||
|
the file. */
|
||||||
struct GTY(()) lto_symtab_entry_def
|
static inline bool
|
||||||
|
resolution_guessed_p (symtab_node node)
|
||||||
{
|
{
|
||||||
/* The symbol table entry key, an IDENTIFIER. */
|
return node->symbol.aux != NULL;
|
||||||
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. */
|
/* Set guessed flag for NODE. */
|
||||||
|
static inline void
|
||||||
static hashval_t
|
set_resolution_guessed (symtab_node node, bool value)
|
||||||
lto_symtab_entry_hash (const void *p)
|
|
||||||
{
|
{
|
||||||
const struct lto_symtab_entry_def *base =
|
node->symbol.aux = (void *)(size_t)value;
|
||||||
(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)
|
|
||||||
{
|
|
||||||
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_entry_def struct that needs
|
|
||||||
to be marked for GC. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
lto_symtab_entry_marked_p (const void *p)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Registers DECL with the LTO symbol table as having resolution RESOLUTION
|
/* Registers DECL with the LTO symbol table as having resolution RESOLUTION
|
||||||
|
|
@ -134,8 +55,7 @@ lto_symtab_register_decl (tree decl,
|
||||||
ld_plugin_symbol_resolution_t resolution,
|
ld_plugin_symbol_resolution_t resolution,
|
||||||
struct lto_file_decl_data *file_data)
|
struct lto_file_decl_data *file_data)
|
||||||
{
|
{
|
||||||
lto_symtab_entry_t new_entry;
|
symtab_node node;
|
||||||
void **slot;
|
|
||||||
|
|
||||||
/* Check that declarations reaching this function do not have
|
/* Check that declarations reaching this function do not have
|
||||||
properties inconsistent with having external linkage. If any of
|
properties inconsistent with having external linkage. If any of
|
||||||
|
|
@ -153,54 +73,15 @@ lto_symtab_register_decl (tree decl,
|
||||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||||
gcc_assert (!DECL_ABSTRACT (decl));
|
gcc_assert (!DECL_ABSTRACT (decl));
|
||||||
|
|
||||||
new_entry = ggc_alloc_cleared_lto_symtab_entry_def ();
|
node = symtab_get_node (decl);
|
||||||
new_entry->id = (*targetm.asm_out.mangle_assembler_name)
|
if (node)
|
||||||
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
|
{
|
||||||
new_entry->decl = decl;
|
node->symbol.resolution = resolution;
|
||||||
new_entry->resolution = resolution;
|
gcc_assert (node->symbol.lto_file_data == file_data);
|
||||||
new_entry->file_data = file_data;
|
gcc_assert (!resolution_guessed_p (node));
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
|
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
|
||||||
all edges and removing the old node. */
|
all edges and removing the old node. */
|
||||||
|
|
||||||
|
|
@ -277,12 +158,15 @@ lto_varpool_replace_node (struct varpool_node *vnode,
|
||||||
should be emitted. */
|
should be emitted. */
|
||||||
|
|
||||||
static bool
|
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 prevailing_decl = prevailing->symbol.decl;
|
||||||
tree decl = entry->decl;
|
tree decl = entry->symbol.decl;
|
||||||
tree prevailing_type, type;
|
tree prevailing_type, type;
|
||||||
|
|
||||||
|
if (prevailing_decl == decl)
|
||||||
|
return true;
|
||||||
|
|
||||||
/* Merge decl state in both directions, we may still end up using
|
/* Merge decl state in both directions, we may still end up using
|
||||||
the new decl. */
|
the new decl. */
|
||||||
TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
|
TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
|
||||||
|
|
@ -377,17 +261,17 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
|
||||||
entry. */
|
entry. */
|
||||||
|
|
||||||
static bool
|
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)
|
if (DECL_EXTERNAL (e->symbol.decl)
|
||||||
|| DECL_COMDAT (e->decl)
|
|| DECL_COMDAT (e->symbol.decl)
|
||||||
|| DECL_ONE_ONLY (e->decl)
|
|| DECL_ONE_ONLY (e->symbol.decl)
|
||||||
|| DECL_WEAK (e->decl))
|
|| DECL_WEAK (e->symbol.decl))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (TREE_CODE (e->decl) == VAR_DECL)
|
if (TREE_CODE (e->symbol.decl) == VAR_DECL)
|
||||||
return (DECL_COMMON (e->decl)
|
return (DECL_COMMON (e->symbol.decl)
|
||||||
|| (!flag_no_common && !DECL_INITIAL (e->decl)));
|
|| (!flag_no_common && !DECL_INITIAL (e->symbol.decl)));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -395,24 +279,23 @@ lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
|
||||||
/* Return true if the symtab entry E can be the prevailing one. */
|
/* Return true if the symtab entry E can be the prevailing one. */
|
||||||
|
|
||||||
static bool
|
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
|
/* The C++ frontend ends up neither setting TREE_STATIC nor
|
||||||
DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
|
DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
|
||||||
So do not reject !TREE_STATIC here but only DECL_EXTERNAL. */
|
So do not reject !TREE_STATIC here but only DECL_EXTERNAL. */
|
||||||
if (DECL_EXTERNAL (e->decl))
|
if (DECL_EXTERNAL (e->symbol.decl))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* For functions we need a non-discarded body. */
|
/* For functions we need a non-discarded body. */
|
||||||
if (TREE_CODE (e->decl) == FUNCTION_DECL)
|
if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
|
||||||
return (e->node && e->node->analyzed);
|
return (cgraph (e)->analyzed);
|
||||||
|
|
||||||
else if (TREE_CODE (e->decl) == VAR_DECL)
|
else if (TREE_CODE (e->symbol.decl) == VAR_DECL)
|
||||||
{
|
return varpool (e)->finalized;
|
||||||
if (!e->vnode)
|
|
||||||
return false;
|
|
||||||
return e->vnode->finalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
}
|
}
|
||||||
|
|
@ -421,23 +304,18 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
|
||||||
their resolutions. */
|
their resolutions. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lto_symtab_resolve_symbols (void **slot)
|
lto_symtab_resolve_symbols (symtab_node first)
|
||||||
{
|
{
|
||||||
lto_symtab_entry_t e;
|
symtab_node e;
|
||||||
lto_symtab_entry_t prevailing = NULL;
|
symtab_node prevailing = NULL;
|
||||||
|
|
||||||
/* Always set e->node so that edges are updated to reflect decl merging. */
|
/* Always set e->node so that edges are updated to reflect decl merging. */
|
||||||
for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
|
for (e = first; e; e = e->symbol.next_sharing_asm_name)
|
||||||
{
|
if (symtab_real_symbol_p (e)
|
||||||
if (TREE_CODE (e->decl) == FUNCTION_DECL)
|
&& (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
|
||||||
e->node = cgraph_get_node (e->decl);
|
|| e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
|
||||||
else if (TREE_CODE (e->decl) == VAR_DECL)
|
|| e->symbol.resolution == LDPR_PREVAILING_DEF))
|
||||||
e->vnode = varpool_get_node (e->decl);
|
prevailing = e;
|
||||||
if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
||||||
|| e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
|
|
||||||
|| e->resolution == LDPR_PREVAILING_DEF)
|
|
||||||
prevailing = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the chain is already resolved there is nothing else to do. */
|
/* If the chain is already resolved there is nothing else to do. */
|
||||||
if (prevailing)
|
if (prevailing)
|
||||||
|
|
@ -445,26 +323,26 @@ lto_symtab_resolve_symbols (void **slot)
|
||||||
|
|
||||||
/* Find the single non-replaceable prevailing symbol and
|
/* Find the single non-replaceable prevailing symbol and
|
||||||
diagnose ODR violations. */
|
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))
|
if (!lto_symtab_resolve_can_prevail_p (e))
|
||||||
{
|
{
|
||||||
e->resolution = LDPR_RESOLVED_IR;
|
e->symbol.resolution = LDPR_RESOLVED_IR;
|
||||||
e->guessed = true;
|
set_resolution_guessed (e, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set a default resolution - the final prevailing one will get
|
/* Set a default resolution - the final prevailing one will get
|
||||||
adjusted later. */
|
adjusted later. */
|
||||||
e->resolution = LDPR_PREEMPTED_IR;
|
e->symbol.resolution = LDPR_PREEMPTED_IR;
|
||||||
e->guessed = true;
|
set_resolution_guessed (e, true);
|
||||||
if (!lto_symtab_resolve_replaceable_p (e))
|
if (!lto_symtab_resolve_replaceable_p (e))
|
||||||
{
|
{
|
||||||
if (prevailing)
|
if (prevailing)
|
||||||
{
|
{
|
||||||
error_at (DECL_SOURCE_LOCATION (e->decl),
|
error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
|
||||||
"%qD has already been defined", e->decl);
|
"%qD has already been defined", e->symbol.decl);
|
||||||
inform (DECL_SOURCE_LOCATION (prevailing->decl),
|
inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
|
||||||
"previously defined here");
|
"previously defined here");
|
||||||
}
|
}
|
||||||
prevailing = e;
|
prevailing = e;
|
||||||
|
|
@ -474,13 +352,14 @@ lto_symtab_resolve_symbols (void **slot)
|
||||||
goto found;
|
goto found;
|
||||||
|
|
||||||
/* Do a second round choosing one from the replaceable prevailing decls. */
|
/* 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;
|
continue;
|
||||||
|
|
||||||
/* Choose the first function that can prevail as prevailing. */
|
/* 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;
|
prevailing = e;
|
||||||
break;
|
break;
|
||||||
|
|
@ -488,8 +367,8 @@ lto_symtab_resolve_symbols (void **slot)
|
||||||
|
|
||||||
/* From variables that can prevail choose the largest one. */
|
/* From variables that can prevail choose the largest one. */
|
||||||
if (!prevailing
|
if (!prevailing
|
||||||
|| tree_int_cst_lt (DECL_SIZE (prevailing->decl),
|
|| tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl),
|
||||||
DECL_SIZE (e->decl))
|
DECL_SIZE (e->symbol.decl))
|
||||||
/* When variables are equivalent try to chose one that has useful
|
/* When variables are equivalent try to chose one that has useful
|
||||||
DECL_INITIAL. This makes sense for keyed vtables that are
|
DECL_INITIAL. This makes sense for keyed vtables that are
|
||||||
DECL_EXTERNAL but initialized. In units that do not need them
|
DECL_EXTERNAL but initialized. In units that do not need them
|
||||||
|
|
@ -499,11 +378,11 @@ lto_symtab_resolve_symbols (void **slot)
|
||||||
We know that the vtable is keyed outside the LTO unit - otherwise
|
We know that the vtable is keyed outside the LTO unit - otherwise
|
||||||
the keyed instance would prevail. We still can preserve useful
|
the keyed instance would prevail. We still can preserve useful
|
||||||
info in the initializer. */
|
info in the initializer. */
|
||||||
|| (DECL_SIZE (prevailing->decl) == DECL_SIZE (e->decl)
|
|| (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl)
|
||||||
&& (DECL_INITIAL (e->decl)
|
&& (DECL_INITIAL (e->symbol.decl)
|
||||||
&& DECL_INITIAL (e->decl) != error_mark_node)
|
&& DECL_INITIAL (e->symbol.decl) != error_mark_node)
|
||||||
&& (!DECL_INITIAL (prevailing->decl)
|
&& (!DECL_INITIAL (prevailing->symbol.decl)
|
||||||
|| DECL_INITIAL (prevailing->decl) == error_mark_node)))
|
|| DECL_INITIAL (prevailing->symbol.decl) == error_mark_node)))
|
||||||
prevailing = e;
|
prevailing = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -524,8 +403,8 @@ found:
|
||||||
variables IRONLY, which are indeed PREVAILING_DEF in
|
variables IRONLY, which are indeed PREVAILING_DEF in
|
||||||
resolution file. These variables still need manual
|
resolution file. These variables still need manual
|
||||||
externally_visible attribute. */
|
externally_visible attribute. */
|
||||||
prevailing->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
prevailing->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
|
||||||
prevailing->guessed = true;
|
set_resolution_guessed (prevailing, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Merge all decls in the symbol table chain to the prevailing decl and
|
/* Merge all decls in the symbol table chain to the prevailing decl and
|
||||||
|
|
@ -533,24 +412,25 @@ found:
|
||||||
do not issue further diagnostics.*/
|
do not issue further diagnostics.*/
|
||||||
|
|
||||||
static void
|
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;
|
VEC(tree, heap) *mismatches = NULL;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
tree decl;
|
tree decl;
|
||||||
|
|
||||||
/* Nothing to do for a single entry. */
|
/* Nothing to do for a single entry. */
|
||||||
prevailing = (lto_symtab_entry_t) *slot;
|
prevailing = first;
|
||||||
if (!prevailing->next)
|
if (!prevailing->symbol.next_sharing_asm_name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Try to merge each entry with the prevailing one. */
|
/* 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)
|
if (!lto_symtab_merge (prevailing, e)
|
||||||
&& !diagnosed_p)
|
&& !diagnosed_p)
|
||||||
VEC_safe_push (tree, heap, mismatches, e->decl);
|
VEC_safe_push (tree, heap, mismatches, e->symbol.decl);
|
||||||
}
|
}
|
||||||
if (VEC_empty (tree, mismatches))
|
if (VEC_empty (tree, mismatches))
|
||||||
return;
|
return;
|
||||||
|
|
@ -558,13 +438,15 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
|
||||||
/* Diagnose all mismatched re-declarations. */
|
/* Diagnose all mismatched re-declarations. */
|
||||||
FOR_EACH_VEC_ELT (tree, mismatches, i, decl)
|
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,
|
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
|
||||||
"type of %qD does not match original "
|
"type of %qD does not match original "
|
||||||
"declaration", decl);
|
"declaration", decl);
|
||||||
|
|
||||||
else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl))
|
else if ((DECL_USER_ALIGN (prevailing->symbol.decl)
|
||||||
&& DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))
|
&& DECL_USER_ALIGN (decl))
|
||||||
|
&& DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl))
|
||||||
{
|
{
|
||||||
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
|
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
|
||||||
"alignment of %qD is bigger than "
|
"alignment of %qD is bigger than "
|
||||||
|
|
@ -572,7 +454,7 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (diagnosed_p)
|
if (diagnosed_p)
|
||||||
inform (DECL_SOURCE_LOCATION (prevailing->decl),
|
inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
|
||||||
"previously declared here");
|
"previously declared here");
|
||||||
|
|
||||||
VEC_free (tree, heap, mismatches);
|
VEC_free (tree, heap, mismatches);
|
||||||
|
|
@ -580,47 +462,50 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
|
||||||
|
|
||||||
/* Helper to process the decl chain for the symbol table entry *SLOT. */
|
/* Helper to process the decl chain for the symbol table entry *SLOT. */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
lto_symtab_merge_decls_1 (symtab_node first)
|
||||||
{
|
{
|
||||||
lto_symtab_entry_t e, prevailing;
|
symtab_node e, prevailing;
|
||||||
bool diagnosed_p = false;
|
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
|
/* Compute the symbol resolutions. This is a no-op when using the
|
||||||
linker plugin. */
|
linker plugin and resolution was decided by the linker. */
|
||||||
lto_symtab_resolve_symbols (slot);
|
lto_symtab_resolve_symbols (first);
|
||||||
|
|
||||||
/* Find the prevailing decl. */
|
/* Find the prevailing decl. */
|
||||||
for (prevailing = (lto_symtab_entry_t) *slot;
|
for (prevailing = first;
|
||||||
prevailing
|
prevailing
|
||||||
&& prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY
|
&& (!symtab_real_symbol_p (prevailing)
|
||||||
&& prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
|
|| (prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY
|
||||||
&& prevailing->resolution != LDPR_PREVAILING_DEF;
|
&& prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
|
||||||
prevailing = prevailing->next)
|
&& prevailing->symbol.resolution != LDPR_PREVAILING_DEF));
|
||||||
|
prevailing = prevailing->symbol.next_sharing_asm_name)
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Assert it's the only one. */
|
/* Assert it's the only one. */
|
||||||
if (prevailing)
|
if (prevailing)
|
||||||
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 (symtab_real_symbol_p (e)
|
||||||
if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
|
&& (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
|
||||||
|| e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
|
|| e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
|
||||||
|| e->resolution == LDPR_PREVAILING_DEF)
|
|| e->symbol.resolution == LDPR_PREVAILING_DEF))
|
||||||
fatal_error ("multiple prevailing defs for %qE",
|
fatal_error ("multiple prevailing defs for %qE",
|
||||||
DECL_NAME (prevailing->decl));
|
DECL_NAME (prevailing->symbol.decl));
|
||||||
}
|
|
||||||
|
|
||||||
/* If there's not a prevailing symbol yet it's an external reference.
|
/* If there's not a prevailing symbol yet it's an external reference.
|
||||||
Happens a lot during ltrans. Choose the first symbol with a
|
Happens a lot during ltrans. Choose the first symbol with a
|
||||||
cgraph or a varpool node. */
|
cgraph or a varpool node. */
|
||||||
if (!prevailing)
|
if (!prevailing)
|
||||||
{
|
{
|
||||||
prevailing = (lto_symtab_entry_t) *slot;
|
prevailing = first;
|
||||||
/* For functions choose one with a cgraph node. */
|
|
||||||
if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
|
|
||||||
while (!prevailing->node
|
|
||||||
&& prevailing->next)
|
|
||||||
prevailing = prevailing->next;
|
|
||||||
/* For variables chose with a priority variant with vnode
|
/* For variables chose with a priority variant with vnode
|
||||||
attached (i.e. from unit where external declaration of
|
attached (i.e. from unit where external declaration of
|
||||||
variable is actually used).
|
variable is actually used).
|
||||||
|
|
@ -628,49 +513,45 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||||
This is needed for C++ typeinfos, for example in
|
This is needed for C++ typeinfos, for example in
|
||||||
lto/20081204-1 there are typeifos in both units, just
|
lto/20081204-1 there are typeifos in both units, just
|
||||||
one of them do have size. */
|
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)
|
for (e = prevailing->symbol.next_sharing_asm_name;
|
||||||
if ((!prevailing->vnode && e->vnode)
|
e; e = e->symbol.next_sharing_asm_name)
|
||||||
|| ((prevailing->vnode != NULL) == (e->vnode != NULL)
|
if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl))
|
||||||
&& !COMPLETE_TYPE_P (TREE_TYPE (prevailing->decl))
|
&& COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl)))
|
||||||
&& COMPLETE_TYPE_P (TREE_TYPE (e->decl))))
|
|
||||||
prevailing = e;
|
prevailing = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move it first in the list. */
|
symtab_prevail_in_asm_name_hash (prevailing);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record the prevailing variable. */
|
/* Record the prevailing variable. */
|
||||||
if (TREE_CODE (prevailing->decl) == VAR_DECL)
|
if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
|
||||||
VEC_safe_push (tree, gc, lto_global_var_decls, prevailing->decl);
|
VEC_safe_push (tree, gc, lto_global_var_decls,
|
||||||
|
prevailing->symbol.decl);
|
||||||
|
|
||||||
/* Diagnose mismatched objects. */
|
/* 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;
|
continue;
|
||||||
|
|
||||||
switch (TREE_CODE (prevailing->decl))
|
switch (TREE_CODE (prevailing->symbol.decl))
|
||||||
{
|
{
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
gcc_assert (TREE_CODE (e->decl) == FUNCTION_DECL);
|
gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL);
|
||||||
error_at (DECL_SOURCE_LOCATION (e->decl),
|
error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
|
||||||
"variable %qD redeclared as function", prevailing->decl);
|
"variable %qD redeclared as function",
|
||||||
|
prevailing->symbol.decl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FUNCTION_DECL:
|
case FUNCTION_DECL:
|
||||||
gcc_assert (TREE_CODE (e->decl) == VAR_DECL);
|
gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL);
|
||||||
error_at (DECL_SOURCE_LOCATION (e->decl),
|
error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
|
||||||
"function %qD redeclared as variable", prevailing->decl);
|
"function %qD redeclared as variable",
|
||||||
|
prevailing->symbol.decl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -680,12 +561,19 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||||
diagnosed_p = true;
|
diagnosed_p = true;
|
||||||
}
|
}
|
||||||
if (diagnosed_p)
|
if (diagnosed_p)
|
||||||
inform (DECL_SOURCE_LOCATION (prevailing->decl),
|
inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
|
||||||
"previously declared here");
|
"previously declared here");
|
||||||
|
|
||||||
/* Merge the chain to the single prevailing decl and diagnose
|
/* Merge the chain to the single prevailing decl and diagnose
|
||||||
mismatches. */
|
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.
|
/* Store resolution decision into the callgraph.
|
||||||
In LTRANS don't overwrite information we stored into callgraph at
|
In LTRANS don't overwrite information we stored into callgraph at
|
||||||
|
|
@ -698,11 +586,9 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||||
PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP.
|
PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP.
|
||||||
First one would disable some whole program optimizations, while
|
First one would disable some whole program optimizations, while
|
||||||
ther second would imply to many whole program assumptions. */
|
ther second would imply to many whole program assumptions. */
|
||||||
if (prevailing->node && !flag_ltrans && !prevailing->guessed)
|
if (resolution_guessed_p (prevailing))
|
||||||
prevailing->node->symbol.resolution = prevailing->resolution;
|
prevailing->symbol.resolution = LDPR_UNKNOWN;
|
||||||
else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed)
|
return;
|
||||||
prevailing->vnode->symbol.resolution = prevailing->resolution;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve and merge all symbol table chains to a prevailing decl. */
|
/* Resolve and merge all symbol table chains to a prevailing decl. */
|
||||||
|
|
@ -710,50 +596,46 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||||
void
|
void
|
||||||
lto_symtab_merge_decls (void)
|
lto_symtab_merge_decls (void)
|
||||||
{
|
{
|
||||||
lto_symtab_maybe_init_hash_table ();
|
symtab_node node;
|
||||||
htab_traverse (lto_symtab_identifiers, lto_symtab_merge_decls_1, NULL);
|
|
||||||
|
/* 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. */
|
/* Helper to process the decl chain for the symbol table entry *SLOT. */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing)
|
||||||
{
|
{
|
||||||
lto_symtab_entry_t e, prevailing = (lto_symtab_entry_t) *slot;
|
symtab_node e, next;
|
||||||
|
|
||||||
if (!prevailing->next)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Replace the cgraph node of each entry with the prevailing one. */
|
/* 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)
|
next = e->symbol.next_sharing_asm_name;
|
||||||
{
|
|
||||||
/* In case we prevail funcion by an alias, we can run into case
|
if (!symtab_real_symbol_p (e))
|
||||||
that the alias has no cgraph node attached, since it was
|
continue;
|
||||||
previously unused. Create the node. */
|
if (symtab_function_p (e))
|
||||||
if (!prevailing->node)
|
lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
|
||||||
{
|
if (symtab_variable_p (e))
|
||||||
prevailing->node = cgraph_create_node (prevailing->decl);
|
lto_varpool_replace_node (varpool (e), varpool (prevailing));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop all but the prevailing decl from the symtab. */
|
return;
|
||||||
prevailing->next = NULL;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Merge cgraph nodes according to the symbol merging done by
|
/* Merge cgraph nodes according to the symbol merging done by
|
||||||
|
|
@ -762,18 +644,33 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||||
void
|
void
|
||||||
lto_symtab_merge_cgraph_nodes (void)
|
lto_symtab_merge_cgraph_nodes (void)
|
||||||
{
|
{
|
||||||
struct cgraph_node *node;
|
struct cgraph_node *cnode;
|
||||||
struct varpool_node *vnode;
|
struct varpool_node *vnode;
|
||||||
lto_symtab_maybe_init_hash_table ();
|
symtab_node node;
|
||||||
htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
|
|
||||||
|
|
||||||
FOR_EACH_FUNCTION (node)
|
/* Populate assembler name hash. */
|
||||||
if ((node->thunk.thunk_p || node->alias)
|
symtab_initialize_asm_name_hash ();
|
||||||
&& 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)
|
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. */
|
/* Given the decl DECL, return the prevailing decl with the same name. */
|
||||||
|
|
@ -781,7 +678,7 @@ lto_symtab_merge_cgraph_nodes (void)
|
||||||
tree
|
tree
|
||||||
lto_symtab_prevailing_decl (tree decl)
|
lto_symtab_prevailing_decl (tree decl)
|
||||||
{
|
{
|
||||||
lto_symtab_entry_t ret;
|
symtab_node ret;
|
||||||
|
|
||||||
/* Builtins and local symbols are their own prevailing decl. */
|
/* Builtins and local symbols are their own prevailing decl. */
|
||||||
if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
|
if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
|
||||||
|
|
@ -795,12 +692,9 @@ lto_symtab_prevailing_decl (tree decl)
|
||||||
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
|
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
|
||||||
|
|
||||||
/* Walk through the list of candidates and return the one we merged to. */
|
/* Walk through the list of candidates and return the one we merged to. */
|
||||||
ret = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
|
ret = symtab_node_for_asm (DECL_ASSEMBLER_NAME (decl));
|
||||||
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return NULL_TREE;
|
return decl;
|
||||||
|
|
||||||
return ret->decl;
|
return ret->symbol.decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "gt-lto-symtab.h"
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2012-09-19 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
* lto.c (lto_materialize_function): Update confused comment.
|
||||||
|
(read_cgraph_and_symbols): Do not free symtab.
|
||||||
|
|
||||||
2012-09-12 Jan Hubicka <jh@suse.cz>
|
2012-09-12 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
* lto.c (do_whole_program_analysis): Care timevars, statistics and
|
* lto.c (do_whole_program_analysis): Care timevars, statistics and
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ lto_materialize_function (struct cgraph_node *node)
|
||||||
and also functions that are needed to produce virtual clones. */
|
and also functions that are needed to produce virtual clones. */
|
||||||
if (cgraph_function_with_gimple_body_p (node) || has_analyzed_clone_p (node))
|
if (cgraph_function_with_gimple_body_p (node) || has_analyzed_clone_p (node))
|
||||||
{
|
{
|
||||||
/* Clones and thunks don't need to be read. */
|
/* Clones don't need to be read. */
|
||||||
if (node->clone_of)
|
if (node->clone_of)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -3006,7 +3006,6 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
|
||||||
VEC_safe_push (ipa_opt_pass, heap,
|
VEC_safe_push (ipa_opt_pass, heap,
|
||||||
node->ipa_transforms_to_apply,
|
node->ipa_transforms_to_apply,
|
||||||
(ipa_opt_pass)&pass_ipa_inline);
|
(ipa_opt_pass)&pass_ipa_inline);
|
||||||
lto_symtab_free ();
|
|
||||||
|
|
||||||
timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
|
timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
|
||||||
|
|
||||||
|
|
@ -3035,7 +3034,6 @@ materialize_cgraph (void)
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
flag_wpa ? "Materializing decls:" : "Reading function bodies:");
|
flag_wpa ? "Materializing decls:" : "Reading function bodies:");
|
||||||
|
|
||||||
|
|
||||||
/* Now that we have input the cgraph, we need to clear all of the aux
|
/* Now that we have input the cgraph, we need to clear all of the aux
|
||||||
nodes and read the functions if we are not running in WPA mode. */
|
nodes and read the functions if we are not running in WPA mode. */
|
||||||
timevar_push (TV_IPA_LTO_GIMPLE_IN);
|
timevar_push (TV_IPA_LTO_GIMPLE_IN);
|
||||||
|
|
|
||||||
47
gcc/symtab.c
47
gcc/symtab.c
|
|
@ -104,6 +104,8 @@ eq_assembler_name (const void *p1, const void *p2)
|
||||||
static void
|
static void
|
||||||
insert_to_assembler_name_hash (symtab_node node)
|
insert_to_assembler_name_hash (symtab_node node)
|
||||||
{
|
{
|
||||||
|
if (symtab_variable_p (node) && DECL_HARD_REGISTER (node->symbol.decl))
|
||||||
|
return;
|
||||||
gcc_checking_assert (!node->symbol.previous_sharing_asm_name
|
gcc_checking_assert (!node->symbol.previous_sharing_asm_name
|
||||||
&& !node->symbol.next_sharing_asm_name);
|
&& !node->symbol.next_sharing_asm_name);
|
||||||
if (assembler_name_hash)
|
if (assembler_name_hash)
|
||||||
|
|
@ -151,9 +153,20 @@ unlink_from_assembler_name_hash (symtab_node node)
|
||||||
else
|
else
|
||||||
*slot = node->symbol.next_sharing_asm_name;
|
*slot = node->symbol.next_sharing_asm_name;
|
||||||
}
|
}
|
||||||
|
node->symbol.next_sharing_asm_name = NULL;
|
||||||
|
node->symbol.previous_sharing_asm_name = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Arrange node to be first in its entry of assembler_name_hash. */
|
||||||
|
|
||||||
|
void
|
||||||
|
symtab_prevail_in_asm_name_hash (symtab_node node)
|
||||||
|
{
|
||||||
|
unlink_from_assembler_name_hash (node);
|
||||||
|
insert_to_assembler_name_hash (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Add node into symbol table. This function is not used directly, but via
|
/* Add node into symbol table. This function is not used directly, but via
|
||||||
cgraph/varpool node creation routines. */
|
cgraph/varpool node creation routines. */
|
||||||
|
|
@ -287,6 +300,22 @@ symtab_remove_node (symtab_node node)
|
||||||
varpool_remove_node (varpool (node));
|
varpool_remove_node (varpool (node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initalize asm name hash unless. */
|
||||||
|
|
||||||
|
void
|
||||||
|
symtab_initialize_asm_name_hash (void)
|
||||||
|
{
|
||||||
|
symtab_node node;
|
||||||
|
if (!assembler_name_hash)
|
||||||
|
{
|
||||||
|
assembler_name_hash =
|
||||||
|
htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
|
||||||
|
NULL);
|
||||||
|
FOR_EACH_SYMBOL (node)
|
||||||
|
insert_to_assembler_name_hash (node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
|
/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
|
||||||
Return NULL if there's no such node. */
|
Return NULL if there's no such node. */
|
||||||
|
|
||||||
|
|
@ -296,15 +325,7 @@ symtab_node_for_asm (const_tree asmname)
|
||||||
symtab_node node;
|
symtab_node node;
|
||||||
void **slot;
|
void **slot;
|
||||||
|
|
||||||
if (!assembler_name_hash)
|
symtab_initialize_asm_name_hash ();
|
||||||
{
|
|
||||||
assembler_name_hash =
|
|
||||||
htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
|
|
||||||
NULL);
|
|
||||||
FOR_EACH_SYMBOL (node)
|
|
||||||
insert_to_assembler_name_hash (node);
|
|
||||||
}
|
|
||||||
|
|
||||||
slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
|
slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
|
||||||
decl_assembler_name_hash (asmname),
|
decl_assembler_name_hash (asmname),
|
||||||
NO_INSERT);
|
NO_INSERT);
|
||||||
|
|
@ -507,6 +528,9 @@ dump_symtab_base (FILE *f, symtab_node node)
|
||||||
ipa_dump_references (f, &node->symbol.ref_list);
|
ipa_dump_references (f, &node->symbol.ref_list);
|
||||||
fprintf (f, " Referring: ");
|
fprintf (f, " Referring: ");
|
||||||
ipa_dump_referring (f, &node->symbol.ref_list);
|
ipa_dump_referring (f, &node->symbol.ref_list);
|
||||||
|
if (node->symbol.lto_file_data)
|
||||||
|
fprintf (f, " Read from file: %s\n",
|
||||||
|
node->symbol.lto_file_data->file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump symtab node. */
|
/* Dump symtab node. */
|
||||||
|
|
@ -597,7 +621,8 @@ verify_symtab_base (symtab_node node)
|
||||||
break;
|
break;
|
||||||
hashed_node = hashed_node->symbol.next_sharing_asm_name;
|
hashed_node = hashed_node->symbol.next_sharing_asm_name;
|
||||||
}
|
}
|
||||||
if (!hashed_node)
|
if (!hashed_node
|
||||||
|
&& !(symtab_variable_p (node) || DECL_HARD_REGISTER (node->symbol.decl)))
|
||||||
{
|
{
|
||||||
error ("node not found in symtab assembler name hash");
|
error ("node not found in symtab assembler name hash");
|
||||||
error_found = true;
|
error_found = true;
|
||||||
|
|
@ -733,6 +758,8 @@ symtab_make_decl_local (tree decl)
|
||||||
DECL_COMDAT_GROUP (decl) = 0;
|
DECL_COMDAT_GROUP (decl) = 0;
|
||||||
DECL_WEAK (decl) = 0;
|
DECL_WEAK (decl) = 0;
|
||||||
DECL_EXTERNAL (decl) = 0;
|
DECL_EXTERNAL (decl) = 0;
|
||||||
|
DECL_VISIBILITY_SPECIFIED (decl) = 0;
|
||||||
|
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
|
||||||
TREE_PUBLIC (decl) = 0;
|
TREE_PUBLIC (decl) = 0;
|
||||||
DECL_VISIBILITY_SPECIFIED (decl) = 0;
|
DECL_VISIBILITY_SPECIFIED (decl) = 0;
|
||||||
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
|
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
|
||||||
|
|
|
||||||
|
|
@ -301,6 +301,10 @@ varpool_assemble_decl (struct varpool_node *node)
|
||||||
&& !targetm.have_tls)
|
&& !targetm.have_tls)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Hard register vars do not need to be output. */
|
||||||
|
if (DECL_HARD_REGISTER (decl))
|
||||||
|
return false;
|
||||||
|
|
||||||
gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
|
gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
|
||||||
&& TREE_CODE (decl) == VAR_DECL
|
&& TREE_CODE (decl) == VAR_DECL
|
||||||
&& !DECL_HAS_VALUE_EXPR_P (decl));
|
&& !DECL_HAS_VALUE_EXPR_P (decl));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue