diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-09-19 10:01:56 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-09-19 10:01:56 +0000 |
commit | c9aa64535850aea75f19172b655ded1c72392c6d (patch) | |
tree | adf76d7fd51871b5c848e4b405009efc05ca3097 /gcc | |
parent | a2e26af78f7b7fcad53f80b5771264adf46586e2 (diff) | |
download | gcc-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/ChangeLog | 42 | ||||
-rw-r--r-- | gcc/cgraph.h | 25 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 5 | ||||
-rw-r--r-- | gcc/lto-streamer.h | 1 | ||||
-rw-r--r-- | gcc/lto-symtab.c | 510 | ||||
-rw-r--r-- | gcc/lto/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/lto/lto.c | 4 | ||||
-rw-r--r-- | gcc/symtab.c | 41 | ||||
-rw-r--r-- | gcc/varpool.c | 4 |
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)); |