Mercurial > hg > CbC > CbC_gcc
diff gcc/lto-symtab.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/lto-symtab.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/lto-symtab.c Mon May 24 12:47:05 2010 +0900 @@ -44,6 +44,9 @@ /* 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; @@ -62,6 +65,15 @@ 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 @@ -69,7 +81,7 @@ { const struct lto_symtab_entry_def *base = (const struct lto_symtab_entry_def *) p; - return htab_hash_string (IDENTIFIER_POINTER (base->id)); + return IDENTIFIER_HASH_VALUE (base->id); } /* Return non-zero if P1 and P2 points to lto_symtab_entry_def structs @@ -94,9 +106,10 @@ const struct lto_symtab_entry_def *base = (const struct lto_symtab_entry_def *) p; - /* Keep this only if the decl or the chain is marked. */ - return (ggc_marked_p (base->decl) - || (base->next && ggc_marked_p (base->next))); + /* 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. */ @@ -211,15 +224,8 @@ next = e->next_caller; cgraph_redirect_edge_callee (e, prevailing_node); } - - /* There are not supposed to be any outgoing edges from a node we - replace. Still this can happen for multiple instances of weak - functions. */ - for (e = node->callees; e; e = next) - { - next = e->next_callee; - cgraph_remove_edge (e); - } + /* Redirect incomming references. */ + ipa_clone_refering (prevailing_node, NULL, &node->ref_list); if (node->same_body) { @@ -244,6 +250,54 @@ cgraph_remove_node (node); } +/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging + all edges and removing the old node. */ + +static void +lto_varpool_replace_node (struct varpool_node *vnode, + struct varpool_node *prevailing_node) +{ + /* Merge node flags. */ + if (vnode->needed) + { + gcc_assert (!vnode->analyzed || prevailing_node->analyzed); + varpool_mark_needed_node (prevailing_node); + } + /* Relink aliases. */ + if (vnode->extra_name && !vnode->alias) + { + struct varpool_node *alias, *last; + for (alias = vnode->extra_name; + alias; alias = alias->next) + { + last = alias; + alias->extra_name = prevailing_node; + } + + if (prevailing_node->extra_name) + { + last->next = prevailing_node->extra_name; + prevailing_node->extra_name->prev = last; + } + prevailing_node->extra_name = vnode->extra_name; + vnode->extra_name = NULL; + } + gcc_assert (!vnode->finalized || prevailing_node->finalized); + gcc_assert (!vnode->analyzed || prevailing_node->analyzed); + + /* When replacing by an alias, the references goes to the original + variable. */ + if (prevailing_node->alias && prevailing_node->extra_name) + prevailing_node = prevailing_node->extra_name; + ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list); + + /* Be sure we can garbage collect the initializer. */ + if (DECL_INITIAL (vnode->decl)) + DECL_INITIAL (vnode->decl) = error_mark_node; + /* Finally remove the replaced node. */ + varpool_remove_node (vnode); +} + /* Merge two variable or function symbol table entries PREVAILING and ENTRY. Return false if the symbols are not fully compatible and a diagnostic should be emitted. */ @@ -383,11 +437,13 @@ /* A variable should have a size. */ else if (TREE_CODE (e->decl) == VAR_DECL) - return (DECL_SIZE (e->decl) != NULL_TREE - /* The C++ frontend retains TREE_STATIC on the declaration - of foo_ in struct Foo { static Foo *foo_; }; but it is - not a definition. g++.dg/lto/20090315_0.C. */ - && !DECL_EXTERNAL (e->decl)); + { + if (!e->vnode) + return false; + if (e->vnode->finalized) + return true; + return e->vnode->alias && e->vnode->extra_name->finalized; + } gcc_unreachable (); } @@ -406,6 +462,14 @@ { 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); + /* The LTO plugin for gold doesn't handle common symbols + properly. Let us choose manually. */ + if (DECL_COMMON (e->decl)) + e->resolution = LDPR_UNKNOWN; + } } e = (lto_symtab_entry_t) *slot; @@ -559,17 +623,22 @@ while (!prevailing->node && prevailing->next) prevailing = prevailing->next; - /* We do not stream varpool nodes, so the first decl has to - be good enough for now. - ??? For QOI choose a variable with readonly initializer - if there is one. This matches C++ - struct Foo { static const int i = 1; }; without a real - definition. */ + /* For variables chose with a priority variant with vnode + attached (i.e. from unit where external declaration of + variable is actually used). + When there are multiple variants, chose one with size. + 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) - while (!(TREE_READONLY (prevailing->decl) - && DECL_INITIAL (prevailing->decl)) - && prevailing->next) - prevailing = prevailing->next; + { + 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)))) + prevailing = e; + } } /* Move it first in the list. */ @@ -625,7 +694,8 @@ lto_symtab_merge_decls_2 (slot); /* Drop all but the prevailing decl from the symtab. */ - if (TREE_CODE (prevailing->decl) != FUNCTION_DECL) + if (TREE_CODE (prevailing->decl) != FUNCTION_DECL + && TREE_CODE (prevailing->decl) != VAR_DECL) prevailing->next = NULL; return 1; @@ -650,8 +720,6 @@ if (!prevailing->next) return 1; - gcc_assert (TREE_CODE (prevailing->decl) == FUNCTION_DECL); - /* Replace the cgraph node of each entry with the prevailing one. */ for (e = prevailing->next; e; e = e->next) { @@ -672,6 +740,8 @@ } lto_cgraph_replace_node (e->node, prevailing->node); } + if (e->vnode != NULL) + lto_varpool_replace_node (e->vnode, prevailing->vnode); } /* Drop all but the prevailing decl from the symtab. */