diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-01 13:08:53 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-01 13:08:53 +0000 |
commit | 48669653091db6b1a1e1ff6fa5c2acf65fdad761 (patch) | |
tree | 227ede588b4d6d5d96381098725519f26a853909 | |
parent | a47321b78ae92ae535fb3f3de0c05250c1c03068 (diff) | |
download | gcc-48669653091db6b1a1e1ff6fa5c2acf65fdad761.tar.gz |
* lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Rename to ...
(lto_symtab_merge_symbols_1): ... this one.
(lto_symtab_merge_cgraph_nodes): Rename to ...
(lto_symtab_merge_symbols): ... this one; simplify.
* cgraph.c (same_body_aliases_done): Rename to ...
(cpp_implicit_aliases_done): ... this one.
(cgraph_create_function_alias): Update.
(cgraph_same_body_alias): Update.
(dump_cgraph_node): Remove alias dumping; simplify
thunk dumping.
(verify_edge_corresponds_to_fndecl): Simplify.
* cgraph.h (symtab_node_base): Add cpp_implicit_alias,
alias_target.
(cgraph_node): Remove same_body_alias.
(varpool_node): Remove alias_of and extra_name_alias.
(same_body_aliases_done): Rename to ..
(cpp_implicit_aliases_done): ... this one.
(symtab_alias_ultimate_target): Add default parameter.
(symtab_resolve_alias): New function.
(fixup_same_cpp_alias_visibility): Declare.
(cgraph_function_node): Add default parameter.
(cgraph_node_asm_name): Likewise.
(cgraph_function_or_thunk_node): Add default parameter; do
not ICE when it is NULL.
(varpool_variable_node): Likewise.
* tree-emutls.c (create_emultls_var): Update.
(ipa_lower_emutls): Update.
* cgraphunit.c (cgraph_decide_is_function_needed): Update.
(cgraph_reset_node): Reset alias info.
(cgraph_finalize_function): Update.
(fixup_same_cpp_alias_visibility): Move to symtab.c.
(analyze_function): Simplify.
(cgraph_process_same_body_aliases): Simplify.
(analyze_functions): Fixup same body aliases.
(handle_alias_pairs): Simplify.
(assemble_thunk): Update.
(assemble_thunks_and_aliases): Update.
(output_weakrefs): Rewrite.
* lto-cgraph.c (lto_output_node): Rewrite alias handling.
(lto_output_varpool_node): Likewise.
(compute_ltrans_boundary): Remve assert.
(get_alias_symbol): New functoin.
(input_node): Rewrite alias handling.
(input_varpool_node): Likewise.
* ipa-pure-const.c (propagate_pure_const): Fix formating.
* ipa.c (process_references): Handle weakrefs correctly.
(symtab_remove_unreachable_nodes): Likewise.
* trans-mem.c (get_cg_data): Update.
(ipa_tm_create_version_alias): Update.
(ipa_tm_execute): Update.
* symtab.c (dump_symtab_base): Dump aliases.
(verify_symtab_base): Verify aliases.
(symtab_node_availability): New function.
(symtab_alias_ultimate_target): Simplify.
(fixup_same_cpp_alias_visibility): Move here from cgraphunit.c;
handle all the fixup cases.
(symtab_resolve_alias): New function.
* passes.c (ipa_write_summaries): Handle weakrefs.
* varpool.c (varpool_analyze_node): Simplify.
(assemble_aliases): Update.
(varpool_create_variable_alias): Simplify.
(varpool_extra_name_alias): Simplify.
* lto-streamer.h (lto_symtab_merge_cgraph_nodes): Rename to...
(lto_symtab_merge_symbols): ... this one.
* decl2.c (cp_write_global_declarations): Replace same_body_alias
by symbol.cpp_implicit_alias.
* lto.c (read_cgraph_and_symbols): Simplify dumping; Replace
lto_symtab_merge_cgraph_nodes by lto_symtab_merge_symbols.
(do_whole_program_analysis): Update dumping.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199577 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 67 | ||||
-rw-r--r-- | gcc/cgraph.c | 36 | ||||
-rw-r--r-- | gcc/cgraph.h | 45 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 145 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/ipa-pure-const.c | 2 | ||||
-rw-r--r-- | gcc/ipa.c | 5 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 62 | ||||
-rw-r--r-- | gcc/lto-streamer.h | 2 | ||||
-rw-r--r-- | gcc/lto-symtab.c | 92 | ||||
-rw-r--r-- | gcc/lto/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/lto/lto.c | 13 | ||||
-rw-r--r-- | gcc/passes.c | 7 | ||||
-rw-r--r-- | gcc/symtab.c | 133 | ||||
-rw-r--r-- | gcc/trans-mem.c | 6 | ||||
-rw-r--r-- | gcc/tree-emutls.c | 8 | ||||
-rw-r--r-- | gcc/varpool.c | 52 |
18 files changed, 384 insertions, 304 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1da3462ed40..c6a7d7dce6f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,70 @@ +2013-06-01 Jan Hubicka <jh@suse.cz> + + * lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Rename to ... + (lto_symtab_merge_symbols_1): ... this one. + (lto_symtab_merge_cgraph_nodes): Rename to ... + (lto_symtab_merge_symbols): ... this one; simplify. + * cgraph.c (same_body_aliases_done): Rename to ... + (cpp_implicit_aliases_done): ... this one. + (cgraph_create_function_alias): Update. + (cgraph_same_body_alias): Update. + (dump_cgraph_node): Remove alias dumping; simplify + thunk dumping. + (verify_edge_corresponds_to_fndecl): Simplify. + * cgraph.h (symtab_node_base): Add cpp_implicit_alias, + alias_target. + (cgraph_node): Remove same_body_alias. + (varpool_node): Remove alias_of and extra_name_alias. + (same_body_aliases_done): Rename to .. + (cpp_implicit_aliases_done): ... this one. + (symtab_alias_ultimate_target): Add default parameter. + (symtab_resolve_alias): New function. + (fixup_same_cpp_alias_visibility): Declare. + (cgraph_function_node): Add default parameter. + (cgraph_node_asm_name): Likewise. + (cgraph_function_or_thunk_node): Add default parameter; do + not ICE when it is NULL. + (varpool_variable_node): Likewise. + * tree-emutls.c (create_emultls_var): Update. + (ipa_lower_emutls): Update. + * cgraphunit.c (cgraph_decide_is_function_needed): Update. + (cgraph_reset_node): Reset alias info. + (cgraph_finalize_function): Update. + (fixup_same_cpp_alias_visibility): Move to symtab.c. + (analyze_function): Simplify. + (cgraph_process_same_body_aliases): Simplify. + (analyze_functions): Fixup same body aliases. + (handle_alias_pairs): Simplify. + (assemble_thunk): Update. + (assemble_thunks_and_aliases): Update. + (output_weakrefs): Rewrite. + * lto-cgraph.c (lto_output_node): Rewrite alias handling. + (lto_output_varpool_node): Likewise. + (compute_ltrans_boundary): Remve assert. + (get_alias_symbol): New functoin. + (input_node): Rewrite alias handling. + (input_varpool_node): Likewise. + * ipa-pure-const.c (propagate_pure_const): Fix formating. + * ipa.c (process_references): Handle weakrefs correctly. + (symtab_remove_unreachable_nodes): Likewise. + * trans-mem.c (get_cg_data): Update. + (ipa_tm_create_version_alias): Update. + (ipa_tm_execute): Update. + * symtab.c (dump_symtab_base): Dump aliases. + (verify_symtab_base): Verify aliases. + (symtab_node_availability): New function. + (symtab_alias_ultimate_target): Simplify. + (fixup_same_cpp_alias_visibility): Move here from cgraphunit.c; + handle all the fixup cases. + (symtab_resolve_alias): New function. + * passes.c (ipa_write_summaries): Handle weakrefs. + * varpool.c (varpool_analyze_node): Simplify. + (assemble_aliases): Update. + (varpool_create_variable_alias): Simplify. + (varpool_extra_name_alias): Simplify. + * lto-streamer.h (lto_symtab_merge_cgraph_nodes): Rename to... + (lto_symtab_merge_symbols): ... this one. + 2013-06-01 Dinar Temirbulatov <dinar@kugelworks.com> Revert diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 735f48a8891..445282a4c52 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -129,7 +129,7 @@ static GTY(()) struct cgraph_node *free_nodes; static GTY(()) struct cgraph_edge *free_edges; /* Did procss_same_body_aliases run? */ -bool same_body_aliases_done; +bool cpp_implicit_aliases_done; /* Map a cgraph_node to cgraph_function_version_info using this htab. The cgraph_function_version_info has a THIS_NODE field that is the @@ -556,15 +556,16 @@ cgraph_get_create_node (tree decl) the function body is associated with (not necessarily cgraph_node (DECL). */ struct cgraph_node * -cgraph_create_function_alias (tree alias, tree decl) +cgraph_create_function_alias (tree alias, tree target) { struct cgraph_node *alias_node; - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + gcc_assert (TREE_CODE (target) == FUNCTION_DECL + || TREE_CODE (target) == IDENTIFIER_NODE); gcc_assert (TREE_CODE (alias) == FUNCTION_DECL); alias_node = cgraph_get_create_node (alias); gcc_assert (!alias_node->symbol.definition); - alias_node->thunk.alias = decl; + alias_node->symbol.alias_target = target; alias_node->symbol.definition = true; alias_node->symbol.alias = true; return alias_node; @@ -589,10 +590,10 @@ cgraph_same_body_alias (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, tree ali return NULL; n = cgraph_create_function_alias (alias, decl); - n->same_body_alias = true; - if (same_body_aliases_done) - ipa_record_reference ((symtab_node)n, (symtab_node)cgraph_get_node (decl), - IPA_REF_ALIAS, NULL); + n->symbol.cpp_implicit_alias = true; + if (cpp_implicit_aliases_done) + symtab_resolve_alias ((symtab_node)n, + (symtab_node)cgraph_get_node (decl)); return n; } @@ -1545,10 +1546,13 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) if (node->thunk.thunk_p) { - fprintf (f, " Thunk of %s (asm: %s) fixed offset %i virtual value %i has " + fprintf (f, " Thunk"); + if (node->thunk.alias) + fprintf (f, " of %s (asm: %s)", + lang_hooks.decl_printable_name (node->thunk.alias, 2), + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->thunk.alias))); + fprintf (f, " fixed offset %i virtual value %i has " "virtual offset %i)\n", - lang_hooks.decl_printable_name (node->thunk.alias, 2), - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->thunk.alias)), (int)node->thunk.fixed_offset, (int)node->thunk.virtual_value, (int)node->thunk.virtual_offset_p); @@ -2288,17 +2292,11 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl) return false; node = cgraph_function_or_thunk_node (node, NULL); - if ((e->callee->former_clone_of != node->symbol.decl - && (!node->same_body_alias - || e->callee->former_clone_of != node->thunk.alias)) + if (e->callee->former_clone_of != node->symbol.decl /* IPA-CP sometimes redirect edge to clone and then back to the former function. This ping-pong has to go, eventually. */ && (node != cgraph_function_or_thunk_node (e->callee, NULL)) - && !clone_of_p (node, e->callee) - /* If decl is a same body alias of some other decl, allow e->callee to be - a clone of a clone of that other decl too. */ - && (!node->same_body_alias - || !clone_of_p (cgraph_get_node (node->thunk.alias), e->callee))) + && !clone_of_p (cgraph_function_or_thunk_node (node, NULL), e->callee)) return true; else return false; diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 0dcc1a691df..276e568230e 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -56,6 +56,13 @@ struct GTY(()) symtab_node_base /* True when symbol is an alias. Set by assemble_alias. */ unsigned alias : 1; + /* C++ frontend produce same body aliases and extra name aliases for + virutal functions and vtables that are obviously equivalent. + Those aliases are bit special, especially because C++ frontend + visibility code is so ugly it can not get them right at first time + and their visibility needs to be copied from their "masters" at + the end of parsing. */ + unsigned cpp_implicit_alias : 1; /* Set once the definition was analyzed. The list of references and other properties are built during analysis. */ unsigned analyzed : 1; @@ -119,6 +126,11 @@ struct GTY(()) symtab_node_base /* Vectors of referring and referenced entities. */ struct ipa_ref_list ref_list; + /* Alias target. May be either DECL pointer or ASSEMBLER_NAME pointer + depending to what was known to frontend on the creation time. + Once alias is resolved, this pointer become NULL. */ + tree alias_target; + /* File stream where this node is being written to. */ struct lto_file_decl_data * lto_file_data; @@ -291,8 +303,6 @@ struct GTY(()) cgraph_node { /* Set once the function has been instantiated and its callee lists created. */ unsigned process : 1; - /* Set for aliases created as C++ same body aliases. */ - unsigned same_body_alias : 1; /* How commonly executed the node is. Initialized during branch probabilities pass. */ ENUM_BITFIELD (node_frequency) frequency : 2; @@ -478,12 +488,9 @@ typedef struct cgraph_edge *cgraph_edge_p; struct GTY(()) varpool_node { struct symtab_node_base symbol; - /* For aliases points to declaration DECL is alias of. */ - tree alias_of; /* Set when variable is scheduled to be assembled. */ unsigned output : 1; - unsigned extra_name_alias : 1; }; /* Every top level asm statement is put into a asm_node. */ @@ -553,7 +560,7 @@ extern cgraph_node_set cgraph_new_nodes; extern GTY(()) struct asm_node *asm_nodes; extern GTY(()) int symtab_order; -extern bool same_body_aliases_done; +extern bool cpp_implicit_aliases_done; /* In symtab.c */ void symtab_register_node (symtab_node); @@ -576,7 +583,10 @@ void verify_symtab_node (symtab_node); bool verify_symtab_base (symtab_node); bool symtab_used_from_object_file_p (symtab_node); void symtab_make_decl_local (tree); -symtab_node symtab_alias_ultimate_target (symtab_node, enum availability *); +symtab_node symtab_alias_ultimate_target (symtab_node, + enum availability *avail = NULL); +bool symtab_resolve_alias (symtab_node node, symtab_node target); +void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target); /* In cgraph.c */ void dump_cgraph (FILE *); @@ -672,7 +682,8 @@ struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_ho void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *); gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *); bool cgraph_propagate_frequency (struct cgraph_node *node); -struct cgraph_node * cgraph_function_node (struct cgraph_node *, enum availability *); +struct cgraph_node * cgraph_function_node (struct cgraph_node *, + enum availability *avail = NULL); /* In cgraphunit.c */ struct asm_node *add_asm_node (tree); @@ -822,7 +833,7 @@ varpool_get_node (const_tree decl) /* Return asm name of cgraph node. */ static inline const char * -cgraph_node_asm_name(struct cgraph_node *node) +cgraph_node_asm_name (struct cgraph_node *node) { return symtab_node_asm_name ((symtab_node)node); } @@ -1258,12 +1269,14 @@ varpool_alias_target (struct varpool_node *n) When AVAILABILITY is non-NULL, get minimal availability in the chain. */ static inline struct cgraph_node * -cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability) +cgraph_function_or_thunk_node (struct cgraph_node *node, + enum availability *availability = NULL) { struct cgraph_node *n; - n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node, availability)); - if (!n) + n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node, + availability)); + if (!n && availability) *availability = AVAIL_NOT_AVAILABLE; return n; } @@ -1272,12 +1285,14 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *avai When AVAILABILITY is non-NULL, get minimal availability in the chain. */ static inline struct varpool_node * -varpool_variable_node (struct varpool_node *node, enum availability *availability) +varpool_variable_node (struct varpool_node *node, + enum availability *availability = NULL) { struct varpool_node *n; - n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node, availability)); - if (!n) + n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node, + availability)); + if (!n && availability) *availability = AVAIL_NOT_AVAILABLE; return n; } diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index ca314a68476..76ef876aa47 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -231,8 +231,7 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl) /* Double check that no one output the function into assembly file early. */ gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl) - || (node->thunk.thunk_p || node->same_body_alias) - || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); + || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); /* Keep constructors, destructors and virtual functions. */ @@ -370,6 +369,8 @@ cgraph_reset_node (struct cgraph_node *node) memset (&node->rtl, 0, sizeof (node->rtl)); node->symbol.analyzed = false; node->symbol.definition = false; + node->symbol.alias = false; + node->symbol.cpp_implicit_alias = false; cgraph_node_remove_callees (node); ipa_remove_all_references (&node->symbol.ref_list); @@ -426,7 +427,7 @@ cgraph_finalize_function (tree decl, bool nested) in the original implementation and it is unclear whether we want to change the behavior here. */ if ((!optimize - && !node->same_body_alias + && !node->symbol.cpp_implicit_alias && !DECL_DISREGARD_INLINE_LIMITS (decl) && !DECL_DECLARED_INLINE_P (decl) && !(DECL_CONTEXT (decl) @@ -573,22 +574,6 @@ output_asm_statements (void) asm_nodes = NULL; } -/* C++ FE sometimes change linkage flags after producing same body aliases. */ -void -fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias) -{ - DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (alias); - if (TREE_PUBLIC (node->symbol.decl)) - { - DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (alias); - DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (alias); - DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (alias); - if (DECL_ONE_ONLY (alias) - && !node->symbol.same_comdat_group) - symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target); - } -} - /* Analyze the function scheduled to be output. */ static void analyze_function (struct cgraph_node *node) @@ -597,39 +582,14 @@ analyze_function (struct cgraph_node *node) location_t saved_loc = input_location; input_location = DECL_SOURCE_LOCATION (decl); - if (node->symbol.alias && node->thunk.alias) - { - struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias); - struct cgraph_node *n; - - for (n = tgt; n && n->symbol.alias; - n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL) - if (n == node) - { - error ("function %q+D part of alias cycle", node->symbol.decl); - node->symbol.alias = false; - input_location = saved_loc; - return; - } - if (!vec_safe_length (node->symbol.ref_list.references)) - ipa_record_reference ((symtab_node)node, (symtab_node)tgt, - IPA_REF_ALIAS, NULL); - if (node->same_body_alias) - { - DECL_DECLARED_INLINE_P (node->symbol.decl) - = DECL_DECLARED_INLINE_P (node->thunk.alias); - DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) - = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias); - fixup_same_cpp_alias_visibility ((symtab_node) node, (symtab_node) tgt, node->thunk.alias); - } - - if (node->symbol.address_taken) - cgraph_mark_address_taken_node (cgraph_alias_target (node)); - } + if (node->symbol.alias) + symtab_resolve_alias + ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target)); else if (node->thunk.thunk_p) { cgraph_create_edge (node, cgraph_get_node (node->thunk.alias), NULL, 0, CGRAPH_FREQ_BASE); + node->thunk.alias = NULL; } else if (node->dispatcher_function) { @@ -693,16 +653,12 @@ analyze_function (struct cgraph_node *node) void cgraph_process_same_body_aliases (void) { - struct cgraph_node *node; - FOR_EACH_FUNCTION (node) - if (node->same_body_alias - && !vec_safe_length (node->symbol.ref_list.references)) - { - struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias); - ipa_record_reference ((symtab_node)node, (symtab_node)tgt, - IPA_REF_ALIAS, NULL); - } - same_body_aliases_done = true; + symtab_node node; + FOR_EACH_SYMBOL (node) + if (node->symbol.cpp_implicit_alias && !node->symbol.analyzed) + symtab_resolve_alias (node, + symtab_get_node (node->symbol.alias_target)); + cpp_implicit_aliases_done = true; } /* Process attributes common for vars and functions. */ @@ -890,6 +846,13 @@ analyze_functions (void) bitmap_obstack_initialize (NULL); cgraph_state = CGRAPH_STATE_CONSTRUCTION; + /* Ugly, but the fixup can not happen at a time same body alias is created; + C++ FE is confused about the COMDAT groups being right. */ + if (cpp_implicit_aliases_done) + FOR_EACH_SYMBOL (node) + if (node->symbol.cpp_implicit_alias) + fixup_same_cpp_alias_visibility (node, symtab_alias_target (node)); + /* Analysis adds static variables that in turn adds references to new functions. So we need to iterate the process until it stabilize. */ while (changed) @@ -940,7 +903,7 @@ analyze_functions (void) and later using weak alias attribute to kill its body. See gcc.c-torture/compile/20011119-1.c */ if (!DECL_STRUCT_FUNCTION (decl) - && (!cnode->symbol.alias || !cnode->thunk.alias) + && !cnode->symbol.alias && !cnode->thunk.thunk_p && !cnode->dispatcher_function) { @@ -970,7 +933,7 @@ analyze_functions (void) else { varpool_node *vnode = dyn_cast <varpool_node> (node); - if (vnode && vnode->symbol.definition) + if (vnode && vnode->symbol.definition && !vnode->symbol.analyzed) varpool_analyze_node (vnode); } @@ -1016,7 +979,7 @@ analyze_functions (void) tree decl = node->symbol.decl; if (cnode->symbol.definition && !gimple_has_body_p (decl) - && (!cnode->symbol.alias || !cnode->thunk.alias) + && !cnode->symbol.alias && !cnode->thunk.thunk_p) cgraph_reset_node (cnode); @@ -1057,17 +1020,11 @@ handle_alias_pairs (void) to later output the weakref pseudo op into asm file. */ if (!target_node && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL) { - if (TREE_CODE (p->decl) == FUNCTION_DECL) - { - struct cgraph_node *anode = cgraph_get_create_node (p->decl); - anode->symbol.alias = true; - anode->thunk.alias = p->target; - } - else + symtab_node node = symtab_get_node (p->decl); + if (node) { - struct varpool_node *anode = varpool_get_node (p->decl); - anode->symbol.alias = true; - anode->alias_of = p->target; + node->symbol.alias_target = p->target; + node->symbol.alias = true; } DECL_EXTERNAL (p->decl) = 1; alias_pairs->unordered_remove (i); @@ -1380,7 +1337,7 @@ assemble_thunk (struct cgraph_node *node) HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset; HOST_WIDE_INT virtual_value = node->thunk.virtual_value; tree virtual_offset = NULL; - tree alias = node->thunk.alias; + tree alias = node->callees->callee->symbol.decl; tree thunk_fndecl = node->symbol.decl; tree a = DECL_ARGUMENTS (thunk_fndecl); @@ -1581,15 +1538,15 @@ assemble_thunks_and_aliases (struct cgraph_node *node) if (ref->use == IPA_REF_ALIAS) { struct cgraph_node *alias = ipa_ref_referring_node (ref); - bool saved_written = TREE_ASM_WRITTEN (alias->thunk.alias); + bool saved_written = TREE_ASM_WRITTEN (node->symbol.decl); /* Force assemble_alias to really output the alias this time instead of buffering it in same alias pairs. */ - TREE_ASM_WRITTEN (alias->thunk.alias) = 1; + TREE_ASM_WRITTEN (node->symbol.decl) = 1; do_assemble_alias (alias->symbol.decl, - DECL_ASSEMBLER_NAME (alias->thunk.alias)); + DECL_ASSEMBLER_NAME (node->symbol.decl)); assemble_thunks_and_aliases (alias); - TREE_ASM_WRITTEN (alias->thunk.alias) = saved_written; + TREE_ASM_WRITTEN (node->symbol.decl) = saved_written; } } @@ -1929,22 +1886,32 @@ get_alias_symbol (tree decl) static void output_weakrefs (void) { - struct cgraph_node *node; - struct varpool_node *vnode; - FOR_EACH_FUNCTION (node) + symtab_node node; + FOR_EACH_SYMBOL (node) if (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl) && !TREE_ASM_WRITTEN (node->symbol.decl) && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl))) - do_assemble_alias (node->symbol.decl, - node->thunk.alias && DECL_P (node->thunk.alias) ? DECL_ASSEMBLER_NAME (node->thunk.alias) - : get_alias_symbol (node->symbol.decl)); - FOR_EACH_VARIABLE (vnode) - if (vnode->symbol.alias && DECL_EXTERNAL (vnode->symbol.decl) - && !TREE_ASM_WRITTEN (vnode->symbol.decl) - && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl))) - do_assemble_alias (vnode->symbol.decl, - vnode->alias_of && DECL_P (vnode->alias_of) ? DECL_ASSEMBLER_NAME (vnode->alias_of) - : get_alias_symbol (vnode->symbol.decl)); + { + tree target; + + /* Weakrefs are special by not requiring target definition in current + compilation unit. It is thus bit hard to work out what we want to + alias. + When alias target is defined, we need to fetch it from symtab reference, + otherwise it is pointed to by alias_target. */ + if (node->symbol.alias_target) + target = (DECL_P (node->symbol.alias_target) + ? DECL_ASSEMBLER_NAME (node->symbol.alias_target) + : node->symbol.alias_target); + else if (node->symbol.analyzed) + target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl); + else + { + gcc_unreachable (); + target = get_alias_symbol (node->symbol.decl); + } + do_assemble_alias (node->symbol.decl, target); + } } /* Initialize callgraph dump file. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ae2c174754e..8dc30f986c5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2013-06-01 Jan Hubicka <jh@suse.cz> + + * decl2.c (cp_write_global_declarations): Replace same_body_alias + by symbol.cpp_implicit_alias. + 2013-05-30 Jason Merrill <jason@redhat.com> PR c++/57404 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 409a7436dca..3fe234e6f09 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4201,7 +4201,7 @@ cp_write_global_declarations (void) struct cgraph_node *node, *next; node = cgraph_get_node (decl); - if (node->same_body_alias) + if (node->symbol.cpp_implicit_alias) node = cgraph_alias_target (node); cgraph_for_node_and_aliases (node, clear_decl_external, diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index c6c41c6657a..9705db19e12 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -1110,7 +1110,7 @@ propagate_pure_const (void) if (dump_file) { dump_cgraph (dump_file); - ipa_print_order(dump_file, "reduced", order, order_pos); + ipa_print_order (dump_file, "reduced", order, order_pos); } /* Propagate the local information through the call graph to produce diff --git a/gcc/ipa.c b/gcc/ipa.c index 254c09fa4fb..5382b7a8f31 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -139,8 +139,7 @@ process_references (struct ipa_ref_list *list, symtab_node node = ref->referred; if (node->symbol.definition - && (!DECL_EXTERNAL (node->symbol.decl) - || node->symbol.alias + && ((!DECL_EXTERNAL (node->symbol.decl) || node->symbol.alias) || (before_inlining_p /* We use variable constructors during late complation for constant folding. Keep references alive so partitioning @@ -297,7 +296,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) if (e->callee->symbol.definition && (!e->inline_failed || !DECL_EXTERNAL (e->callee->symbol.decl) - || cnode->symbol.alias + || e->callee->symbol.alias || before_inlining_p)) pointer_set_insert (reachable, e->callee); enqueue_node ((symtab_node) e->callee, &first, reachable); diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 2268f240804..6699b8aa2ff 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -377,6 +377,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, struct cgraph_node *clone_of; struct ipa_opt_pass_d *pass; int i; + bool alias_p; boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node); @@ -485,7 +486,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, defined in other unit, we may use the info on aliases to resolve symbol1 != symbol2 type tests that we can do only for locally defined objects otherwise. */ - bp_pack_value (&bp, node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1); + alias_p = node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)); + bp_pack_value (&bp, alias_p, 1); bp_pack_value (&bp, node->frequency, 2); bp_pack_value (&bp, node->only_called_at_startup, 1); bp_pack_value (&bp, node->only_called_at_exit, 1); @@ -504,15 +506,6 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset); streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value); } - if ((node->symbol.alias || node->thunk.thunk_p) - && (!boundary_p || (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl)))) - { - streamer_write_hwi_in_range (ob->main_stream, 0, 1, - node->thunk.alias != NULL); - if (node->thunk.alias != NULL) - lto_output_fn_decl_index (ob->decl_state, ob->main_stream, - node->thunk.alias); - } } /* Output the varpool NODE to OB. @@ -522,10 +515,10 @@ static void lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node, lto_symtab_encoder_t encoder) { - bool boundary_p = (node->symbol.definition - && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node)); + bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node); struct bitpack_d bp; int ref; + bool alias_p; streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, LTO_symtab_variable); @@ -536,8 +529,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node bp_pack_value (&bp, node->symbol.force_output, 1); bp_pack_value (&bp, node->symbol.unique_name, 1); bp_pack_value (&bp, node->symbol.definition, 1); - bp_pack_value (&bp, node->symbol.alias, 1); - bp_pack_value (&bp, node->alias_of != NULL, 1); + alias_p = node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)); + bp_pack_value (&bp, alias_p, 1); + bp_pack_value (&bp, node->symbol.analyzed && !boundary_p, 1); gcc_assert (node->symbol.definition || !node->symbol.analyzed); /* Constant pool initializers can be de-unified into individual ltrans units. FIXME: Alternatively at -Os we may want to avoid generating for them the local @@ -554,12 +548,11 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node bp_pack_value (&bp, node->symbol.definition && referenced_from_other_partition_p (&node->symbol.ref_list, encoder), 1); - bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1); + bp_pack_value (&bp, node->symbol.analyzed + && boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1); /* in_other_partition. */ } streamer_write_bitpack (&bp); - if (node->alias_of) - lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of); if (node->symbol.same_comdat_group && !boundary_p) { ref = lto_symtab_encoder_lookup (encoder, @@ -756,7 +749,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei)) { struct varpool_node *vnode = lsei_varpool_node (lsei); - gcc_assert (!vnode->symbol.alias || vnode->alias_of); + lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); lto_set_symtab_encoder_encode_initializer (encoder, vnode); add_references (encoder, &vnode->symbol.ref_list); @@ -919,6 +912,17 @@ input_overwrite_node (struct lto_file_decl_data *file_data, LDPR_NUM_KNOWN); } +/* Return string alias is alias of. */ + +static tree +get_alias_symbol (tree decl) +{ + tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)); + gcc_assert (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))); + return get_identifier (TREE_STRING_POINTER + (TREE_VALUE (TREE_VALUE (alias)))); +} + /* Read a node from input_block IB. TAG is the node's tag just read. Return the node read or overwriten. */ @@ -1004,15 +1008,8 @@ input_node (struct lto_file_decl_data *file_data, node->thunk.virtual_value = virtual_value; node->thunk.virtual_offset_p = (type & 4); } - if (node->thunk.thunk_p || node->symbol.alias) - { - if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1)) - { - decl_index = streamer_read_uhwi (ib); - node->thunk.alias = lto_file_decl_data_get_fn_decl (file_data, - decl_index); - } - } + if (node->symbol.alias && !node->symbol.analyzed) + node->symbol.alias_target = get_alias_symbol (node->symbol.decl); return node; } @@ -1028,7 +1025,6 @@ input_varpool_node (struct lto_file_decl_data *file_data, struct varpool_node *node; struct bitpack_d bp; int ref = LCC_NOT_FOUND; - bool non_null_aliasof; int order; order = streamer_read_hwi (ib) + order_base; @@ -1046,20 +1042,16 @@ input_varpool_node (struct lto_file_decl_data *file_data, node->symbol.unique_name = bp_unpack_value (&bp, 1); node->symbol.definition = bp_unpack_value (&bp, 1); node->symbol.alias = bp_unpack_value (&bp, 1); - non_null_aliasof = bp_unpack_value (&bp, 1); + node->symbol.analyzed = bp_unpack_value (&bp, 1); node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1); node->symbol.in_other_partition = bp_unpack_value (&bp, 1); - node->symbol.analyzed = (node->symbol.definition && (!node->symbol.alias || !node->symbol.in_other_partition)); if (node->symbol.in_other_partition) { DECL_EXTERNAL (node->symbol.decl) = 1; TREE_STATIC (node->symbol.decl) = 0; } - if (non_null_aliasof) - { - decl_index = streamer_read_uhwi (ib); - node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index); - } + if (node->symbol.alias && !node->symbol.analyzed) + node->symbol.alias_target = get_alias_symbol (node->symbol.decl); ref = streamer_read_hwi (ib); /* Store a reference for now, and fix up later to be a pointer. */ node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref; diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index e0db8b10a70..0f05d180183 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -898,7 +898,7 @@ lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder); /* In lto-symtab.c. */ extern void lto_symtab_merge_decls (void); -extern void lto_symtab_merge_cgraph_nodes (void); +extern void lto_symtab_merge_symbols (void); extern tree lto_symtab_prevailing_decl (tree decl); extern GTY(()) vec<tree, va_gc> *lto_global_var_decls; diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c index 6c433f42731..2b41933c67e 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -542,7 +542,7 @@ lto_symtab_merge_decls (void) /* Helper to process the decl chain for the symbol table entry *SLOT. */ static void -lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing) +lto_symtab_merge_symbols_1 (symtab_node prevailing) { symtab_node e, next; @@ -568,88 +568,32 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing) lto_symtab_merge_decls. */ void -lto_symtab_merge_cgraph_nodes (void) +lto_symtab_merge_symbols (void) { - struct cgraph_node *cnode; - struct varpool_node *vnode; symtab_node node; - /* Populate assembler name hash. */ - symtab_initialize_asm_name_hash (); - if (!flag_ltrans) - FOR_EACH_SYMBOL (node) - if (lto_symtab_symbol_p (node) - && node->symbol.next_sharing_asm_name - && !node->symbol.previous_sharing_asm_name) - lto_symtab_merge_cgraph_nodes_1 (node); - - FOR_EACH_FUNCTION (cnode) - { - /* Resolve weakrefs to symbol defined in other unit. */ - if (!cnode->symbol.analyzed && cnode->thunk.alias && !DECL_P (cnode->thunk.alias)) - { - symtab_node node = symtab_node_for_asm (cnode->thunk.alias); - if (node && is_a <cgraph_node> (node)) - { - struct cgraph_node *n; - - for (n = cgraph (node); n && n->symbol.alias; - n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL) - if (n == cnode) - { - error ("function %q+D part of alias cycle", cnode->symbol.decl); - cnode->symbol.alias = false; - break; - } - if (cnode->symbol.alias) - { - cgraph_create_function_alias (cnode->symbol.decl, node->symbol.decl); - ipa_record_reference ((symtab_node)cnode, (symtab_node)node, - IPA_REF_ALIAS, NULL); - cnode->symbol.analyzed = true; - } - } - else if (node) - error ("%q+D alias in between function and variable is not supported", cnode->symbol.decl); - } - if ((cnode->thunk.thunk_p || cnode->symbol.alias) - && cnode->thunk.alias && DECL_P (cnode->thunk.alias)) - cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias); - cnode->symbol.aux = NULL; - } - FOR_EACH_VARIABLE (vnode) { - /* Resolve weakrefs to symbol defined in other unit. */ - if (!vnode->symbol.analyzed && vnode->alias_of && !DECL_P (vnode->alias_of)) + symtab_initialize_asm_name_hash (); + + /* Do the actual merging. */ + FOR_EACH_SYMBOL (node) + if (lto_symtab_symbol_p (node) + && node->symbol.next_sharing_asm_name + && !node->symbol.previous_sharing_asm_name) + lto_symtab_merge_symbols_1 (node); + + /* Resolve weakref aliases whose target are now in the compilation unit. */ + FOR_EACH_SYMBOL (node) { - symtab_node node = symtab_node_for_asm (vnode->alias_of); - if (node && is_a <cgraph_node> (node)) + if (!node->symbol.analyzed && node->symbol.alias_target) { - struct varpool_node *n; - - for (n = varpool (node); n && n->symbol.alias; - n = n->symbol.analyzed ? varpool_alias_target (n) : NULL) - if (n == vnode) - { - error ("function %q+D part of alias cycle", vnode->symbol.decl); - vnode->symbol.alias = false; - break; - } - if (vnode->symbol.alias) - { - varpool_create_variable_alias (vnode->symbol.decl, node->symbol.decl); - ipa_record_reference ((symtab_node)vnode, (symtab_node)node, - IPA_REF_ALIAS, NULL); - vnode->symbol.analyzed = true; - } + symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target); + if (tgt) + symtab_resolve_alias (node, tgt); } - else if (node) - error ("%q+D alias in between function and variable is not supported", vnode->symbol.decl); + node->symbol.aux = NULL; } - if (vnode->symbol.alias && DECL_P (vnode->alias_of)) - vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of); - vnode->symbol.aux = NULL; } } diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index ded10566313..0a01c1b4f12 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2013-06-01 Jan Hubicka <jh@suse.cz> + + * lto.c (read_cgraph_and_symbols): Simplify dumping; Replace + lto_symtab_merge_cgraph_nodes by lto_symtab_merge_symbols. + (do_whole_program_analysis): Update dumping. + 2013-05-29 Jan Hubicka <jh@suse.cz> * lto.c (has_analyzed_clone_p, lto_materialize_function): Update for new symtab diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index f2a59d3bf74..05867e1ecf9 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -3033,10 +3033,9 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Before merging:\n"); - dump_cgraph (cgraph_dump_file); - dump_varpool (cgraph_dump_file); + dump_symtab (cgraph_dump_file); } - lto_symtab_merge_cgraph_nodes (); + lto_symtab_merge_symbols (); ggc_collect (); /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization @@ -3169,10 +3168,7 @@ do_whole_program_analysis (void) cgraph_function_flags_ready = true; if (cgraph_dump_file) - { - dump_cgraph (cgraph_dump_file); - dump_varpool (cgraph_dump_file); - } + dump_symtab (cgraph_dump_file); bitmap_obstack_initialize (NULL); cgraph_state = CGRAPH_STATE_IPA_SSA; @@ -3182,8 +3178,7 @@ do_whole_program_analysis (void) if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Optimized "); - dump_cgraph (cgraph_dump_file); - dump_varpool (cgraph_dump_file); + dump_symtab (cgraph_dump_file); } #ifdef ENABLE_CHECKING verify_cgraph (); diff --git a/gcc/passes.c b/gcc/passes.c index feaf3226fac..2a29d9f8244 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -2461,6 +2461,7 @@ ipa_write_summaries (void) lto_symtab_encoder_t encoder; int i, order_pos; struct varpool_node *vnode; + struct cgraph_node *node; struct cgraph_node **order; if (!flag_generate_lto || seen_error ()) @@ -2496,9 +2497,11 @@ ipa_write_summaries (void) lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node); } + FOR_EACH_DEFINED_FUNCTION (node) + if (node->symbol.alias) + lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node); FOR_EACH_DEFINED_VARIABLE (vnode) - if ((!vnode->symbol.alias || vnode->alias_of)) - lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); + lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); ipa_write_summaries_1 (compute_ltrans_boundary (encoder)); diff --git a/gcc/symtab.c b/gcc/symtab.c index 1a7f8262add..af8e70bb02c 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -481,6 +481,14 @@ dump_symtab_base (FILE *f, symtab_node node) fprintf (f, " analyzed"); if (node->symbol.alias) fprintf (f, " alias"); + if (node->symbol.cpp_implicit_alias) + fprintf (f, " cpp_implicit_alias"); + if (node->symbol.alias_target) + fprintf (f, " target:%s", + DECL_P (node->symbol.alias_target) + ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME + (node->symbol.alias_target)) + : IDENTIFIER_POINTER (node->symbol.alias_target)); fprintf (f, "\n Visibility:"); if (node->symbol.in_other_partition) fprintf (f, " in_other_partition"); @@ -666,6 +674,17 @@ verify_symtab_base (symtab_node node) error ("node is analyzed byt it is not a definition"); error_found = true; } + if (node->symbol.cpp_implicit_alias && !node->symbol.alias) + { + error ("node is alias but not implicit alias"); + error_found = true; + } + if (node->symbol.alias && !node->symbol.definition + && !lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl))) + { + error ("node is alias but not definition"); + error_found = true; + } if (node->symbol.same_comdat_group) { symtab_node n = node->symbol.same_comdat_group; @@ -757,6 +776,7 @@ symtab_used_from_object_file_p (symtab_node node) /* Make DECL local. FIXME: We shouldn't need to mess with rtl this early, but other code such as notice_global_symbol generates rtl. */ + void symtab_make_decl_local (tree decl) { @@ -796,6 +816,17 @@ symtab_make_decl_local (tree decl) SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl); } +/* Return availability of NODE. */ + +enum availability +symtab_node_availability (symtab_node node) +{ + if (is_a <cgraph_node> (node)) + return cgraph_function_body_availability (cgraph (node)); + else + return cgraph_variable_initializer_availability (varpool (node)); +} + /* Given NODE, walk the alias chain to return the symbol NODE is alias of. If NODE is not an alias, return NODE. When AVAILABILITY is non-NULL, get minimal availability in the chain. */ @@ -804,12 +835,7 @@ symtab_node symtab_alias_ultimate_target (symtab_node node, enum availability *availability) { if (availability) - { - if (is_a <cgraph_node> (node)) - *availability = cgraph_function_body_availability (cgraph (node)); - else - *availability = cgraph_variable_initializer_availability (varpool (node)); - } + *availability = symtab_node_availability (node); while (node) { if (node->symbol.alias && node->symbol.analyzed) @@ -818,11 +844,7 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability) return node; if (node && availability) { - enum availability a; - if (is_a <cgraph_node> (node)) - a = cgraph_function_body_availability (cgraph (node)); - else - a = cgraph_variable_initializer_availability (varpool (node)); + enum availability a = symtab_node_availability (node); if (a < *availability) *availability = a; } @@ -831,4 +853,93 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability) *availability = AVAIL_NOT_AVAILABLE; return NULL; } + +/* C++ FE sometimes change linkage flags after producing same body aliases. + + FIXME: C++ produce implicit aliases for virtual functions and vtables that + are obviously equivalent. The way it is doing so is however somewhat + kludgy and interferes with the visibility code. As a result we need to + copy the visibility from the target to get things right. */ + +void +fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target) +{ + if (is_a <cgraph_node> (node)) + { + DECL_DECLARED_INLINE_P (node->symbol.decl) + = DECL_DECLARED_INLINE_P (target->symbol.decl); + DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) + = DECL_DISREGARD_INLINE_LIMITS (target->symbol.decl); + } + /* FIXME: It is not really clear why those flags should not be copied for + functions, too. */ + else + { + DECL_WEAK (node->symbol.decl) = DECL_WEAK (target->symbol.decl); + DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl); + DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (target->symbol.decl); + } + DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (target->symbol.decl); + if (TREE_PUBLIC (node->symbol.decl)) + { + DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl); + DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (target->symbol.decl); + DECL_COMDAT_GROUP (node->symbol.decl) + = DECL_COMDAT_GROUP (target->symbol.decl); + if (DECL_ONE_ONLY (target->symbol.decl) + && !node->symbol.same_comdat_group) + symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target); + } + node->symbol.externally_visible = target->symbol.externally_visible; +} + +/* Add reference recording that NODE is alias of TARGET. + The function can fail in the case of aliasing cycles; in this case + it returns false. */ + +bool +symtab_resolve_alias (symtab_node node, symtab_node target) +{ + symtab_node n; + + gcc_assert (!node->symbol.analyzed + && !vec_safe_length (node->symbol.ref_list.references)); + + /* Never let cycles to creep into the symbol table alias references; + those will make alias walkers to be infinite. */ + for (n = target; n && n->symbol.alias; + n = n->symbol.analyzed ? symtab_alias_target (n) : NULL) + if (n == node) + { + if (is_a <cgraph_node> (node)) + error ("function %q+D part of alias cycle", node->symbol.decl); + else if (is_a <varpool_node> (node)) + error ("variable %q+D part of alias cycle", node->symbol.decl); + else + gcc_unreachable (); + node->symbol.alias = false; + return false; + } + + /* "analyze" the node - i.e. mark the reference. */ + node->symbol.definition = true; + node->symbol.alias = true; + node->symbol.analyzed = true; + ipa_record_reference (node, target, IPA_REF_ALIAS, NULL); + + /* Alias targets become reudndant after alias is resolved into an reference. + We do not want to keep it around or we would have to mind updating them + when renaming symbols. */ + node->symbol.alias_target = NULL; + DECL_ATTRIBUTES (node->symbol.decl) + = remove_attribute ("alias", DECL_ATTRIBUTES (node->symbol.decl)); + + if (node->symbol.cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION) + fixup_same_cpp_alias_visibility (node, target); + + /* If alias has address taken, so does the target. */ + if (node->symbol.address_taken) + symtab_alias_ultimate_target (target, NULL)->symbol.address_taken = true; + return true; +} #include "gt-symtab.h" diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index d7e5a40106f..03aba755b92 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -3933,7 +3933,7 @@ get_cg_data (struct cgraph_node **node, bool traverse_aliases) struct tm_ipa_cg_data *d; if (traverse_aliases && (*node)->symbol.alias) - *node = cgraph_get_node ((*node)->thunk.alias); + *node = cgraph_alias_target (*node); d = (struct tm_ipa_cg_data *) (*node)->symbol.aux; @@ -4699,7 +4699,7 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data) tree old_decl, new_decl, tm_name; struct cgraph_node *new_node; - if (!node->same_body_alias) + if (!node->symbol.cpp_implicit_alias) return false; old_decl = node->symbol.decl; @@ -5369,7 +5369,7 @@ ipa_tm_execute (void) bool doit = false; node = tm_callees[i]; - if (node->same_body_alias) + if (node->symbol.cpp_implicit_alias) continue; a = cgraph_function_body_availability (node); diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c index 9fecb6cb663..6329fdd5015 100644 --- a/gcc/tree-emutls.c +++ b/gcc/tree-emutls.c @@ -699,7 +699,9 @@ create_emultls_var (struct varpool_node *var, void *data) tree cdecl; struct varpool_node *cvar; - cdecl = new_emutls_decl (var->symbol.decl, var->alias_of); + cdecl = new_emutls_decl (var->symbol.decl, + var->symbol.alias && var->symbol.analyzed + ? varpool_alias_target (var)->symbol.decl : NULL); cvar = varpool_get_node (cdecl); control_vars.quick_push (cvar); @@ -711,7 +713,7 @@ create_emultls_var (struct varpool_node *var, void *data) need to do this once for the main variable. */ emutls_common_1 (var->symbol.decl, cdecl, (tree *)data); } - if (var->symbol.alias && !var->alias_of) + if (var->symbol.alias && !var->symbol.analyzed) cvar->symbol.alias = true; /* Indicate that the value of the TLS variable may be found elsewhere, @@ -767,7 +769,7 @@ ipa_lower_emutls (void) { var = tls_vars->nodes[i]; - if (var->symbol.alias && !var->alias_of) + if (var->symbol.alias && !var->symbol.analyzed) any_aliases = true; else if (!var->symbol.alias) varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true); diff --git a/gcc/varpool.c b/gcc/varpool.c index 1916b76d960..7915a95fb50 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -240,30 +240,9 @@ varpool_analyze_node (struct varpool_node *node) already informed about increased alignment. */ align_variable (decl, 0); } - if (node->symbol.alias && node->alias_of) - { - struct varpool_node *tgt = varpool_node_for_decl (node->alias_of); - struct varpool_node *n; - - for (n = tgt; n && n->symbol.alias; - n = n->symbol.analyzed ? varpool_alias_target (n) : NULL) - if (n == node) - { - error ("variable %q+D part of alias cycle", node->symbol.decl); - node->symbol.alias = false; - continue; - } - if (!vec_safe_length (node->symbol.ref_list.references)) - ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL); - if (node->extra_name_alias) - { - DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of); - DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of); - DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of); - fixup_same_cpp_alias_visibility ((symtab_node) node, - (symtab_node) tgt, node->alias_of); - } - } + if (node->symbol.alias) + symtab_resolve_alias + ((symtab_node) node, (symtab_node) varpool_get_node (node->symbol.alias_target)); else if (DECL_INITIAL (decl)) record_references_in_initializer (decl, node->symbol.analyzed); node->symbol.analyzed = true; @@ -281,7 +260,7 @@ assemble_aliases (struct varpool_node *node) { struct varpool_node *alias = ipa_ref_referring_varpool_node (ref); do_assemble_alias (alias->symbol.decl, - DECL_ASSEMBLER_NAME (alias->alias_of)); + DECL_ASSEMBLER_NAME (node->symbol.decl)); assemble_aliases (alias); } } @@ -494,18 +473,7 @@ varpool_create_variable_alias (tree alias, tree decl) alias_node = varpool_node_for_decl (alias); alias_node->symbol.alias = true; alias_node->symbol.definition = true; - alias_node->alias_of = decl; - - /* Extra name alias mechanizm creates aliases really late - via DECL_ASSEMBLER_NAME mechanizm. - This is unfortunate because they are not going through the - standard channels. Ensure they get output. */ - if (cgraph_state >= CGRAPH_STATE_IPA) - { - varpool_analyze_node (alias_node); - if (TREE_PUBLIC (alias)) - alias_node->symbol.externally_visible = true; - } + alias_node->symbol.alias_target = decl; return alias_node; } @@ -522,7 +490,15 @@ varpool_extra_name_alias (tree alias, tree decl) return NULL; #endif alias_node = varpool_create_variable_alias (alias, decl); - alias_node->extra_name_alias = true; + alias_node->symbol.cpp_implicit_alias = true; + + /* Extra name alias mechanizm creates aliases really late + via DECL_ASSEMBLER_NAME mechanizm. + This is unfortunate because they are not going through the + standard channels. Ensure they get output. */ + if (cpp_implicit_aliases_done) + symtab_resolve_alias ((symtab_node)alias_node, + (symtab_node)varpool_node_for_decl (decl)); return alias_node; } |