diff options
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 78 |
1 files changed, 68 insertions, 10 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index fff437a..66a88db 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -97,6 +97,7 @@ The callgraph: #include "diagnostic-core.h" #include "rtl.h" #include "ipa-utils.h" +#include "lto-streamer.h" static void cgraph_node_remove_callers (struct cgraph_node *node); static inline void cgraph_edge_remove_caller (struct cgraph_edge *e); @@ -1975,20 +1976,43 @@ debug_cgraph (void) void change_decl_assembler_name (tree decl, tree name) { - gcc_assert (!assembler_name_hash); + struct cgraph_node *node; + void **slot; if (!DECL_ASSEMBLER_NAME_SET_P (decl)) + SET_DECL_ASSEMBLER_NAME (decl, name); + else { - SET_DECL_ASSEMBLER_NAME (decl, name); - return; - } - if (name == DECL_ASSEMBLER_NAME (decl)) - return; + if (name == DECL_ASSEMBLER_NAME (decl)) + return; - if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) - && DECL_RTL_SET_P (decl)) - warning (0, "%D renamed after being referenced in assembly", decl); + if (assembler_name_hash + && TREE_CODE (decl) == FUNCTION_DECL + && (node = cgraph_get_node_or_alias (decl)) != NULL) + { + tree old_name = DECL_ASSEMBLER_NAME (decl); + slot = htab_find_slot_with_hash (assembler_name_hash, old_name, + decl_assembler_name_hash (old_name), + NO_INSERT); + /* Inline clones are not hashed. */ + if (slot && *slot == node) + htab_clear_slot (assembler_name_hash, slot); + } + if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) + && DECL_RTL_SET_P (decl)) + warning (0, "%D renamed after being referenced in assembly", decl); - SET_DECL_ASSEMBLER_NAME (decl, name); + SET_DECL_ASSEMBLER_NAME (decl, name); + } + if (assembler_name_hash + && TREE_CODE (decl) == FUNCTION_DECL + && (node = cgraph_get_node_or_alias (decl)) != NULL) + { + slot = htab_find_slot_with_hash (assembler_name_hash, name, + decl_assembler_name_hash (name), + INSERT); + gcc_assert (!*slot); + *slot = node; + } } /* Add a top-level asm statement to the list. */ @@ -2459,6 +2483,40 @@ cgraph_make_decl_local (tree decl) if (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; + + old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + if (TREE_CODE (decl) == FUNCTION_DECL) + { + struct cgraph_node *node = cgraph_get_node_or_alias (decl); + change_decl_assembler_name (decl, + clone_function_name (decl, "local")); + if (node->local.lto_file_data) + lto_record_renamed_decl (node->local.lto_file_data, + old_name, + IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (decl))); + } + else if (TREE_CODE (decl) == VAR_DECL) + { + struct varpool_node *vnode = varpool_get_node (decl); + /* change_decl_assembler_name will warn here on vtables because + C++ frontend still sets TREE_SYMBOL_REFERENCED on them. */ + SET_DECL_ASSEMBLER_NAME (decl, + clone_function_name (decl, "local")); + if (vnode->lto_file_data) + lto_record_renamed_decl (vnode->lto_file_data, + old_name, + IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (decl))); + } + } DECL_SECTION_NAME (decl) = 0; DECL_COMDAT (decl) = 0; } |