diff options
-rw-r--r-- | gcc/lto/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/lto/lto-symtab.c | 37 | ||||
-rw-r--r-- | gcc/lto/lto-symtab.h | 11 |
3 files changed, 54 insertions, 1 deletions
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index ac20a3f..1e509b1 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,10 @@ +2015-12-10 Jan Hubicka <hubicka@ucw.cz> + + PR lto/68878 + * lto-symtab.c (lto_symtab_prevailing_virtual_decl): New function. + * lto-symtab.h (lto_symtab_prevailing_virtual_decl): Declare. + (lto_symtab_prevailing_decl): Use it. + 2015-12-15 Ilya Verbin <ilya.verbin@intel.com> * lto.c: Include stringpool.h and fold-const.h. diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c index 35c690a..957fbf6 100644 --- a/gcc/lto/lto-symtab.c +++ b/gcc/lto/lto-symtab.c @@ -517,6 +517,8 @@ lto_symtab_merge_p (tree prevailing, tree decl) "TREE_CODE mismatch\n"); return false; } + gcc_checking_assert (TREE_CHAIN (prevailing) == TREE_CHAIN (decl)); + if (TREE_CODE (prevailing) == FUNCTION_DECL) { if (DECL_BUILT_IN (prevailing) != DECL_BUILT_IN (decl)) @@ -883,6 +885,11 @@ lto_symtab_merge_symbols_1 (symtab_node *prevailing) else { DECL_INITIAL (e->decl) = error_mark_node; + if (e->lto_file_data) + { + lto_free_function_in_decl_state_for_node (e); + e->lto_file_data = NULL; + } symtab->call_varpool_removal_hooks (dyn_cast<varpool_node *> (e)); } e->remove_all_references (); @@ -968,3 +975,33 @@ lto_symtab_merge_symbols (void) } } } + +/* Virtual tables may matter for code generation even if they are not + directly refernced by the code because they may be used for devirtualizaiton. + For this reason it is important to merge even virtual tables that have no + associated symbol table entries. Without doing so we lose optimization + oppurtunities by losing track of the vtable constructor. + FIXME: we probably ought to introduce explicit symbol table entries for + those before streaming. */ + +tree +lto_symtab_prevailing_virtual_decl (tree decl) +{ + gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl)) + && DECL_ASSEMBLER_NAME_SET_P (decl)); + + symtab_node *n = symtab_node::get_for_asmname + (DECL_ASSEMBLER_NAME (decl)); + while (n && ((!DECL_EXTERNAL (n->decl) && !TREE_PUBLIC (n->decl)) + || !DECL_VIRTUAL_P (n->decl))) + n = n->next_sharing_asm_name; + if (n) + { + lto_symtab_prevail_decl (n->decl, decl); + decl = n->decl; + } + else + symtab_node::get_create (decl); + + return decl; +} diff --git a/gcc/lto/lto-symtab.h b/gcc/lto/lto-symtab.h index c6b68b6..4c44631 100644 --- a/gcc/lto/lto-symtab.h +++ b/gcc/lto/lto-symtab.h @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see extern void lto_symtab_merge_decls (void); extern void lto_symtab_merge_symbols (void); extern tree lto_symtab_prevailing_decl (tree decl); +extern tree lto_symtab_prevailing_virtual_decl (tree decl); /* Mark DECL to be previailed by PREVAILING. Use DECL_ABSTRACT_ORIGIN and DECL_CHAIN as special markers; those do not @@ -31,6 +32,7 @@ inline void lto_symtab_prevail_decl (tree prevailing, tree decl) { gcc_checking_assert (DECL_ABSTRACT_ORIGIN (decl) != error_mark_node); + gcc_assert (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)); DECL_CHAIN (decl) = prevailing; DECL_ABSTRACT_ORIGIN (decl) = error_mark_node; } @@ -43,5 +45,12 @@ lto_symtab_prevailing_decl (tree decl) if (DECL_ABSTRACT_ORIGIN (decl) == error_mark_node) return DECL_CHAIN (decl); else - return decl; + { + if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) + && DECL_VIRTUAL_P (decl) + && (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)) + && !symtab_node::get (decl)) + return lto_symtab_prevailing_virtual_decl (decl); + return decl; + } } |