diff options
author | Jan Hubicka <jh@suse.cz> | 2020-03-20 22:06:24 +0100 |
---|---|---|
committer | Jan Hubicka <jh@suse.cz> | 2020-03-20 22:06:24 +0100 |
commit | 72b3bc895f023bf451357659cfe96c966945bdf9 (patch) | |
tree | b50df34185a414a85416a84b69ca390fa091d954 /gcc/cgraph.c | |
parent | a89349e664ff420f33612d47e486954de5848e49 (diff) | |
download | gcc-72b3bc895f023bf451357659cfe96c966945bdf9.zip gcc-72b3bc895f023bf451357659cfe96c966945bdf9.tar.gz gcc-72b3bc895f023bf451357659cfe96c966945bdf9.tar.bz2 |
Fix verifier ICE on wrong comdat local flag [PR93347]
gcc/ChangeLog:
2020-03-20 Jan Hubicka <hubicka@ucw.cz>
PR ipa/93347
* cgraph.c (symbol_table::create_edge): Update calls_comdat_local flag.
(cgraph_edge::redirect_callee): Move here; likewise.
(cgraph_node::remove_callees): Update calls_comdat_local flag.
(cgraph_node::verify_node): Verify that calls_comdat_local flag match
reality.
(cgraph_node::check_calls_comdat_local_p): New member function.
* cgraph.h (cgraph_node::check_calls_comdat_local_p): Declare.
(cgraph_edge::redirect_callee): Move offline.
* ipa-fnsummary.c (compute_fn_summary): Do not compute
calls_comdat_local flag here.
* ipa-inline-transform.c (inline_call): Fix updating of
calls_comdat_local flag.
* ipa-split.c (split_function): Use true instead of 1 to set the flag.
* symtab.c (symtab_node::add_to_same_comdat_group): Update
calls_comdat_local flag.
gcc/testsuite/ChangeLog:
2020-03-20 Jan Hubicka <hubicka@ucw.cz>
* g++.dg/torture/pr93347.C: New test.
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index b41dea1..6b780f8 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -557,7 +557,8 @@ cgraph_node::get_create (tree decl) } /* Mark ALIAS as an alias to DECL. DECL_NODE is cgraph node representing - the function body is associated with (not necessarily cgraph_node (DECL). */ + the function body is associated with + (not necessarily cgraph_node (DECL)). */ cgraph_node * cgraph_node::create_alias (tree alias, tree target) @@ -914,6 +915,10 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee, else edge->in_polymorphic_cdtor = caller->thunk.thunk_p; + if (callee && symtab->state != LTO_STREAMING + && edge->callee->comdat_local_p ()) + edge->caller->calls_comdat_local = true; + return edge; } @@ -1341,6 +1346,34 @@ cgraph_edge::make_direct (cgraph_edge *edge, cgraph_node *callee) return edge; } +/* Redirect callee of the edge to N. The function does not update underlying + call expression. */ + +void +cgraph_edge::redirect_callee (cgraph_node *n) +{ + bool loc = callee->comdat_local_p (); + /* Remove from callers list of the current callee. */ + remove_callee (); + + /* Insert to callers list of the new callee. */ + set_callee (n); + + if (!inline_failed) + return; + if (!loc && n->comdat_local_p ()) + { + cgraph_node *to = caller->inlined_to ? caller->inlined_to : caller; + to->calls_comdat_local = true; + } + else if (loc && !n->comdat_local_p ()) + { + cgraph_node *to = caller->inlined_to ? caller->inlined_to : caller; + gcc_checking_assert (to->calls_comdat_local); + to->calls_comdat_local = to->check_calls_comdat_local_p (); + } +} + /* If necessary, change the function declaration in the call statement associated with E so that it corresponds to the edge callee. Speculations can be resolved in the process and EDGE can be removed and deallocated. @@ -1674,6 +1707,8 @@ cgraph_node::remove_callees (void) { cgraph_edge *e, *f; + calls_comdat_local = false; + /* It is sufficient to remove the edges from the lists of callers of the callees. The callee list of the node can be zapped with one assignment. */ @@ -3369,10 +3404,18 @@ cgraph_node::verify_node (void) error ("inline clone is forced to output"); error_found = true; } - if (calls_comdat_local && !same_comdat_group) + if (symtab->state != LTO_STREAMING) { - error ("calls_comdat_local is set outside of a comdat group"); - error_found = true; + if (calls_comdat_local && !same_comdat_group) + { + error ("calls_comdat_local is set outside of a comdat group"); + error_found = true; + } + if (!inlined_to && calls_comdat_local != check_calls_comdat_local_p ()) + { + error ("invalid calls_comdat_local flag"); + error_found = true; + } } if (DECL_IS_MALLOC (decl) && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) @@ -4044,6 +4087,19 @@ cgraph_edge::num_speculative_call_targets_p (void) return indirect_info ? indirect_info->num_speculative_call_targets : 0; } +/* Check if function calls comdat local. This is used to recompute + calls_comdat_local flag after function transformations. */ +bool +cgraph_node::check_calls_comdat_local_p () +{ + for (cgraph_edge *e = callees; e; e = e->next_callee) + if (e->inline_failed + ? e->callee->comdat_local_p () + : e->callee->check_calls_comdat_local_p ()) + return true; + return false; +} + /* A stashed copy of "symtab" for use by selftest::symbol_table_test. This needs to be a global so that it can be a GC root, and thus prevent the stashed copy from being garbage-collected if the GC runs |