diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2018-02-06 14:27:04 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2018-02-06 13:27:04 +0000 |
commit | 43fbc2e9c46ad20a9566cc85f12ac24021f19ad3 (patch) | |
tree | 23b2060ac12fe84d4040f663cbf34a555f1840e8 /gcc/lto/lto.c | |
parent | b25e5572f1262ed0ec4beea19eec15ac28fdf8ed (diff) |
re PR lto/81004 (linking failed with -flto and static libboost_program_options)
PR lto/81004
* lto.c: Include builtins.h
(register_resolution): Merge resolutions in case trees was
merged across units.
(lto_maybe_register_decl): Break out from ...
(lto_read_decls): ... here.
(unify_scc): Also register decls here.
(read_cgraph_and_symbols): Sanity check that all resolutions was
read.
From-SVN: r257412
Diffstat (limited to 'gcc/lto/lto.c')
-rw-r--r-- | gcc/lto/lto.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index a8707d40c49..0ac8b1ef491 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "fold-const.h" #include "attribs.h" +#include "builtins.h" /* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */ @@ -830,12 +831,20 @@ static void register_resolution (struct lto_file_decl_data *file_data, tree decl, enum ld_plugin_symbol_resolution resolution) { + bool existed; if (resolution == LDPR_UNKNOWN) return; if (!file_data->resolution_map) file_data->resolution_map = new hash_map<tree, ld_plugin_symbol_resolution>; - file_data->resolution_map->put (decl, resolution); + ld_plugin_symbol_resolution_t &res + = file_data->resolution_map->get_or_insert (decl, &existed); + gcc_assert (!existed || res == resolution); + if (!existed + || resolution == LDPR_PREVAILING_DEF_IRONLY + || resolution == LDPR_PREVAILING_DEF + || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + res = resolution; } /* Register DECL with the global symbol table and change its @@ -878,6 +887,18 @@ lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl, decl, get_resolution (data_in, ix)); } +/* Check if T is a decl and needs register its resolution info. */ + +static void +lto_maybe_register_decl (struct data_in *data_in, tree t, unsigned ix) +{ + if (TREE_CODE (t) == VAR_DECL) + lto_register_var_decl_in_symtab (data_in, t, ix); + else if (TREE_CODE (t) == FUNCTION_DECL + && !DECL_BUILT_IN (t)) + lto_register_function_decl_in_symtab (data_in, t, ix); +} + /* For the type T re-materialize it in the type variant list and the pointer/reference-to chains. */ @@ -1617,7 +1638,10 @@ unify_scc (struct data_in *data_in, unsigned from, /* Fixup the streamer cache with the prevailing nodes according to the tree node mapping computed by compare_tree_sccs. */ if (len == 1) - streamer_tree_cache_replace_tree (cache, pscc->entries[0], from); + { + lto_maybe_register_decl (data_in, pscc->entries[0], from); + streamer_tree_cache_replace_tree (cache, pscc->entries[0], from); + } else { tree *map2 = XALLOCAVEC (tree, 2 * len); @@ -1625,6 +1649,7 @@ unify_scc (struct data_in *data_in, unsigned from, { map2[i*2] = (tree)(uintptr_t)(from + i); map2[i*2+1] = scc->entries[i]; + lto_maybe_register_decl (data_in, scc->entries[i], from + i); } qsort (map2, len, 2 * sizeof (tree), cmp_tree); qsort (map, len, 2 * sizeof (tree), cmp_tree); @@ -1761,13 +1786,7 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, cache_integer_cst (t); if (!flag_ltrans) { - /* Register variables and functions with the - symbol table. */ - if (TREE_CODE (t) == VAR_DECL) - lto_register_var_decl_in_symtab (data_in, t, from + i); - else if (TREE_CODE (t) == FUNCTION_DECL - && !DECL_BUILT_IN (t)) - lto_register_function_decl_in_symtab (data_in, t, from + i); + lto_maybe_register_decl (data_in, t, from + i); /* Scan the tree for references to global functions or variables and record those for later fixup. */ if (mentions_vars_p (t)) @@ -2873,13 +2892,21 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) /* Store resolutions into the symbol table. */ - ld_plugin_symbol_resolution_t *res; FOR_EACH_SYMBOL (snode) - if (snode->real_symbol_p () - && snode->lto_file_data - && snode->lto_file_data->resolution_map - && (res = snode->lto_file_data->resolution_map->get (snode->decl))) - snode->resolution = *res; + if (snode->externally_visible && snode->real_symbol_p () + && snode->lto_file_data && snode->lto_file_data->resolution_map + && !is_builtin_fn (snode->decl) + && !(VAR_P (snode->decl) && DECL_HARD_REGISTER (snode->decl))) + { + ld_plugin_symbol_resolution_t *res; + + res = snode->lto_file_data->resolution_map->get (snode->decl); + if (!res || *res == LDPR_UNKNOWN) + fatal_error (input_location, "missing resolution data for %s", + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (snode->decl))); + else + snode->resolution = *res; + } for (i = 0; all_file_decl_data[i]; i++) if (all_file_decl_data[i]->resolution_map) { |