===================================================================
@@ -573,16 +573,21 @@ lto_symtab_merge_symbols (void)
{
symtab_initialize_asm_name_hash ();
- /* Do the actual merging. */
+ /* Do the actual merging.
+ At this point we invalidate hash translating decls into symtab nodes
+ because after removing one of duplicate decls the hash is not correcly
+ updated to the ohter dupliate. */
FOR_EACH_SYMBOL (node)
if (lto_symtab_symbol_p (node)
&& node->symbol.next_sharing_asm_name
&& !node->symbol.previous_sharing_asm_name)
lto_symtab_merge_symbols_1 (node);
- /* Resolve weakref aliases whose target are now in the compilation unit. */
+ /* Resolve weakref aliases whose target are now in the compilation unit.
+ also re-populate the hash translating decls into symtab nodes*/
FOR_EACH_SYMBOL (node)
{
+ cgraph_node *cnode;
if (!node->symbol.analyzed && node->symbol.alias_target)
{
symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target);
@@ -591,6 +596,10 @@ lto_symtab_merge_symbols (void)
symtab_resolve_alias (node, tgt);
}
node->symbol.aux = NULL;
+ if (!(cnode = dyn_cast <cgraph_node> (node))
+ || !cnode->clone_of
+ || cnode->clone_of->symbol.decl != cnode->symbol.decl)
+ symtab_insert_node_to_hashtable ((symtab_node)node);
}
}
}
===================================================================
@@ -773,6 +773,7 @@ bool cgraph_maybe_hot_edge_p (struct cgr
bool cgraph_optimize_for_size_p (struct cgraph_node *);
/* In varpool.c */
+struct varpool_node *varpool_create_empty_node (void);
struct varpool_node *varpool_node_for_decl (tree);
struct varpool_node *varpool_node_for_asm (tree asmname);
void varpool_mark_needed_node (struct varpool_node *);
===================================================================
@@ -959,7 +959,14 @@ input_node (struct lto_file_decl_data *f
vNULL, false);
}
else
- node = cgraph_get_create_node (fn_decl);
+ {
+ /* Declaration of functions can be already merged with a declaration
+ from other input file. We keep cgraph unmerged until after streaming
+ of ipa passes is done. Alays forcingly create a fresh node. */
+ node = cgraph_create_empty_node ();
+ node->symbol.decl = fn_decl;
+ symtab_register_node ((symtab_node)node);
+ }
node->symbol.order = order;
if (order >= symtab_order)
@@ -1035,7 +1042,14 @@ input_varpool_node (struct lto_file_decl
order = streamer_read_hwi (ib) + order_base;
decl_index = streamer_read_uhwi (ib);
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
- node = varpool_node_for_decl (var_decl);
+
+ /* Declaration of functions can be already merged with a declaration
+ from other input file. We keep cgraph unmerged until after streaming
+ of ipa passes is done. Alays forcingly create a fresh node. */
+ node = varpool_create_empty_node ();
+ node->symbol.decl = var_decl;
+ symtab_register_node ((symtab_node)node);
+
node->symbol.order = order;
if (order >= symtab_order)
symtab_order = order + 1;
===================================================================
@@ -1726,18 +1726,16 @@ get_resolution (struct data_in *data_in,
return LDPR_UNKNOWN;
}
-/* Map assigning declarations their resolutions. */
-static pointer_map_t *resolution_map;
-
/* We need to record resolutions until symbol table is read. */
static void
-register_resolution (tree decl, enum ld_plugin_symbol_resolution resolution)
+register_resolution (struct lto_file_decl_data *file_data, tree decl,
+ enum ld_plugin_symbol_resolution resolution)
{
if (resolution == LDPR_UNKNOWN)
return;
- if (!resolution_map)
- resolution_map = pointer_map_create ();
- *pointer_map_insert (resolution_map, decl) = (void *)(size_t)resolution;
+ if (!file_data->resolution_map)
+ file_data->resolution_map = pointer_map_create ();
+ *pointer_map_insert (file_data->resolution_map, decl) = (void *)(size_t)resolution;
}
/* Register DECL with the global symbol table and change its
@@ -1764,7 +1762,7 @@ lto_register_var_decl_in_symtab (struct
unsigned ix;
if (!streamer_tree_cache_lookup (data_in->reader_cache, decl, &ix))
gcc_unreachable ();
- register_resolution (decl, get_resolution (data_in, ix));
+ register_resolution (data_in->file_data, decl, get_resolution (data_in, ix));
}
}
@@ -1784,7 +1782,7 @@ lto_register_function_decl_in_symtab (st
unsigned ix;
if (!streamer_tree_cache_lookup (data_in->reader_cache, decl, &ix))
gcc_unreachable ();
- register_resolution (decl, get_resolution (data_in, ix));
+ register_resolution (data_in->file_data, decl, get_resolution (data_in, ix));
}
}
@@ -2865,6 +2863,8 @@ read_cgraph_and_symbols (unsigned nfiles
struct cgraph_node *node;
int count = 0;
struct lto_file_decl_data **decl_data;
+ void **res;
+ symtab_node snode;
init_cgraph ();
@@ -2971,21 +2971,21 @@ read_cgraph_and_symbols (unsigned nfiles
input_symtab ();
/* Store resolutions into the symbol table. */
- if (resolution_map)
- {
- void **res;
- symtab_node snode;
- FOR_EACH_SYMBOL (snode)
- if (symtab_real_symbol_p (snode)
- && (res = pointer_map_contains (resolution_map,
- snode->symbol.decl)))
- snode->symbol.resolution
- = (enum ld_plugin_symbol_resolution)(size_t)*res;
-
- pointer_map_destroy (resolution_map);
- resolution_map = NULL;
- }
+ FOR_EACH_SYMBOL (snode)
+ if (symtab_real_symbol_p (snode)
+ && snode->symbol.lto_file_data
+ && snode->symbol.lto_file_data->resolution_map
+ && (res = pointer_map_contains (snode->symbol.lto_file_data->resolution_map,
+ snode->symbol.decl)))
+ snode->symbol.resolution
+ = (enum ld_plugin_symbol_resolution)(size_t)*res;
+ for (i = 0; all_file_decl_data[i]; i++)
+ if (all_file_decl_data[i]->resolution_map)
+ {
+ pointer_map_destroy (all_file_decl_data[i]->resolution_map);
+ all_file_decl_data[i]->resolution_map = NULL;
+ }
timevar_pop (TV_IPA_LTO_CGRAPH_IO);
===================================================================
@@ -269,7 +269,11 @@ symtab_unregister_node (symtab_node node
node->symbol.previous = NULL;
slot = htab_find_slot (symtab_hash, node, NO_INSERT);
- if (*slot == node)
+
+ /* During LTO symtab merging we temporarily corrupt decl to symtab node
+ hash. */
+ gcc_assert ((slot && *slot) || in_lto_p);
+ if (slot && *slot && *slot == node)
{
symtab_node replacement_node = NULL;
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
@@ -291,10 +295,14 @@ symtab_get_node (const_tree decl)
symtab_node *slot;
struct symtab_node_base key;
+#ifdef ENABLE_CHECKING
+ /* Check that we are called for sane type of object - functions
+ and static or external variables. */
gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
|| (TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
|| in_lto_p)));
+#endif
if (!symtab_hash)
return NULL;
===================================================================
@@ -36,18 +36,26 @@ along with GCC; see the file COPYING3.
#include "tree-flow.h"
#include "flags.h"
+/* Allocate new callgraph node and insert it into basic data structures. */
+
+struct varpool_node *
+varpool_create_empty_node (void)
+{
+ struct varpool_node *node = ggc_alloc_cleared_varpool_node ();
+ node->symbol.type = SYMTAB_VARIABLE;
+ return node;
+}
+
/* Return varpool node assigned to DECL. Create new one when needed. */
struct varpool_node *
varpool_node_for_decl (tree decl)
{
struct varpool_node *node = varpool_get_node (decl);
- gcc_assert (TREE_CODE (decl) == VAR_DECL
- && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p));
+ gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
if (node)
return node;
- node = ggc_alloc_cleared_varpool_node ();
- node->symbol.type = SYMTAB_VARIABLE;
+ node = varpool_create_empty_node ();
node->symbol.decl = decl;
symtab_register_node ((symtab_node)node);
return node;
===================================================================
@@ -569,6 +569,9 @@ struct GTY(()) lto_file_decl_data
unsigned max_index;
struct gcov_ctr_summary GTY((skip)) profile_info;
+
+ /* Map assigning declarations their resolutions. */
+ pointer_map_t * GTY((skip)) resolution_map;
};
typedef struct lto_file_decl_data *lto_file_decl_data_ptr;