mirror of git://gcc.gnu.org/git/gcc.git
Jan Hubicka <jh@suse.cz>
Richard Biener <rguenther@suse.de> PR lto/54095 * symtab.c (symtab_make_decl_local): Do not add private names. * lto.c (lto_register_var_decl_in_symtab): Don't do renaming. (lto_register_var_decl_in_symtab): Likewise. (lto_main): Promote statics. * lto-partition.c (privatize_symbol_name): New function. (promote_symbol): Use it. (may_need_named_section_p): New predicate. (rename_statics): New functions. (lto_promote_cross_file_statics): Simplify; do renaming. (lto_promote_statics_nonwpa): New function. * lto-partition.h (lto_promote_statics_nonwpa): New function. Co-Authored-By: Richard Biener <rguenther@suse.de> From-SVN: r198741
This commit is contained in:
parent
c3167b004d
commit
64cfa6c0db
|
|
@ -1,3 +1,9 @@
|
|||
2013-05-09 Jan Hubicka <jh@suse.cz>
|
||||
Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR lto/54095
|
||||
* symtab.c (symtab_make_decl_local): Do not add private names.
|
||||
|
||||
2013-05-09 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR lto/54095
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
2013-05-09 Jan Hubicka <jh@suse.cz>
|
||||
Richard Biener <rguenther@suse.de>
|
||||
|
||||
* lto.c (lto_register_var_decl_in_symtab): Don't do renaming.
|
||||
(lto_register_var_decl_in_symtab): Likewise.
|
||||
(lto_main): Promote statics.
|
||||
* lto-partition.c (privatize_symbol_name): New function.
|
||||
(promote_symbol): Use it.
|
||||
(may_need_named_section_p): New predicate.
|
||||
(rename_statics): New functions.
|
||||
(lto_promote_cross_file_statics): Simplify; do renaming.
|
||||
(lto_promote_statics_nonwpa): New function.
|
||||
* lto-partition.h (lto_promote_statics_nonwpa): New function.
|
||||
|
||||
2013-02-08 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR lto/56231
|
||||
|
|
|
|||
|
|
@ -755,6 +755,56 @@ lto_balanced_map (void)
|
|||
free (order);
|
||||
}
|
||||
|
||||
/* Mangle NODE symbol name into a local name.
|
||||
This is necessary to do
|
||||
1) if two or more static vars of same assembler name
|
||||
are merged into single ltrans unit.
|
||||
2) if prevoiusly static var was promoted hidden to avoid possible conflict
|
||||
with symbols defined out of the LTO world.
|
||||
*/
|
||||
|
||||
static void
|
||||
privatize_symbol_name (symtab_node node)
|
||||
{
|
||||
tree decl = node->symbol.decl;
|
||||
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
char *label;
|
||||
|
||||
/* Our renaming machinery do not handle more than one change of assembler name.
|
||||
We should not need more than one anyway. */
|
||||
if (node->symbol.lto_file_data
|
||||
&& lto_get_decl_name_mapping (node->symbol.lto_file_data, name) != name)
|
||||
{
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"Not privatizing symbol name: %s. It privatized already.\n",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
/* Avoid mangling of already mangled clones.
|
||||
??? should have a flag whether a symbol has a 'private' name already,
|
||||
since we produce some symbols like that i.e. for global constructors
|
||||
that are not really clones. */
|
||||
if (node->symbol.unique_name)
|
||||
{
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"Not privatizing symbol name: %s. Has unique name.\n",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
|
||||
change_decl_assembler_name (decl, clone_function_name (decl, "lto_priv"));
|
||||
if (node->symbol.lto_file_data)
|
||||
lto_record_renamed_decl (node->symbol.lto_file_data, name,
|
||||
IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (decl)));
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"Privatizing symbol name: %s -> %s\n",
|
||||
name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
|
||||
}
|
||||
|
||||
/* Promote variable VNODE to be static. */
|
||||
|
||||
static void
|
||||
|
|
@ -768,6 +818,9 @@ promote_symbol (symtab_node node)
|
|||
|
||||
gcc_checking_assert (!TREE_PUBLIC (node->symbol.decl)
|
||||
&& !DECL_EXTERNAL (node->symbol.decl));
|
||||
/* Be sure that newly public symbol does not conflict with anything already
|
||||
defined by the non-LTO part. */
|
||||
privatize_symbol_name (node);
|
||||
TREE_PUBLIC (node->symbol.decl) = 1;
|
||||
DECL_VISIBILITY (node->symbol.decl) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (node->symbol.decl) = true;
|
||||
|
|
@ -776,6 +829,85 @@ promote_symbol (symtab_node node)
|
|||
"Promoting as hidden: %s\n", symtab_node_name (node));
|
||||
}
|
||||
|
||||
/* Return true if NODE needs named section even if it won't land in the partition
|
||||
symbol table.
|
||||
FIXME: we should really not use named sections for inline clones and master clones. */
|
||||
|
||||
static bool
|
||||
may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node)
|
||||
{
|
||||
struct cgraph_node *cnode = dyn_cast <cgraph_node> (node);
|
||||
if (!cnode)
|
||||
return false;
|
||||
if (symtab_real_symbol_p (node))
|
||||
return false;
|
||||
if (!cnode->global.inlined_to && !cnode->clones)
|
||||
return false;
|
||||
return (!encoder
|
||||
|| (lto_symtab_encoder_lookup (encoder, node) != LCC_NOT_FOUND
|
||||
&& lto_symtab_encoder_encode_body_p (encoder,
|
||||
cnode)));
|
||||
}
|
||||
|
||||
/* If NODE represents a static variable. See if there are other variables
|
||||
of the same name in partition ENCODER (or in whole compilation unit if
|
||||
ENCODER is NULL) and if so, mangle the statics. Always mangle all
|
||||
conflicting statics, so we reduce changes of silently miscompiling
|
||||
asm statemnets refering to them by symbol name. */
|
||||
|
||||
static void
|
||||
rename_statics (lto_symtab_encoder_t encoder, symtab_node node)
|
||||
{
|
||||
tree decl = node->symbol.decl;
|
||||
symtab_node s;
|
||||
tree name = DECL_ASSEMBLER_NAME (decl);
|
||||
|
||||
/* See if this is static symbol. */
|
||||
if ((node->symbol.externally_visible
|
||||
/* FIXME: externally_visible is somewhat illogically not set for
|
||||
external symbols (i.e. those not defined). Remove this test
|
||||
once this is fixed. */
|
||||
|| DECL_EXTERNAL (node->symbol.decl)
|
||||
|| !symtab_real_symbol_p (node))
|
||||
&& !may_need_named_section_p (encoder, node))
|
||||
return;
|
||||
|
||||
/* Now walk symbols sharing the same name and see if there are any conflicts.
|
||||
(all types of symbols counts here, since we can not have static of the
|
||||
same name as external or public symbol.) */
|
||||
for (s = symtab_node_for_asm (name);
|
||||
s; s = s->symbol.next_sharing_asm_name)
|
||||
if ((symtab_real_symbol_p (s) || may_need_named_section_p (encoder, s))
|
||||
&& s->symbol.decl != node->symbol.decl
|
||||
&& (!encoder
|
||||
|| lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND))
|
||||
break;
|
||||
|
||||
/* OK, no confict, so we have nothing to do. */
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"Renaming statics with asm name: %s\n", symtab_node_name (node));
|
||||
|
||||
/* Assign every symbol in the set that shares the same ASM name an unique
|
||||
mangled name. */
|
||||
for (s = symtab_node_for_asm (name); s;)
|
||||
if (!s->symbol.externally_visible
|
||||
&& ((symtab_real_symbol_p (s)
|
||||
&& !DECL_EXTERNAL (node->symbol.decl)
|
||||
&& !TREE_PUBLIC (node->symbol.decl))
|
||||
|| may_need_named_section_p (encoder, s))
|
||||
&& (!encoder
|
||||
|| lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND))
|
||||
{
|
||||
privatize_symbol_name (s);
|
||||
/* Re-start from beggining since we do not know how many symbols changed a name. */
|
||||
s = symtab_node_for_asm (name);
|
||||
}
|
||||
else s = s->symbol.next_sharing_asm_name;
|
||||
}
|
||||
|
||||
/* Find out all static decls that need to be promoted to global because
|
||||
of cross file sharing. This function must be run in the WPA mode after
|
||||
|
|
@ -801,16 +933,17 @@ lto_promote_cross_file_statics (void)
|
|||
for (i = 0; i < n_sets; i++)
|
||||
{
|
||||
lto_symtab_encoder_iterator lsei;
|
||||
lto_symtab_encoder_t encoder;
|
||||
ltrans_partition part
|
||||
= ltrans_partitions[i];
|
||||
lto_symtab_encoder_t encoder = ltrans_partitions[i]->encoder;
|
||||
|
||||
encoder = part->encoder;
|
||||
for (lsei = lsei_start (encoder); !lsei_end_p (lsei);
|
||||
lsei_next (&lsei))
|
||||
{
|
||||
symtab_node node = lsei_node (lsei);
|
||||
|
||||
/* If symbol is static, rename it if its assembler name clash with
|
||||
anything else in this unit. */
|
||||
rename_statics (encoder, node);
|
||||
|
||||
/* No need to promote if symbol already is externally visible ... */
|
||||
if (node->symbol.externally_visible
|
||||
/* ... or if it is part of current partition ... */
|
||||
|
|
@ -824,3 +957,14 @@ lto_promote_cross_file_statics (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rename statics in the whole unit in the case that
|
||||
we do -flto-partition=none. */
|
||||
|
||||
void
|
||||
lto_promote_statics_nonwpa (void)
|
||||
{
|
||||
symtab_node node;
|
||||
FOR_EACH_SYMBOL (node)
|
||||
rename_statics (NULL, node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,3 +37,4 @@ void lto_max_map (void);
|
|||
void lto_balanced_map (void);
|
||||
void lto_promote_cross_file_statics (void);
|
||||
void free_ltrans_partitions (void);
|
||||
void lto_promote_statics_nonwpa (void);
|
||||
|
|
|
|||
|
|
@ -1748,23 +1748,11 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl)
|
|||
{
|
||||
tree context;
|
||||
|
||||
/* Variable has file scope, not local. Need to ensure static variables
|
||||
between different files don't clash unexpectedly. */
|
||||
/* Variable has file scope, not local. */
|
||||
if (!TREE_PUBLIC (decl)
|
||||
&& !((context = decl_function_context (decl))
|
||||
&& auto_var_in_fn_p (decl, context)))
|
||||
{
|
||||
/* ??? We normally pre-mangle names before we serialize them
|
||||
out. Here, in lto1, we do not know the language, and
|
||||
thus cannot do the mangling again. Instead, we just
|
||||
append a suffix to the mangled name. The resulting name,
|
||||
however, is not a properly-formed mangled name, and will
|
||||
confuse any attempt to unmangle it. */
|
||||
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
char *label;
|
||||
|
||||
ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
|
||||
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
|
||||
rest_of_decl_compilation (decl, 1, 0);
|
||||
}
|
||||
|
||||
|
|
@ -1788,44 +1776,6 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl)
|
|||
static void
|
||||
lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl)
|
||||
{
|
||||
/* Need to ensure static entities between different files
|
||||
don't clash unexpectedly. */
|
||||
if (!TREE_PUBLIC (decl))
|
||||
{
|
||||
/* We must not use the DECL_ASSEMBLER_NAME macro here, as it
|
||||
may set the assembler name where it was previously empty. */
|
||||
tree old_assembler_name = decl->decl_with_vis.assembler_name;
|
||||
|
||||
/* FIXME lto: We normally pre-mangle names before we serialize
|
||||
them out. Here, in lto1, we do not know the language, and
|
||||
thus cannot do the mangling again. Instead, we just append a
|
||||
suffix to the mangled name. The resulting name, however, is
|
||||
not a properly-formed mangled name, and will confuse any
|
||||
attempt to unmangle it. */
|
||||
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
char *label;
|
||||
|
||||
ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
|
||||
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
|
||||
|
||||
/* We may arrive here with the old assembler name not set
|
||||
if the function body is not needed, e.g., it has been
|
||||
inlined away and does not appear in the cgraph. */
|
||||
if (old_assembler_name)
|
||||
{
|
||||
tree new_assembler_name = DECL_ASSEMBLER_NAME (decl);
|
||||
|
||||
/* Make the original assembler name available for later use.
|
||||
We may have used it to indicate the section within its
|
||||
object file where the function body may be found.
|
||||
FIXME lto: Find a better way to maintain the function decl
|
||||
to body section mapping so we don't need this hack. */
|
||||
lto_record_renamed_decl (data_in->file_data,
|
||||
IDENTIFIER_POINTER (old_assembler_name),
|
||||
IDENTIFIER_POINTER (new_assembler_name));
|
||||
}
|
||||
}
|
||||
|
||||
/* If this variable has already been declared, queue the
|
||||
declaration for merging. */
|
||||
if (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl))
|
||||
|
|
@ -3396,6 +3346,8 @@ lto_main (void)
|
|||
timevar_start (TV_PHASE_OPT_GEN);
|
||||
|
||||
materialize_cgraph ();
|
||||
if (!flag_ltrans)
|
||||
lto_promote_statics_nonwpa ();
|
||||
|
||||
/* Let the middle end know that we have read and merged all of
|
||||
the input files. */
|
||||
|
|
|
|||
17
gcc/symtab.c
17
gcc/symtab.c
|
|
@ -756,23 +756,6 @@ symtab_make_decl_local (tree decl)
|
|||
|
||||
if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl))
|
||||
{
|
||||
/* It is possible that we are linking against library defining same COMDAT
|
||||
function. To avoid conflict we need to rename our local name of the
|
||||
function just in the case WHOPR partitioning decide to make it hidden
|
||||
to avoid cross partition references. */
|
||||
if (flag_wpa)
|
||||
{
|
||||
const char *old_name;
|
||||
symtab_node node = symtab_get_node (decl);
|
||||
old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
change_decl_assembler_name (decl,
|
||||
clone_function_name (decl, "local"));
|
||||
if (node->symbol.lto_file_data)
|
||||
lto_record_renamed_decl (node->symbol.lto_file_data,
|
||||
old_name,
|
||||
IDENTIFIER_POINTER
|
||||
(DECL_ASSEMBLER_NAME (decl)));
|
||||
}
|
||||
DECL_SECTION_NAME (decl) = 0;
|
||||
DECL_COMDAT (decl) = 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue