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:
Jan Hubicka 2012-09-19 12:01:56 +02:00 committed by Jan Hubicka
parent 9745abfd1c
commit b5493fb2fa
9 changed files with 317 additions and 326 deletions

View file

@ -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>
PR other/53316

View file

@ -704,6 +704,8 @@ bool varpool_for_node_and_aliases (struct varpool_node *,
bool (*) (struct varpool_node *, void *),
void *, bool);
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. */
static inline bool
@ -1309,4 +1311,27 @@ cgraph_mark_force_output_node (struct cgraph_node *node)
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 */

View file

@ -668,10 +668,7 @@ add_references (lto_symtab_encoder_t encoder,
if (symtab_function_p (ref->referred))
add_node_to (encoder, ipa_ref_node (ref), false);
else
{
struct varpool_node *vnode = ipa_ref_varpool_node (ref);
lto_symtab_encoder_encode (encoder, (symtab_node)vnode);
}
lto_symtab_encoder_encode (encoder, ref->referred);
}
/* Find all symbols we want to stream into given partition and insert them

View file

@ -866,7 +866,6 @@ extern void lto_symtab_merge_decls (void);
extern void lto_symtab_merge_cgraph_nodes (void);
extern tree lto_symtab_prevailing_decl (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;

View file

@ -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. */
VEC(tree,gc) *lto_global_var_decls;
/* Symbol table entry. */
struct GTY(()) lto_symtab_entry_def
/* Return true if the resolution was guessed and not obtained from
the file. */
static inline bool
resolution_guessed_p (symtab_node node)
{
/* 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 node->symbol.aux != 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)
/* 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;
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);
node->symbol.aux = (void *)(size_t)value;
}
/* 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,
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
@ -153,54 +73,15 @@ lto_symtab_register_decl (tree decl,
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;
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));
}
}
/* 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
all edges and removing the old node. */
@ -277,12 +158,15 @@ lto_varpool_replace_node (struct varpool_node *vnode,
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);
@ -377,17 +261,17 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
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;
}
@ -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. */
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 ();
}
@ -421,23 +304,18 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
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)
@ -445,26 +323,26 @@ lto_symtab_resolve_symbols (void **slot)
/* 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;
@ -474,13 +352,14 @@ lto_symtab_resolve_symbols (void **slot)
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;
@ -488,8 +367,8 @@ lto_symtab_resolve_symbols (void **slot)
/* 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
@ -499,11 +378,11 @@ lto_symtab_resolve_symbols (void **slot)
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;
}
@ -524,8 +403,8 @@ found:
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
@ -533,24 +412,25 @@ found:
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;
@ -558,13 +438,15 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
/* 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 "
@ -572,7 +454,7 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
}
}
if (diagnosed_p)
inform (DECL_SOURCE_LOCATION (prevailing->decl),
inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
"previously declared here");
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. */
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).
@ -628,49 +513,45 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
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:
@ -680,12 +561,19 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
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
@ -698,11 +586,9 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
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. */
@ -710,50 +596,46 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
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;
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));
}
/* Drop all but the prevailing decl from the symtab. */
prevailing->next = NULL;
return 1;
return;
}
/* 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
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;
FOR_EACH_FUNCTION (node)
if ((node->thunk.thunk_p || node->alias)
&& node->thunk.alias)
node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
/* Populate assembler name hash. */
symtab_initialize_asm_name_hash ();
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. */
@ -781,7 +678,7 @@ lto_symtab_merge_cgraph_nodes (void)
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))
@ -795,12 +692,9 @@ 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 ((*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"

View file

@ -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>
* lto.c (do_whole_program_analysis): Care timevars, statistics and

View file

@ -198,7 +198,7 @@ lto_materialize_function (struct cgraph_node *node)
and also functions that are needed to produce virtual clones. */
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)
return;
@ -3006,7 +3006,6 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
VEC_safe_push (ipa_opt_pass, heap,
node->ipa_transforms_to_apply,
(ipa_opt_pass)&pass_ipa_inline);
lto_symtab_free ();
timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
@ -3035,7 +3034,6 @@ materialize_cgraph (void)
fprintf (stderr,
flag_wpa ? "Materializing decls:" : "Reading function bodies:");
/* 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. */
timevar_push (TV_IPA_LTO_GIMPLE_IN);

View file

@ -104,6 +104,8 @@ eq_assembler_name (const void *p1, const void *p2)
static void
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
&& !node->symbol.next_sharing_asm_name);
if (assembler_name_hash)
@ -151,9 +153,20 @@ unlink_from_assembler_name_hash (symtab_node node)
else
*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
cgraph/varpool node creation routines. */
@ -287,6 +300,22 @@ symtab_remove_node (symtab_node 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 NULL if there's no such node. */
@ -296,15 +325,7 @@ symtab_node_for_asm (const_tree asmname)
symtab_node node;
void **slot;
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);
}
symtab_initialize_asm_name_hash ();
slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
decl_assembler_name_hash (asmname),
NO_INSERT);
@ -507,6 +528,9 @@ dump_symtab_base (FILE *f, symtab_node node)
ipa_dump_references (f, &node->symbol.ref_list);
fprintf (f, " Referring: ");
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. */
@ -597,7 +621,8 @@ verify_symtab_base (symtab_node node)
break;
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_found = true;
@ -733,6 +758,8 @@ symtab_make_decl_local (tree decl)
DECL_COMDAT_GROUP (decl) = 0;
DECL_WEAK (decl) = 0;
DECL_EXTERNAL (decl) = 0;
DECL_VISIBILITY_SPECIFIED (decl) = 0;
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
TREE_PUBLIC (decl) = 0;
DECL_VISIBILITY_SPECIFIED (decl) = 0;
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;

View file

@ -301,6 +301,10 @@ varpool_assemble_decl (struct varpool_node *node)
&& !targetm.have_tls)
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)
&& TREE_CODE (decl) == VAR_DECL
&& !DECL_HAS_VALUE_EXPR_P (decl));