diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/lto/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/lto/lto-partition.c | 152 | ||||
-rw-r--r-- | gcc/lto/lto-partition.h | 1 | ||||
-rw-r--r-- | gcc/lto/lto.c | 54 | ||||
-rw-r--r-- | gcc/symtab.c | 17 |
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; } |