mirror of git://gcc.gnu.org/git/gcc.git
lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Rename to ...
* 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. From-SVN: r199577
This commit is contained in:
parent
2175988161
commit
40a7fe1e38
|
|
@ -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
|
||||
|
|
|
|||
36
gcc/cgraph.c
36
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;
|
||||
|
|
|
|||
45
gcc/cgraph.h
45
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;
|
||||
}
|
||||
|
|
|
|||
145
gcc/cgraphunit.c
145
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)
|
||||
symtab_node node = symtab_get_node (p->decl);
|
||||
if (node)
|
||||
{
|
||||
struct cgraph_node *anode = cgraph_get_create_node (p->decl);
|
||||
anode->symbol.alias = true;
|
||||
anode->thunk.alias = p->target;
|
||||
}
|
||||
else
|
||||
{
|
||||
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. */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
symtab_initialize_asm_name_hash ();
|
||||
|
||||
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_node node = symtab_node_for_asm (vnode->alias_of);
|
||||
if (node && is_a <cgraph_node> (node))
|
||||
{
|
||||
struct varpool_node *n;
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
/* Resolve weakref aliases whose target are now in the compilation unit. */
|
||||
FOR_EACH_SYMBOL (node)
|
||||
{
|
||||
if (!node->symbol.analyzed && node->symbol.alias_target)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
133
gcc/symtab.c
133
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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue