aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/lto/ChangeLog14
-rw-r--r--gcc/lto/lto-partition.c152
-rw-r--r--gcc/lto/lto-partition.h1
-rw-r--r--gcc/lto/lto.c54
-rw-r--r--gcc/symtab.c17
6 files changed, 172 insertions, 72 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 94ed169..d22b31d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,10 @@
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
* symtab.c (insert_to_assembler_name_hash): Handle clones.
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index e3530da..8732069 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -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
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 833d926..652272a 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -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);
+}
diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
index cf5650f..73c131f 100644
--- a/gcc/lto/lto-partition.h
+++ b/gcc/lto/lto-partition.h
@@ -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);
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 52442f9..0943335 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -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. */
diff --git a/gcc/symtab.c b/gcc/symtab.c
index a474bfe..56f0de9 100644
--- a/gcc/symtab.c
+++ b/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;
}