* cgraph.h (clone_function_name_1): Declare. * cgraphclones.c (clone_function_name_1): New function. (clone_function_name): Use it. * lto-partition.c: Include "stringpool.h". (must_not_rename, maybe_rewrite_identifier, validize_symbol_for_target): New static functions. (privatize_symbol_name): Use must_not_rename. (promote_symbol): Call validize_symbol_for_target. (lto_promote_cross_file_statics): Likewise. (lto_promote_statics_nonwpa): Likewise. --- gcc/cgraph.h.jj 2015-02-16 11:19:03.474984223 +0100 +++ gcc/cgraph.h 2015-02-17 13:54:00.413964133 +0100 @@ -2206,6 +2206,7 @@ basic_block init_lowered_empty_function /* In cgraphclones.c */ +tree clone_function_name_1 (const char *, const char *); tree clone_function_name (tree decl, const char *); void tree_function_versioning (tree, tree, vec *, --- gcc/cgraphclones.c.jj 2015-02-17 10:07:53.208582797 +0100 +++ gcc/cgraphclones.c 2015-02-17 13:54:00.413964133 +0100 @@ -533,19 +533,19 @@ cgraph_node::create_clone (tree decl, gc return new_node; } -/* Return a new assembler name for a clone of DECL with SUFFIX. */ - static GTY(()) unsigned int clone_fn_id_num; +/* Return a new assembler name for a clone with SUFFIX of a decl named + NAME. */ + tree -clone_function_name (tree decl, const char *suffix) +clone_function_name_1 (const char *name, const char *suffix) { - tree name = DECL_ASSEMBLER_NAME (decl); - size_t len = IDENTIFIER_LENGTH (name); + size_t len = strlen (name); char *tmp_name, *prefix; prefix = XALLOCAVEC (char, len + strlen (suffix) + 2); - memcpy (prefix, IDENTIFIER_POINTER (name), len); + memcpy (prefix, name, len); strcpy (prefix + len + 1, suffix); #ifndef NO_DOT_IN_LABEL prefix[len] = '.'; @@ -558,6 +558,16 @@ clone_function_name (tree decl, const ch return get_identifier (tmp_name); } +/* Return a new assembler name for a clone of DECL with SUFFIX. */ + +tree +clone_function_name (tree decl, const char *suffix) +{ + tree name = DECL_ASSEMBLER_NAME (decl); + return clone_function_name_1 (IDENTIFIER_POINTER (name), suffix); +} + + /* Create callgraph node clone with new declaration. The actual body will be copied later at compilation stage. --- gcc/lto/lto-partition.c.jj 2015-01-15 14:05:08.706092596 +0100 +++ gcc/lto/lto-partition.c 2015-02-17 14:01:13.182718693 +0100 @@ -57,6 +57,7 @@ along with GCC; see the file COPYING3. #include "ipa-inline.h" #include "ipa-utils.h" #include "lto-partition.h" +#include "stringpool.h" vec ltrans_partitions; @@ -783,29 +784,11 @@ lto_balanced_map (int n_lto_partitions) 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. -*/ - +/* Return true if we must not change the name of the NODE. The name as + extracted from the corresponding decl should be passed in NAME. */ static bool -privatize_symbol_name (symtab_node *node) +must_not_rename (symtab_node *node, const char *name) { - tree decl = node->decl; - cgraph_node *cnode = dyn_cast (node); - const char *name; - - /* If we want to privatize instrumentation clone - then we need to change original function name - which is used via transparent alias chain. */ - if (cnode && cnode->instrumentation_clone) - decl = cnode->orig_decl; - - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - /* Our renaming machinery do not handle more than one change of assembler name. We should not need more than one anyway. */ if (node->lto_file_data @@ -813,9 +796,9 @@ privatize_symbol_name (symtab_node *node { if (symtab->dump_file) fprintf (symtab->dump_file, - "Not privatizing symbol name: %s. It privatized already.\n", - name); - return false; + "Not privatizing symbol name: %s. It privatized already.\n", + name); + return true; } /* Avoid mangling of already mangled clones. ??? should have a flag whether a symbol has a 'private' name already, @@ -825,18 +808,108 @@ privatize_symbol_name (symtab_node *node { if (symtab->dump_file) fprintf (symtab->dump_file, - "Not privatizing symbol name: %s. Has unique name.\n", - name); - return false; + "Not privatizing symbol name: %s. Has unique name.\n", + name); + return true; + } + return false; +} + +/* If we are an offload compiler, we may have to rewrite symbols to be + valid on this target. Return either PTR or a modified version of it. */ + +static const char * +maybe_rewrite_identifier (const char *ptr) +{ +#if defined ACCEL_COMPILER && (defined NO_DOT_IN_LABEL || defined NO_DOLLAR_IN_LABEL) +#ifndef NO_DOT_IN_LABEL + char valid = '.'; + const char reject[] = "$"; +#elif !defined NO_DOLLAR_IN_LABEL + char valid = '$'; + const char reject[] = "."; +#else + char valid = '_'; + const char reject[] = ".$"; +#endif + + char *copy = NULL; + const char *match = ptr; + for (;;) + { + size_t off = strcspn (match, reject); + if (match[off] == '\0') + break; + if (copy == NULL) + { + copy = xstrdup (ptr); + match = copy; + } + copy[off] = valid; + } + return match; +#else + return ptr; +#endif +} + +/* Ensure that the symbol in NODE is valid for the target, and if not, + rewrite it. */ + +static void +validize_symbol_for_target (symtab_node *node) +{ + tree decl = node->decl; + const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + + if (must_not_rename (node, name)) + return; + + const char *name2 = maybe_rewrite_identifier (name); + if (name2 != name) + { + symtab->change_decl_assembler_name (decl, get_identifier (name2)); + if (node->lto_file_data) + lto_record_renamed_decl (node->lto_file_data, name, + IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (decl))); } +} + +/* 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 previously static var was promoted hidden to avoid possible conflict + with symbols defined out of the LTO world. */ + +static bool +privatize_symbol_name (symtab_node *node) +{ + tree decl = node->decl; + cgraph_node *cnode = dyn_cast (node); + + /* If we want to privatize instrumentation clone + then we need to change original function name + which is used via transparent alias chain. */ + if (cnode && cnode->instrumentation_clone) + decl = cnode->orig_decl; + + const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + + if (must_not_rename (node, name)) + return false; + + name = maybe_rewrite_identifier (name); symtab->change_decl_assembler_name (decl, - clone_function_name (decl, "lto_priv")); + clone_function_name_1 (name, + "lto_priv")); if (node->lto_file_data) lto_record_renamed_decl (node->lto_file_data, name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); /* We could change name which is a target of transparent alias - chain of instrumented function name. Fix alias chain if so .*/ + chain of instrumented function name. Fix alias chain if so. */ if (cnode) { tree iname = NULL_TREE; @@ -868,7 +941,10 @@ promote_symbol (symtab_node *node) if (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN && DECL_VISIBILITY_SPECIFIED (node->decl) && TREE_PUBLIC (node->decl)) - return; + { + validize_symbol_for_target (node); + return; + } gcc_checking_assert (!TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl)); @@ -1007,7 +1083,10 @@ lto_promote_cross_file_statics (void) /* ... or if we do not partition it. This mean that it will appear in every partition refernecing it. */ || node->get_partitioning_class () != SYMBOL_PARTITION) - continue; + { + validize_symbol_for_target (node); + continue; + } promote_symbol (node); } @@ -1022,5 +1101,8 @@ lto_promote_statics_nonwpa (void) { symtab_node *node; FOR_EACH_SYMBOL (node) - rename_statics (NULL, node); + { + rename_statics (NULL, node); + validize_symbol_for_target (node); + } }