summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-09-19 10:01:56 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-09-19 10:01:56 +0000
commitc9aa64535850aea75f19172b655ded1c72392c6d (patch)
treeadf76d7fd51871b5c848e4b405009efc05ca3097 /gcc
parenta2e26af78f7b7fcad53f80b5771264adf46586e2 (diff)
downloadgcc-c9aa64535850aea75f19172b655ded1c72392c6d.tar.gz
* symtab.c (insert_to_assembler_name_hash): Do not insert
register vars. (unlink_from_assembler_name_hash): NULL out pointers of unlinked var. (symtab_prevail_in_asm_name_hash): New. (symtab_initialize_asm_name_hash): Break out from ... (symtab_node_for_asm): ... here. (dump_symtab_base): Dump LTO file data. (verify_symtab_base): Register vars are not in symtab. * cgraph.h (symtab_initialize_asm_name_hash, symtab_prevail_in_asm_name_hash): New functions. (symtab_real_symbol_p): New inline. * lto-symtab.c: Do not include gt-lto-symtab.h. (lto_symtab_entry_def): Remove. (lto_symtab_entry_t): Remove. (lto_symtab_identifiers): Remove. (lto_symtab_free): Remove. (lto_symtab_entry_hash): Remove. (lto_symtab_entry_eq): Remove. (lto_symtab_entry_marked_p): Remove. (lto_symtab_maybe_init_hash_table): Remove. (resolution_guessed_p, set_resolution_guessed): New functions. (lto_symtab_register_decl): Only set resolution info. (lto_symtab_get, lto_symtab_get_resolution): Remove. (lto_symtab_merge): Reorg to work across symtab; do nothing if decls are same. (lto_symtab_resolve_replaceable_p): Reorg to work on symtab. (lto_symtab_resolve_can_prevail_p): Likewise; only real symbols can prevail. (lto_symtab_resolve_symbols): Reorg to work on symtab. (lto_symtab_merge_decls_2): Likewise. (lto_symtab_merge_decls_1): Likewise; add debug dumps. (lto_symtab_merge_decls): Likewise; do not merge at ltrans stage. (lto_symtab_merge_cgraph_nodes_1): Reorg to work on symtab. (lto_symtab_merge_cgraph_nodes): Likewise; do not merge at ltrans stage. (lto_symtab_prevailing_decl): Rewrite to lookup into symtab. * lto-streaer.h (lto_symtab_free): Remove. * lto-cgraph.c (add_references): Cleanup. * varpool.c (varpool_assemble_decl): Skip hard regs. * lto.c (lto_materialize_function): Update confused comment. (read_cgraph_and_symbols): Do not free symtab. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@191466 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog42
-rw-r--r--gcc/cgraph.h25
-rw-r--r--gcc/lto-cgraph.c5
-rw-r--r--gcc/lto-streamer.h1
-rw-r--r--gcc/lto-symtab.c510
-rw-r--r--gcc/lto/ChangeLog5
-rw-r--r--gcc/lto/lto.c4
-rw-r--r--gcc/symtab.c41
-rw-r--r--gcc/varpool.c4
9 files changed, 314 insertions, 323 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d4d4f1b6ce7..d00f3e29449 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,45 @@
+2012-09-19 Jan Hubicka <jh@suse.cz>
+
+ * symtab.c (insert_to_assembler_name_hash): Do not insert
+ register vars.
+ (unlink_from_assembler_name_hash): NULL out pointers of unlinked
+ var.
+ (symtab_prevail_in_asm_name_hash): New.
+ (symtab_initialize_asm_name_hash): Break out from ...
+ (symtab_node_for_asm): ... here.
+ (dump_symtab_base): Dump LTO file data.
+ (verify_symtab_base): Register vars are not in symtab.
+ * cgraph.h (symtab_initialize_asm_name_hash,
+ symtab_prevail_in_asm_name_hash): New functions.
+ (symtab_real_symbol_p): New inline.
+ * lto-symtab.c: Do not include gt-lto-symtab.h.
+ (lto_symtab_entry_def): Remove.
+ (lto_symtab_entry_t): Remove.
+ (lto_symtab_identifiers): Remove.
+ (lto_symtab_free): Remove.
+ (lto_symtab_entry_hash): Remove.
+ (lto_symtab_entry_eq): Remove.
+ (lto_symtab_entry_marked_p): Remove.
+ (lto_symtab_maybe_init_hash_table): Remove.
+ (resolution_guessed_p, set_resolution_guessed): New functions.
+ (lto_symtab_register_decl): Only set resolution info.
+ (lto_symtab_get, lto_symtab_get_resolution): Remove.
+ (lto_symtab_merge): Reorg to work across symtab; do nothing if decls
+ are same.
+ (lto_symtab_resolve_replaceable_p): Reorg to work on symtab.
+ (lto_symtab_resolve_can_prevail_p): Likewise; only real symbols can
+ prevail.
+ (lto_symtab_resolve_symbols): Reorg to work on symtab.
+ (lto_symtab_merge_decls_2): Likewise.
+ (lto_symtab_merge_decls_1): Likewise; add debug dumps.
+ (lto_symtab_merge_decls): Likewise; do not merge at ltrans stage.
+ (lto_symtab_merge_cgraph_nodes_1): Reorg to work on symtab.
+ (lto_symtab_merge_cgraph_nodes): Likewise; do not merge at ltrans stage.
+ (lto_symtab_prevailing_decl): Rewrite to lookup into symtab.
+ * lto-streaer.h (lto_symtab_free): Remove.
+ * lto-cgraph.c (add_references): Cleanup.
+ * varpool.c (varpool_assemble_decl): Skip hard regs.
+
2012-09-19 Richard Guenther <rguenther@suse.de>
PR other/53316
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 0d2ad41c43a..b8001a62bc7 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -704,6 +704,8 @@ bool varpool_for_node_and_aliases (struct varpool_node *,
bool (*) (struct varpool_node *, void *),
void *, bool);
void varpool_add_new_variable (tree);
+void symtab_initialize_asm_name_hash (void);
+void symtab_prevail_in_asm_name_hash (symtab_node node);
/* Return true when NODE is function. */
static inline bool
@@ -1309,4 +1311,27 @@ cgraph_mark_force_output_node (struct cgraph_node *node)
gcc_checking_assert (!node->global.inlined_to);
}
+/* Return true when the symbol is real symbol, i.e. it is not inline clone
+ or extern function kept around just for inlining. */
+
+static inline bool
+symtab_real_symbol_p (symtab_node node)
+{
+ struct cgraph_node *cnode;
+ struct ipa_ref *ref;
+
+ if (!symtab_function_p (node))
+ return true;
+ cnode = cgraph (node);
+ if (cnode->global.inlined_to)
+ return false;
+ if (cnode->abstract_and_needed)
+ return false;
+ /* We keep virtual clones in symtab. */
+ if (!cnode->analyzed
+ || DECL_EXTERNAL (cnode->symbol.decl))
+ return (cnode->callers
+ || ipa_ref_list_referring_iterate (&cnode->symbol.ref_list, 0, ref));
+ return true;
+}
#endif /* GCC_CGRAPH_H */
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 24222883da4..b8693343090 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -668,10 +668,7 @@ add_references (lto_symtab_encoder_t encoder,
if (symtab_function_p (ref->referred))
add_node_to (encoder, ipa_ref_node (ref), false);
else
- {
- struct varpool_node *vnode = ipa_ref_varpool_node (ref);
- lto_symtab_encoder_encode (encoder, (symtab_node)vnode);
- }
+ lto_symtab_encoder_encode (encoder, ref->referred);
}
/* Find all symbols we want to stream into given partition and insert them
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index abeaa4b2417..059959e737f 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -866,7 +866,6 @@ extern void lto_symtab_merge_decls (void);
extern void lto_symtab_merge_cgraph_nodes (void);
extern tree lto_symtab_prevailing_decl (tree decl);
extern enum ld_plugin_symbol_resolution lto_symtab_get_resolution (tree decl);
-extern void lto_symtab_free (void);
extern GTY(()) VEC(tree,gc) *lto_global_var_decls;
diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c
index c5efb7f0156..58b77a353a7 100644
--- a/gcc/lto-symtab.c
+++ b/gcc/lto-symtab.c
@@ -32,98 +32,19 @@ along with GCC; see the file COPYING3. If not see
/* Vector to keep track of external variables we've seen so far. */
VEC(tree,gc) *lto_global_var_decls;
-/* Symbol table entry. */
-
-struct GTY(()) lto_symtab_entry_def
-{
- /* The symbol table entry key, an IDENTIFIER. */
- tree id;
- /* The symbol table entry, a DECL. */
- tree decl;
- /* The cgraph node if decl is a function decl. Filled in during the
- merging process. */
- struct cgraph_node *node;
- /* The varpool node if decl is a variable decl. Filled in during the
- merging process. */
- struct varpool_node *vnode;
- /* LTO file-data and symbol resolution for this decl. */
- struct lto_file_decl_data * GTY((skip (""))) file_data;
- enum ld_plugin_symbol_resolution resolution;
- /* True when resolution was guessed and not read from the file. */
- bool guessed;
- /* Pointer to the next entry with the same key. Before decl merging
- this links all symbols from the different TUs. After decl merging
- this links merged but incompatible decls, thus all prevailing ones
- remaining. */
- struct lto_symtab_entry_def *next;
-};
-typedef struct lto_symtab_entry_def *lto_symtab_entry_t;
-
-/* A poor man's symbol table. This hashes identifier to prevailing DECL
- if there is one. */
-
-static GTY ((if_marked ("lto_symtab_entry_marked_p"),
- param_is (struct lto_symtab_entry_def)))
- htab_t lto_symtab_identifiers;
-
-/* Free symtab hashtable. */
-
-void
-lto_symtab_free (void)
-{
- htab_delete (lto_symtab_identifiers);
- lto_symtab_identifiers = NULL;
-}
-
-/* Return the hash value of an lto_symtab_entry_t object pointed to by P. */
-
-static hashval_t
-lto_symtab_entry_hash (const void *p)
-{
- const struct lto_symtab_entry_def *base =
- (const struct lto_symtab_entry_def *) p;
- return IDENTIFIER_HASH_VALUE (base->id);
-}
-
-/* Return non-zero if P1 and P2 points to lto_symtab_entry_def structs
- corresponding to the same symbol. */
-
-static int
-lto_symtab_entry_eq (const void *p1, const void *p2)
+/* Return true if the resolution was guessed and not obtained from
+ the file. */
+static inline bool
+resolution_guessed_p (symtab_node node)
{
- const struct lto_symtab_entry_def *base1 =
- (const struct lto_symtab_entry_def *) p1;
- const struct lto_symtab_entry_def *base2 =
- (const struct lto_symtab_entry_def *) p2;
- return (base1->id == base2->id);
+ return node->symbol.aux != NULL;
}
-/* Returns non-zero if P points to an lto_symtab_entry_def struct that needs
- to be marked for GC. */
-
-static int
-lto_symtab_entry_marked_p (const void *p)
+/* Set guessed flag for NODE. */
+static inline void
+set_resolution_guessed (symtab_node node, bool value)
{
- const struct lto_symtab_entry_def *base =
- (const struct lto_symtab_entry_def *) p;
-
- /* Keep this only if the common IDENTIFIER_NODE of the symtab chain
- is marked which it will be if at least one of the DECLs in the
- chain is marked. */
- return ggc_marked_p (base->id);
-}
-
-/* Lazily initialize resolution hash tables. */
-
-static void
-lto_symtab_maybe_init_hash_table (void)
-{
- if (lto_symtab_identifiers)
- return;
-
- lto_symtab_identifiers =
- htab_create_ggc (1021, lto_symtab_entry_hash,
- lto_symtab_entry_eq, NULL);
+ node->symbol.aux = (void *)(size_t)value;
}
/* Registers DECL with the LTO symbol table as having resolution RESOLUTION
@@ -134,8 +55,7 @@ lto_symtab_register_decl (tree decl,
ld_plugin_symbol_resolution_t resolution,
struct lto_file_decl_data *file_data)
{
- lto_symtab_entry_t new_entry;
- void **slot;
+ symtab_node node;
/* Check that declarations reaching this function do not have
properties inconsistent with having external linkage. If any of
@@ -153,54 +73,15 @@ lto_symtab_register_decl (tree decl,
if (TREE_CODE (decl) == FUNCTION_DECL)
gcc_assert (!DECL_ABSTRACT (decl));
- new_entry = ggc_alloc_cleared_lto_symtab_entry_def ();
- new_entry->id = (*targetm.asm_out.mangle_assembler_name)
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- new_entry->decl = decl;
- new_entry->resolution = resolution;
- new_entry->file_data = file_data;
-
- lto_symtab_maybe_init_hash_table ();
- slot = htab_find_slot (lto_symtab_identifiers, new_entry, INSERT);
- new_entry->next = (lto_symtab_entry_t) *slot;
- *slot = new_entry;
-}
-
-/* Get the lto_symtab_entry_def struct associated with ID
- if there is one. */
-
-static lto_symtab_entry_t
-lto_symtab_get (tree id)
-{
- struct lto_symtab_entry_def temp;
- void **slot;
-
- lto_symtab_maybe_init_hash_table ();
- temp.id = id;
- slot = htab_find_slot (lto_symtab_identifiers, &temp, NO_INSERT);
- return slot ? (lto_symtab_entry_t) *slot : NULL;
-}
-
-/* Get the linker resolution for DECL. */
-
-enum ld_plugin_symbol_resolution
-lto_symtab_get_resolution (tree decl)
-{
- lto_symtab_entry_t e;
-
- gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-
- e = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
- while (e && e->decl != decl)
- e = e->next;
- if (!e)
- return LDPR_UNKNOWN;
-
- return e->resolution;
+ node = symtab_get_node (decl);
+ if (node)
+ {
+ node->symbol.resolution = resolution;
+ gcc_assert (node->symbol.lto_file_data == file_data);
+ gcc_assert (!resolution_guessed_p (node));
+ }
}
-
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
all edges and removing the old node. */
@@ -277,12 +158,15 @@ lto_varpool_replace_node (struct varpool_node *vnode,
should be emitted. */
static bool
-lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
+lto_symtab_merge (symtab_node prevailing, symtab_node entry)
{
- tree prevailing_decl = prevailing->decl;
- tree decl = entry->decl;
+ tree prevailing_decl = prevailing->symbol.decl;
+ tree decl = entry->symbol.decl;
tree prevailing_type, type;
+ if (prevailing_decl == decl)
+ return true;
+
/* Merge decl state in both directions, we may still end up using
the new decl. */
TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
@@ -377,17 +261,17 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
entry. */
static bool
-lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
+lto_symtab_resolve_replaceable_p (symtab_node e)
{
- if (DECL_EXTERNAL (e->decl)
- || DECL_COMDAT (e->decl)
- || DECL_ONE_ONLY (e->decl)
- || DECL_WEAK (e->decl))
+ if (DECL_EXTERNAL (e->symbol.decl)
+ || DECL_COMDAT (e->symbol.decl)
+ || DECL_ONE_ONLY (e->symbol.decl)
+ || DECL_WEAK (e->symbol.decl))
return true;
- if (TREE_CODE (e->decl) == VAR_DECL)
- return (DECL_COMMON (e->decl)
- || (!flag_no_common && !DECL_INITIAL (e->decl)));
+ if (TREE_CODE (e->symbol.decl) == VAR_DECL)
+ return (DECL_COMMON (e->symbol.decl)
+ || (!flag_no_common && !DECL_INITIAL (e->symbol.decl)));
return false;
}
@@ -395,24 +279,23 @@ lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
/* Return true if the symtab entry E can be the prevailing one. */
static bool
-lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
+lto_symtab_resolve_can_prevail_p (symtab_node e)
{
+ if (!symtab_real_symbol_p (e))
+ return false;
+
/* The C++ frontend ends up neither setting TREE_STATIC nor
DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
So do not reject !TREE_STATIC here but only DECL_EXTERNAL. */
- if (DECL_EXTERNAL (e->decl))
+ if (DECL_EXTERNAL (e->symbol.decl))
return false;
/* For functions we need a non-discarded body. */
- if (TREE_CODE (e->decl) == FUNCTION_DECL)
- return (e->node && e->node->analyzed);
+ if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
+ return (cgraph (e)->analyzed);
- else if (TREE_CODE (e->decl) == VAR_DECL)
- {
- if (!e->vnode)
- return false;
- return e->vnode->finalized;
- }
+ else if (TREE_CODE (e->symbol.decl) == VAR_DECL)
+ return varpool (e)->finalized;
gcc_unreachable ();
}
@@ -421,23 +304,18 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
their resolutions. */
static void
-lto_symtab_resolve_symbols (void **slot)
+lto_symtab_resolve_symbols (symtab_node first)
{
- lto_symtab_entry_t e;
- lto_symtab_entry_t prevailing = NULL;
+ symtab_node e;
+ symtab_node prevailing = NULL;
/* Always set e->node so that edges are updated to reflect decl merging. */
- for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
- {
- if (TREE_CODE (e->decl) == FUNCTION_DECL)
- e->node = cgraph_get_node (e->decl);
- else if (TREE_CODE (e->decl) == VAR_DECL)
- e->vnode = varpool_get_node (e->decl);
- if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
- || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || e->resolution == LDPR_PREVAILING_DEF)
- prevailing = e;
- }
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ if (symtab_real_symbol_p (e)
+ && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
+ || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+ || e->symbol.resolution == LDPR_PREVAILING_DEF))
+ prevailing = e;
/* If the chain is already resolved there is nothing else to do. */
if (prevailing)
@@ -445,26 +323,26 @@ lto_symtab_resolve_symbols (void **slot)
/* Find the single non-replaceable prevailing symbol and
diagnose ODR violations. */
- for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
{
if (!lto_symtab_resolve_can_prevail_p (e))
{
- e->resolution = LDPR_RESOLVED_IR;
- e->guessed = true;
+ e->symbol.resolution = LDPR_RESOLVED_IR;
+ set_resolution_guessed (e, true);
continue;
}
/* Set a default resolution - the final prevailing one will get
adjusted later. */
- e->resolution = LDPR_PREEMPTED_IR;
- e->guessed = true;
+ e->symbol.resolution = LDPR_PREEMPTED_IR;
+ set_resolution_guessed (e, true);
if (!lto_symtab_resolve_replaceable_p (e))
{
if (prevailing)
{
- error_at (DECL_SOURCE_LOCATION (e->decl),
- "%qD has already been defined", e->decl);
- inform (DECL_SOURCE_LOCATION (prevailing->decl),
+ error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+ "%qD has already been defined", e->symbol.decl);
+ inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
"previously defined here");
}
prevailing = e;
@@ -474,13 +352,14 @@ lto_symtab_resolve_symbols (void **slot)
goto found;
/* Do a second round choosing one from the replaceable prevailing decls. */
- for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
{
- if (e->resolution != LDPR_PREEMPTED_IR)
+ if (e->symbol.resolution != LDPR_PREEMPTED_IR
+ || !symtab_real_symbol_p (e))
continue;
/* Choose the first function that can prevail as prevailing. */
- if (TREE_CODE (e->decl) == FUNCTION_DECL)
+ if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
{
prevailing = e;
break;
@@ -488,8 +367,8 @@ lto_symtab_resolve_symbols (void **slot)
/* From variables that can prevail choose the largest one. */
if (!prevailing
- || tree_int_cst_lt (DECL_SIZE (prevailing->decl),
- DECL_SIZE (e->decl))
+ || tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl),
+ DECL_SIZE (e->symbol.decl))
/* When variables are equivalent try to chose one that has useful
DECL_INITIAL. This makes sense for keyed vtables that are
DECL_EXTERNAL but initialized. In units that do not need them
@@ -499,11 +378,11 @@ lto_symtab_resolve_symbols (void **slot)
We know that the vtable is keyed outside the LTO unit - otherwise
the keyed instance would prevail. We still can preserve useful
info in the initializer. */
- || (DECL_SIZE (prevailing->decl) == DECL_SIZE (e->decl)
- && (DECL_INITIAL (e->decl)
- && DECL_INITIAL (e->decl) != error_mark_node)
- && (!DECL_INITIAL (prevailing->decl)
- || DECL_INITIAL (prevailing->decl) == error_mark_node)))
+ || (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl)
+ && (DECL_INITIAL (e->symbol.decl)
+ && DECL_INITIAL (e->symbol.decl) != error_mark_node)
+ && (!DECL_INITIAL (prevailing->symbol.decl)
+ || DECL_INITIAL (prevailing->symbol.decl) == error_mark_node)))
prevailing = e;
}
@@ -524,8 +403,8 @@ found:
variables IRONLY, which are indeed PREVAILING_DEF in
resolution file. These variables still need manual
externally_visible attribute. */
- prevailing->resolution = LDPR_PREVAILING_DEF_IRONLY;
- prevailing->guessed = true;
+ prevailing->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
+ set_resolution_guessed (prevailing, true);
}
/* Merge all decls in the symbol table chain to the prevailing decl and
@@ -533,24 +412,25 @@ found:
do not issue further diagnostics.*/
static void
-lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
+lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
{
- lto_symtab_entry_t prevailing, e;
+ symtab_node prevailing, e;
VEC(tree, heap) *mismatches = NULL;
unsigned i;
tree decl;
/* Nothing to do for a single entry. */
- prevailing = (lto_symtab_entry_t) *slot;
- if (!prevailing->next)
+ prevailing = first;
+ if (!prevailing->symbol.next_sharing_asm_name)
return;
/* Try to merge each entry with the prevailing one. */
- for (e = prevailing->next; e; e = e->next)
+ for (e = prevailing->symbol.next_sharing_asm_name;
+ e; e = e->symbol.next_sharing_asm_name)
{
if (!lto_symtab_merge (prevailing, e)
&& !diagnosed_p)
- VEC_safe_push (tree, heap, mismatches, e->decl);
+ VEC_safe_push (tree, heap, mismatches, e->symbol.decl);
}
if (VEC_empty (tree, mismatches))
return;
@@ -558,13 +438,15 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
/* Diagnose all mismatched re-declarations. */
FOR_EACH_VEC_ELT (tree, mismatches, i, decl)
{
- if (!types_compatible_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl)))
+ if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl),
+ TREE_TYPE (decl)))
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
"type of %qD does not match original "
"declaration", decl);
- else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl))
- && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))
+ else if ((DECL_USER_ALIGN (prevailing->symbol.decl)
+ && DECL_USER_ALIGN (decl))
+ && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl))
{
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
"alignment of %qD is bigger than "
@@ -572,7 +454,7 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
}
}
if (diagnosed_p)
- inform (DECL_SOURCE_LOCATION (prevailing->decl),
+ inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
"previously declared here");
VEC_free (tree, heap, mismatches);
@@ -580,47 +462,50 @@ lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
/* Helper to process the decl chain for the symbol table entry *SLOT. */
-static int
-lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+static void
+lto_symtab_merge_decls_1 (symtab_node first)
{
- lto_symtab_entry_t e, prevailing;
+ symtab_node e, prevailing;
bool diagnosed_p = false;
+ if (cgraph_dump_file)
+ {
+ fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n",
+ symtab_node_asm_name (first));
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ dump_symtab_node (cgraph_dump_file, e);
+ }
+
/* Compute the symbol resolutions. This is a no-op when using the
- linker plugin. */
- lto_symtab_resolve_symbols (slot);
+ linker plugin and resolution was decided by the linker. */
+ lto_symtab_resolve_symbols (first);
/* Find the prevailing decl. */
- for (prevailing = (lto_symtab_entry_t) *slot;
+ for (prevailing = first;
prevailing
- && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY
- && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
- && prevailing->resolution != LDPR_PREVAILING_DEF;
- prevailing = prevailing->next)
+ && (!symtab_real_symbol_p (prevailing)
+ || (prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY
+ && prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
+ && prevailing->symbol.resolution != LDPR_PREVAILING_DEF));
+ prevailing = prevailing->symbol.next_sharing_asm_name)
;
/* Assert it's the only one. */
if (prevailing)
- for (e = prevailing->next; e; e = e->next)
- {
- if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
- || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || e->resolution == LDPR_PREVAILING_DEF)
- fatal_error ("multiple prevailing defs for %qE",
- DECL_NAME (prevailing->decl));
- }
+ for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name)
+ if (symtab_real_symbol_p (e)
+ && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
+ || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+ || e->symbol.resolution == LDPR_PREVAILING_DEF))
+ fatal_error ("multiple prevailing defs for %qE",
+ DECL_NAME (prevailing->symbol.decl));
/* If there's not a prevailing symbol yet it's an external reference.
Happens a lot during ltrans. Choose the first symbol with a
cgraph or a varpool node. */
if (!prevailing)
{
- prevailing = (lto_symtab_entry_t) *slot;
- /* For functions choose one with a cgraph node. */
- if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
- while (!prevailing->node
- && prevailing->next)
- prevailing = prevailing->next;
+ prevailing = first;
/* For variables chose with a priority variant with vnode
attached (i.e. from unit where external declaration of
variable is actually used).
@@ -628,49 +513,45 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
This is needed for C++ typeinfos, for example in
lto/20081204-1 there are typeifos in both units, just
one of them do have size. */
- if (TREE_CODE (prevailing->decl) == VAR_DECL)
+ if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
{
- for (e = prevailing->next; e; e = e->next)
- if ((!prevailing->vnode && e->vnode)
- || ((prevailing->vnode != NULL) == (e->vnode != NULL)
- && !COMPLETE_TYPE_P (TREE_TYPE (prevailing->decl))
- && COMPLETE_TYPE_P (TREE_TYPE (e->decl))))
+ for (e = prevailing->symbol.next_sharing_asm_name;
+ e; e = e->symbol.next_sharing_asm_name)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl))
+ && COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl)))
prevailing = e;
}
}
- /* Move it first in the list. */
- if ((lto_symtab_entry_t) *slot != prevailing)
- {
- for (e = (lto_symtab_entry_t) *slot; e->next != prevailing; e = e->next)
- ;
- e->next = prevailing->next;
- prevailing->next = (lto_symtab_entry_t) *slot;
- *slot = (void *) prevailing;
- }
+ symtab_prevail_in_asm_name_hash (prevailing);
/* Record the prevailing variable. */
- if (TREE_CODE (prevailing->decl) == VAR_DECL)
- VEC_safe_push (tree, gc, lto_global_var_decls, prevailing->decl);
+ if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
+ VEC_safe_push (tree, gc, lto_global_var_decls,
+ prevailing->symbol.decl);
/* Diagnose mismatched objects. */
- for (e = prevailing->next; e; e = e->next)
+ for (e = prevailing->symbol.next_sharing_asm_name;
+ e; e = e->symbol.next_sharing_asm_name)
{
- if (TREE_CODE (prevailing->decl) == TREE_CODE (e->decl))
+ if (TREE_CODE (prevailing->symbol.decl)
+ == TREE_CODE (e->symbol.decl))
continue;
- switch (TREE_CODE (prevailing->decl))
+ switch (TREE_CODE (prevailing->symbol.decl))
{
case VAR_DECL:
- gcc_assert (TREE_CODE (e->decl) == FUNCTION_DECL);
- error_at (DECL_SOURCE_LOCATION (e->decl),
- "variable %qD redeclared as function", prevailing->decl);
+ gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL);
+ error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+ "variable %qD redeclared as function",
+ prevailing->symbol.decl);
break;
case FUNCTION_DECL:
- gcc_assert (TREE_CODE (e->decl) == VAR_DECL);
- error_at (DECL_SOURCE_LOCATION (e->decl),
- "function %qD redeclared as variable", prevailing->decl);
+ gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL);
+ error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+ "function %qD redeclared as variable",
+ prevailing->symbol.decl);
break;
default:
@@ -680,12 +561,19 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
diagnosed_p = true;
}
if (diagnosed_p)
- inform (DECL_SOURCE_LOCATION (prevailing->decl),
+ inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
"previously declared here");
/* Merge the chain to the single prevailing decl and diagnose
mismatches. */
- lto_symtab_merge_decls_2 (slot, diagnosed_p);
+ lto_symtab_merge_decls_2 (first, diagnosed_p);
+
+ if (cgraph_dump_file)
+ {
+ fprintf (cgraph_dump_file, "After resolution:\n");
+ for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ dump_symtab_node (cgraph_dump_file, e);
+ }
/* Store resolution decision into the callgraph.
In LTRANS don't overwrite information we stored into callgraph at
@@ -698,11 +586,9 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP.
First one would disable some whole program optimizations, while
ther second would imply to many whole program assumptions. */
- if (prevailing->node && !flag_ltrans && !prevailing->guessed)
- prevailing->node->symbol.resolution = prevailing->resolution;
- else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed)
- prevailing->vnode->symbol.resolution = prevailing->resolution;
- return 1;
+ if (resolution_guessed_p (prevailing))
+ prevailing->symbol.resolution = LDPR_UNKNOWN;
+ return;
}
/* Resolve and merge all symbol table chains to a prevailing decl. */
@@ -710,50 +596,46 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
void
lto_symtab_merge_decls (void)
{
- lto_symtab_maybe_init_hash_table ();
- htab_traverse (lto_symtab_identifiers, lto_symtab_merge_decls_1, NULL);
+ symtab_node node;
+
+ /* In ltrans mode we read merged cgraph, we do not really need to care
+ about resolving symbols again, we only need to replace duplicated declarations
+ read from the callgraph and from function sections. */
+ if (flag_ltrans)
+ return;
+
+ /* Populate assembler name hash. */
+ symtab_initialize_asm_name_hash ();
+
+ FOR_EACH_SYMBOL (node)
+ if (TREE_PUBLIC (node->symbol.decl)
+ && node->symbol.next_sharing_asm_name
+ && !node->symbol.previous_sharing_asm_name)
+ lto_symtab_merge_decls_1 (node);
}
/* Helper to process the decl chain for the symbol table entry *SLOT. */
-static int
-lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+static void
+lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing)
{
- lto_symtab_entry_t e, prevailing = (lto_symtab_entry_t) *slot;
-
- if (!prevailing->next)
- return 1;
+ symtab_node e, next;
/* Replace the cgraph node of each entry with the prevailing one. */
- for (e = prevailing->next; e; e = e->next)
+ for (e = prevailing->symbol.next_sharing_asm_name; e;
+ e = next)
{
- if (e->node != NULL)
- {
- /* In case we prevail funcion by an alias, we can run into case
- that the alias has no cgraph node attached, since it was
- previously unused. Create the node. */
- if (!prevailing->node)
- {
- prevailing->node = cgraph_create_node (prevailing->decl);
- prevailing->node->alias = true;
- }
- lto_cgraph_replace_node (e->node, prevailing->node);
- }
- if (e->vnode != NULL)
- {
- if (!prevailing->vnode)
- {
- prevailing->vnode = varpool_node (prevailing->decl);
- prevailing->vnode->alias = true;
- }
- lto_varpool_replace_node (e->vnode, prevailing->vnode);
- }
- }
+ next = e->symbol.next_sharing_asm_name;
- /* Drop all but the prevailing decl from the symtab. */
- prevailing->next = NULL;
+ if (!symtab_real_symbol_p (e))
+ continue;
+ if (symtab_function_p (e))
+ lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
+ if (symtab_variable_p (e))
+ lto_varpool_replace_node (varpool (e), varpool (prevailing));
+ }
- return 1;
+ return;
}
/* Merge cgraph nodes according to the symbol merging done by
@@ -762,18 +644,33 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
void
lto_symtab_merge_cgraph_nodes (void)
{
- struct cgraph_node *node;
+ struct cgraph_node *cnode;
struct varpool_node *vnode;
- lto_symtab_maybe_init_hash_table ();
- htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
+ symtab_node node;
+
+ /* Populate assembler name hash. */
+ symtab_initialize_asm_name_hash ();
- FOR_EACH_FUNCTION (node)
- if ((node->thunk.thunk_p || node->alias)
- && node->thunk.alias)
- node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
+ if (!flag_ltrans)
+ FOR_EACH_SYMBOL (node)
+ if (TREE_PUBLIC (node->symbol.decl)
+ && node->symbol.next_sharing_asm_name
+ && !node->symbol.previous_sharing_asm_name)
+ lto_symtab_merge_cgraph_nodes_1 (node);
+
+ FOR_EACH_FUNCTION (cnode)
+ {
+ if ((cnode->thunk.thunk_p || cnode->alias)
+ && cnode->thunk.alias)
+ cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias);
+ cnode->symbol.aux = NULL;
+ }
FOR_EACH_VARIABLE (vnode)
- if (vnode->alias_of)
- vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
+ {
+ if (vnode->alias_of)
+ vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
+ vnode->symbol.aux = NULL;
+ }
}
/* Given the decl DECL, return the prevailing decl with the same name. */
@@ -781,7 +678,7 @@ lto_symtab_merge_cgraph_nodes (void)
tree
lto_symtab_prevailing_decl (tree decl)
{
- lto_symtab_entry_t ret;
+ symtab_node ret;
/* Builtins and local symbols are their own prevailing decl. */
if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
@@ -795,12 +692,9 @@ lto_symtab_prevailing_decl (tree decl)
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
/* Walk through the list of candidates and return the one we merged to. */
- ret = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
+ ret = symtab_node_for_asm (DECL_ASSEMBLER_NAME (decl));
if (!ret)
- return NULL_TREE;
+ return decl;
- return ret->decl;
+ return ret->symbol.decl;
}
-
-#include "gt-lto-symtab.h"
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 8b2a469d864..c6abe4b221f 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,8 @@
+2012-09-19 Jan Hubicka <jh@suse.cz>
+
+ * lto.c (lto_materialize_function): Update confused comment.
+ (read_cgraph_and_symbols): Do not free symtab.
+
2012-09-12 Jan Hubicka <jh@suse.cz>
* lto.c (do_whole_program_analysis): Care timevars, statistics and
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index c15f9cff5a7..930e990b780 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -198,7 +198,7 @@ lto_materialize_function (struct cgraph_node *node)
and also functions that are needed to produce virtual clones. */
if (cgraph_function_with_gimple_body_p (node) || has_analyzed_clone_p (node))
{
- /* Clones and thunks don't need to be read. */
+ /* Clones don't need to be read. */
if (node->clone_of)
return;
@@ -3006,7 +3006,6 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
VEC_safe_push (ipa_opt_pass, heap,
node->ipa_transforms_to_apply,
(ipa_opt_pass)&pass_ipa_inline);
- lto_symtab_free ();
timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
@@ -3035,7 +3034,6 @@ materialize_cgraph (void)
fprintf (stderr,
flag_wpa ? "Materializing decls:" : "Reading function bodies:");
-
/* Now that we have input the cgraph, we need to clear all of the aux
nodes and read the functions if we are not running in WPA mode. */
timevar_push (TV_IPA_LTO_GIMPLE_IN);
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 1dceb799dad..c21edcbb79d 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -104,6 +104,8 @@ eq_assembler_name (const void *p1, const void *p2)
static void
insert_to_assembler_name_hash (symtab_node node)
{
+ if (symtab_variable_p (node) && DECL_HARD_REGISTER (node->symbol.decl))
+ return;
gcc_checking_assert (!node->symbol.previous_sharing_asm_name
&& !node->symbol.next_sharing_asm_name);
if (assembler_name_hash)
@@ -151,9 +153,20 @@ unlink_from_assembler_name_hash (symtab_node node)
else
*slot = node->symbol.next_sharing_asm_name;
}
+ node->symbol.next_sharing_asm_name = NULL;
+ node->symbol.previous_sharing_asm_name = NULL;
}
}
+/* Arrange node to be first in its entry of assembler_name_hash. */
+
+void
+symtab_prevail_in_asm_name_hash (symtab_node node)
+{
+ unlink_from_assembler_name_hash (node);
+ insert_to_assembler_name_hash (node);
+}
+
/* Add node into symbol table. This function is not used directly, but via
cgraph/varpool node creation routines. */
@@ -287,15 +300,12 @@ symtab_remove_node (symtab_node node)
varpool_remove_node (varpool (node));
}
-/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
- Return NULL if there's no such node. */
+/* Initalize asm name hash unless. */
-symtab_node
-symtab_node_for_asm (const_tree asmname)
+void
+symtab_initialize_asm_name_hash (void)
{
symtab_node node;
- void **slot;
-
if (!assembler_name_hash)
{
assembler_name_hash =
@@ -304,7 +314,18 @@ symtab_node_for_asm (const_tree asmname)
FOR_EACH_SYMBOL (node)
insert_to_assembler_name_hash (node);
}
+}
+/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
+ Return NULL if there's no such node. */
+
+symtab_node
+symtab_node_for_asm (const_tree asmname)
+{
+ symtab_node node;
+ void **slot;
+
+ symtab_initialize_asm_name_hash ();
slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
decl_assembler_name_hash (asmname),
NO_INSERT);
@@ -507,6 +528,9 @@ dump_symtab_base (FILE *f, symtab_node node)
ipa_dump_references (f, &node->symbol.ref_list);
fprintf (f, " Referring: ");
ipa_dump_referring (f, &node->symbol.ref_list);
+ if (node->symbol.lto_file_data)
+ fprintf (f, " Read from file: %s\n",
+ node->symbol.lto_file_data->file_name);
}
/* Dump symtab node. */
@@ -597,7 +621,8 @@ verify_symtab_base (symtab_node node)
break;
hashed_node = hashed_node->symbol.next_sharing_asm_name;
}
- if (!hashed_node)
+ if (!hashed_node
+ && !(symtab_variable_p (node) || DECL_HARD_REGISTER (node->symbol.decl)))
{
error ("node not found in symtab assembler name hash");
error_found = true;
@@ -733,6 +758,8 @@ symtab_make_decl_local (tree decl)
DECL_COMDAT_GROUP (decl) = 0;
DECL_WEAK (decl) = 0;
DECL_EXTERNAL (decl) = 0;
+ DECL_VISIBILITY_SPECIFIED (decl) = 0;
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
TREE_PUBLIC (decl) = 0;
DECL_VISIBILITY_SPECIFIED (decl) = 0;
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
diff --git a/gcc/varpool.c b/gcc/varpool.c
index b0063c16328..314c66ee308 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -301,6 +301,10 @@ varpool_assemble_decl (struct varpool_node *node)
&& !targetm.have_tls)
return false;
+ /* Hard register vars do not need to be output. */
+ if (DECL_HARD_REGISTER (decl))
+ return false;
+
gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
&& TREE_CODE (decl) == VAR_DECL
&& !DECL_HAS_VALUE_EXPR_P (decl));