summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-01 13:08:53 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-01 13:08:53 +0000
commit48669653091db6b1a1e1ff6fa5c2acf65fdad761 (patch)
tree227ede588b4d6d5d96381098725519f26a853909
parenta47321b78ae92ae535fb3f3de0c05250c1c03068 (diff)
downloadgcc-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/ChangeLog67
-rw-r--r--gcc/cgraph.c36
-rw-r--r--gcc/cgraph.h45
-rw-r--r--gcc/cgraphunit.c145
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/ipa-pure-const.c2
-rw-r--r--gcc/ipa.c5
-rw-r--r--gcc/lto-cgraph.c62
-rw-r--r--gcc/lto-streamer.h2
-rw-r--r--gcc/lto-symtab.c92
-rw-r--r--gcc/lto/ChangeLog6
-rw-r--r--gcc/lto/lto.c13
-rw-r--r--gcc/passes.c7
-rw-r--r--gcc/symtab.c133
-rw-r--r--gcc/trans-mem.c6
-rw-r--r--gcc/tree-emutls.c8
-rw-r--r--gcc/varpool.c52
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;
}