From patchwork Wed Mar 2 10:07:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 85062 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A312BB711F for ; Wed, 2 Mar 2011 21:07:43 +1100 (EST) Received: (qmail 7861 invoked by alias); 2 Mar 2011 10:07:41 -0000 Received: (qmail 7851 invoked by uid 22791); 2 Mar 2011 10:07:39 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 02 Mar 2011 10:07:33 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id E96919AC871; Wed, 2 Mar 2011 11:07:30 +0100 (CET) Date: Wed, 2 Mar 2011 11:07:30 +0100 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: PR lto/47497 (undefined symbol when building soplex) Message-ID: <20110302100730.GA4958@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, the problem is with thunks referring thunks or aliases. lto-symtab is wrong here and when moving thunks&aliases associated with one node to the other node, it overwrites thunk.alias by the destination node. It consequently turns thunk referring another thunk into thunk referring the functoin itself. I fixed this by adding extra loop setting alias decl to prevailing decl. Richi, perhaps there is better place to put this? I don't like it being in the loop redirecting thunks&aliases from one node to another because 1) I think that loop is not quite correct. When one function is prevailed by another, local static thunk from the first function should not be redirected to another. That happens correctly and is harmless (we end up with dead thunk) 2) It may happen that thunks get prevailed other way than nodes they are aliased with. We use comdat groups that prevents this from happening, but I would rather not 100% rely on this on all targets since not all targets implements comdat groups. So I think it is more robust to simply merge the decls in alias field like we merge other decls. Fixing this problem cause different problem with streaming. When we have alias A referring function F and alias B referring alias A and we are unlucky with prevailing and other things, we might end up streaming alias B before alias A. This leads us to call cgraph_same_body_alias on decl of A before A is added to cgraph as an alias. Consequently cgraph_same_body_alias does nothing later when we try to create alias A itself, because the node already exists. This patch fixes it by adding node pointer into the cgraph_same_body_alias and cgraph_add_thunk so the thunks&aliases can be added in random order w/o problems as long as the function they are associated with is already in cgraph. Bootstraped/regtested x86_64-linux, also tested with Mozilla and qt build. Honza PR lto/47497 * lto-symtab.c (lto_cgraph_replace_node): Do not set thunk.alias. (lto_symtab_merge_cgraph_nodes_1): Update thunk.alias pointers here. * cgraph.h (cgraph_same_body_alias, cgraph_add_thunk): Add node pointers. * cgraph.c (cgraph_same_body_alias_1, cgraph_same_body_alias, cgraph_add_thunk): Add node pointers. * lto-cgraph.c (lto_output_node): Verify that thunks&aliases are associated to right node. (input_node): Update use of cgraph_same_body_alias and cgraph_add_thunk. * optimize.c (maybe_clone_body): Update call of cgraph_same_body_alias and cgraph_add_thunk. * method.c (make_alias_for_thunk, use_thunk): Likewise. * mangle.c (mangle_decl): Likewise. Index: lto-symtab.c =================================================================== --- lto-symtab.c (revision 170364) +++ lto-symtab.c (working copy) @@ -273,7 +273,6 @@ lto_cgraph_replace_node (struct cgraph_n last = alias; gcc_assert (alias->same_body_alias); alias->same_body = prevailing_node; - alias->thunk.alias = prevailing_node->decl; } last->next = prevailing_node->same_body; /* Node with aliases is prevailed by alias. @@ -828,8 +827,16 @@ lto_symtab_merge_cgraph_nodes_1 (void ** void lto_symtab_merge_cgraph_nodes (void) { + struct cgraph_node *node, *alias, *next; lto_symtab_maybe_init_hash_table (); htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL); + + for (node = cgraph_nodes; node; node = node->next) + for (alias = node->same_body; alias; alias = next) + { + next = alias->next; + alias->thunk.alias = lto_symtab_prevailing_decl (alias->thunk.alias); + } } /* Given the decl DECL, return the prevailing decl with the same name. */ Index: cgraph.h =================================================================== --- cgraph.h (revision 170364) +++ cgraph.h (working copy) @@ -559,8 +559,8 @@ struct cgraph_indirect_call_info *cgraph struct cgraph_node * cgraph_get_node (const_tree); struct cgraph_node * cgraph_get_node_or_alias (const_tree); struct cgraph_node * cgraph_node (tree); -struct cgraph_node * cgraph_same_body_alias (tree, tree); -struct cgraph_node * cgraph_add_thunk (tree, tree, bool, HOST_WIDE_INT, +struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree); +struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree); void cgraph_remove_same_body_alias (struct cgraph_node *); struct cgraph_node *cgraph_node_for_asm (tree); Index: cgraph.c =================================================================== --- cgraph.c (revision 170364) +++ cgraph.c (working copy) @@ -536,16 +536,16 @@ cgraph_node (tree decl) return node; } -/* Mark ALIAS as an alias to DECL. */ +/* Mark ALIAS as an alias to DECL. DECL_NODE is cgraph node representing + the function body is associated with (not neccesarily cgraph_node (DECL). */ static struct cgraph_node * -cgraph_same_body_alias_1 (tree alias, tree decl) +cgraph_same_body_alias_1 (struct cgraph_node *decl_node, tree alias, tree decl) { - struct cgraph_node key, *alias_node, *decl_node, **slot; + struct cgraph_node key, *alias_node, **slot; gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); gcc_assert (TREE_CODE (alias) == FUNCTION_DECL); - decl_node = cgraph_node (decl); key.decl = alias; @@ -575,7 +575,7 @@ cgraph_same_body_alias_1 (tree alias, tr and cgraph_node (ALIAS) transparently returns cgraph_node (DECL). */ struct cgraph_node * -cgraph_same_body_alias (tree alias, tree decl) +cgraph_same_body_alias (struct cgraph_node *decl_node, tree alias, tree decl) { #ifndef ASM_OUTPUT_DEF /* If aliases aren't supported by the assembler, fail. */ @@ -584,7 +584,7 @@ cgraph_same_body_alias (tree alias, tree /*gcc_assert (!assembler_name_hash);*/ - return cgraph_same_body_alias_1 (alias, decl); + return cgraph_same_body_alias_1 (decl_node, alias, decl); } /* Add thunk alias into callgraph. The alias declaration is ALIAS and it @@ -592,7 +592,8 @@ cgraph_same_body_alias (tree alias, tree See comments in thunk_adjust for detail on the parameters. */ struct cgraph_node * -cgraph_add_thunk (tree alias, tree decl, bool this_adjusting, +cgraph_add_thunk (struct cgraph_node *decl_node, tree alias, tree decl, + bool this_adjusting, HOST_WIDE_INT fixed_offset, HOST_WIDE_INT virtual_value, tree virtual_offset, tree real_alias) @@ -606,7 +607,7 @@ cgraph_add_thunk (tree alias, tree decl, cgraph_remove_node (node); } - node = cgraph_same_body_alias_1 (alias, decl); + node = cgraph_same_body_alias_1 (decl_node, alias, decl); gcc_assert (node); gcc_checking_assert (!virtual_offset || tree_int_cst_equal (virtual_offset, @@ -2722,7 +2723,7 @@ cgraph_propagate_frequency (struct cgrap case NODE_FREQUENCY_EXECUTED_ONCE: if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " Called by %s that is executed once\n", - cgraph_node_name (node)); + cgraph_node_name (edge->caller)); maybe_unlikely_executed = false; if (edge->loop_nest) { @@ -2735,7 +2736,7 @@ cgraph_propagate_frequency (struct cgrap case NODE_FREQUENCY_NORMAL: if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " Called by %s that is normal or hot\n", - cgraph_node_name (node)); + cgraph_node_name (edge->caller)); maybe_unlikely_executed = false; maybe_executed_once = false; break; Index: cp/optimize.c =================================================================== --- cp/optimize.c (revision 170364) +++ cp/optimize.c (working copy) @@ -309,7 +309,7 @@ maybe_clone_body (tree fn) && (!DECL_ONE_ONLY (fns[0]) || (HAVE_COMDAT_GROUP && DECL_WEAK (fns[0]))) - && cgraph_same_body_alias (clone, fns[0])) + && cgraph_same_body_alias (cgraph_node (fns[0]), clone, fns[0])) { alias = true; if (DECL_ONE_ONLY (fns[0])) Index: cp/method.c =================================================================== --- cp/method.c (revision 170364) +++ cp/method.c (working copy) @@ -259,7 +259,8 @@ make_alias_for_thunk (tree function) if (!flag_syntax_only) { - struct cgraph_node *aliasn = cgraph_same_body_alias (alias, function); + struct cgraph_node *aliasn = cgraph_same_body_alias (cgraph_node (function), + alias, function); DECL_ASSEMBLER_NAME (function); gcc_assert (aliasn != NULL); } @@ -376,7 +377,7 @@ use_thunk (tree thunk_fndecl, bool emit_ a = nreverse (t); DECL_ARGUMENTS (thunk_fndecl) = a; TREE_ASM_WRITTEN (thunk_fndecl) = 1; - cgraph_add_thunk (thunk_fndecl, function, + cgraph_add_thunk (cgraph_node (function), thunk_fndecl, function, this_adjusting, fixed_offset, virtual_value, virtual_offset, alias); Index: cp/mangle.c =================================================================== --- cp/mangle.c (revision 170364) +++ cp/mangle.c (working copy) @@ -3109,7 +3109,7 @@ mangle_decl (const tree decl) if (vague_linkage_p (decl)) DECL_WEAK (alias) = 1; if (TREE_CODE (decl) == FUNCTION_DECL) - cgraph_same_body_alias (alias, decl); + cgraph_same_body_alias (cgraph_node (decl), alias, decl); else varpool_extra_name_alias (alias, decl); #endif Index: lto-cgraph.c =================================================================== --- lto-cgraph.c (revision 170364) +++ lto-cgraph.c (working copy) @@ -551,6 +551,7 @@ lto_output_node (struct lto_simple_outpu lto_output_fn_decl_index (ob->decl_state, ob->main_stream, alias->thunk.alias); } + gcc_assert (cgraph_node (alias->thunk.alias) == node); lto_output_uleb128_stream (ob->main_stream, alias->resolution); alias = alias->previous; } @@ -1094,7 +1095,7 @@ input_node (struct lto_file_decl_data *f tree real_alias; decl_index = lto_input_uleb128 (ib); real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index); - alias = cgraph_same_body_alias (alias_decl, real_alias); + alias = cgraph_same_body_alias (node, alias_decl, real_alias); } else { @@ -1103,12 +1104,13 @@ input_node (struct lto_file_decl_data *f tree real_alias; decl_index = lto_input_uleb128 (ib); real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index); - alias = cgraph_add_thunk (alias_decl, fn_decl, type & 2, fixed_offset, + alias = cgraph_add_thunk (node, alias_decl, fn_decl, type & 2, fixed_offset, virtual_value, (type & 4) ? size_int (virtual_value) : NULL_TREE, real_alias); } - alias->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib); + gcc_assert (alias); + alias->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib); } return node; }