From cd35bcf7e8fa8fb1f11e8a45fd1012ca6461e278 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sat, 18 Jun 2011 10:31:03 +0200 Subject: [PATCH] lto-symtab.c (lto_varpool_replace_node): Remove code handling extra name aliases. * lto-symtab.c (lto_varpool_replace_node): Remove code handling extra name aliases. (lto_symtab_resolve_can_prevail_p): Likewise. (lto_symtab_merge_cgraph_nodes): Update alias_of pointers. * cgraphbuild.c (record_reference): Remove extra body alias code. (mark_load): Likewise. (mark_store): Likewise. * cgraph.h (varpool_node): Remove extra_name filed; add alias_of and extraname_alias. (varpool_create_variable_alias, varpool_for_node_and_aliases): Declare. (varpool_alias_aliased_node): New inline function. (varpool_variable_node): New function. * cgraphunit.c (handle_alias_pairs): Handle also variable aliases. * ipa-ref.c (ipa_record_reference): Allow aliases on variables. * lto-cgraph.c (lto_output_varpool_node): Update streaming. (input_varpool_node): Likewise. * lto-streamer-out.c (produce_symtab): Remove extra name aliases. (varpool_externally_visible_p): Remove extra body alias code. (function_and_variable_visibility): Likewise. * tree-ssa-structalias.c (associate_varinfo_to_alias_1): New function. (ipa_pta_execute): Use it. * varpool.c (varpool_remove_node): Remove extra name alias code. (varpool_mark_needed_node): Likewise. (varpool_analyze_pending_decls): Analyze aliases. (assemble_aliases): New functoin. (varpool_assemble_decl): Use it. (varpool_create_variable_alias): New function. (varpool_extra_name_alias): Rewrite. (varpool_for_node_and_aliases): New function. From-SVN: r175167 --- gcc/ChangeLog | 32 +++++++ gcc/cgraph.h | 52 +++++++++++- gcc/cgraphbuild.c | 8 -- gcc/cgraphunit.c | 15 ++++ gcc/ipa-ref.c | 2 +- gcc/lto-cgraph.c | 47 +++-------- gcc/lto-streamer-out.c | 10 +-- gcc/lto-symtab.c | 32 ++----- gcc/tree-ssa-structalias.c | 18 ++-- gcc/varpool.c | 166 +++++++++++++++++++++++-------------- 10 files changed, 235 insertions(+), 147 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80431630bf5..4fe0b105bf0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2011-06-18 Jan Hubicka + + * lto-symtab.c (lto_varpool_replace_node): Remove code handling + extra name aliases. + (lto_symtab_resolve_can_prevail_p): Likewise. + (lto_symtab_merge_cgraph_nodes): Update alias_of pointers. + * cgraphbuild.c (record_reference): Remove extra body alias code. + (mark_load): Likewise. + (mark_store): Likewise. + * cgraph.h (varpool_node): Remove extra_name filed; + add alias_of and extraname_alias. + (varpool_create_variable_alias, varpool_for_node_and_aliases): Declare. + (varpool_alias_aliased_node): New inline function. + (varpool_variable_node): New function. + * cgraphunit.c (handle_alias_pairs): Handle also variable aliases. + * ipa-ref.c (ipa_record_reference): Allow aliases on variables. + * lto-cgraph.c (lto_output_varpool_node): Update streaming. + (input_varpool_node): Likewise. + * lto-streamer-out.c (produce_symtab): Remove extra name aliases. + (varpool_externally_visible_p): Remove extra body alias code. + (function_and_variable_visibility): Likewise. + * tree-ssa-structalias.c (associate_varinfo_to_alias_1): New function. + (ipa_pta_execute): Use it. + * varpool.c (varpool_remove_node): Remove extra name alias code. + (varpool_mark_needed_node): Likewise. + (varpool_analyze_pending_decls): Analyze aliases. + (assemble_aliases): New functoin. + (varpool_assemble_decl): Use it. + (varpool_create_variable_alias): New function. + (varpool_extra_name_alias): Rewrite. + (varpool_for_node_and_aliases): New function. + 2011-06-18 Jakub Jelinek PR target/49411 diff --git a/gcc/cgraph.h b/gcc/cgraph.h index feb742d387e..dd08febaf12 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -380,13 +380,12 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap); struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { tree decl; + /* For aliases points to declaration DECL is alias of. */ + tree alias_of; /* Pointer to the next function in varpool_nodes. */ struct varpool_node *next, *prev; /* Pointer to the next function in varpool_nodes_queue. */ struct varpool_node *next_needed, *prev_needed; - /* For normal nodes a pointer to the first extra name alias. For alias - nodes a pointer to the normal node. */ - struct varpool_node *extra_name; /* Circular list of nodes in the same comdat group if non-NULL. */ struct varpool_node *same_comdat_group; struct ipa_ref_list ref_list; @@ -415,6 +414,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { /* Set for aliases once they got through assemble_alias. Also set for extra name aliases in varpool_extra_name_alias. */ unsigned alias : 1; + unsigned extra_name_alias : 1; /* Set when variable is used from other LTRANS partition. */ unsigned used_from_other_partition : 1; /* Set when variable is available in the other LTRANS partition. @@ -665,9 +665,13 @@ bool varpool_analyze_pending_decls (void); void varpool_remove_unreferenced_decls (void); void varpool_empty_needed_queue (void); struct varpool_node * varpool_extra_name_alias (tree, tree); +struct varpool_node * varpool_create_variable_alias (tree, tree); const char * varpool_node_name (struct varpool_node *node); void varpool_reset_queue (void); bool const_value_known_p (tree); +bool varpool_for_node_and_aliases (struct varpool_node *, + bool (*) (struct varpool_node *, void *), + void *, bool); /* Walk all reachable static variables. */ #define FOR_EACH_STATIC_VARIABLE(node) \ @@ -968,6 +972,20 @@ cgraph_alias_aliased_node (struct cgraph_node *n) return NULL; } +/* Return node that alias N is aliasing. */ + +static inline struct varpool_node * +varpool_alias_aliased_node (struct varpool_node *n) +{ + struct ipa_ref *ref; + + ipa_ref_list_reference_iterate (&n->ref_list, 0, ref); + gcc_checking_assert (ref->use == IPA_REF_ALIAS); + if (ref->refered_type == IPA_REF_CGRAPH) + return ipa_ref_varpool_node (ref); + return NULL; +} + /* Given NODE, walk the alias chain to return the function NODE is alias of. Walk through thunk, too. When AVAILABILITY is non-NULL, get minimal availablity in the chain. */ @@ -1026,6 +1044,34 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *avai return NULL; } +/* Given NODE, walk the alias chain to return the function NODE is alias of. + Do not walk through thunks. + When AVAILABILITY is non-NULL, get minimal availablity in the chain. */ + +static inline struct varpool_node * +varpool_variable_node (struct varpool_node *node, enum availability *availability) +{ + if (availability) + *availability = cgraph_variable_initializer_availability (node); + while (node) + { + if (node->alias && node->analyzed) + node = varpool_alias_aliased_node (node); + else + return node; + if (node && availability) + { + enum availability a; + a = cgraph_variable_initializer_availability (node); + if (a < *availability) + *availability = a; + } + } + if (*availability) + *availability = AVAIL_NOT_AVAILABLE; + return NULL; +} + /* Return true when the edge E represents a direct recursion. */ static inline bool cgraph_edge_recursive_p (struct cgraph_edge *e) diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 961804b415e..8bf88300593 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -87,8 +87,6 @@ record_reference (tree *tp, int *walk_subtrees, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference (NULL, ctx->varpool_node, NULL, vnode, IPA_REF_ADDR, NULL); @@ -261,8 +259,6 @@ mark_address (gimple stmt, tree addr, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, IPA_REF_ADDR, stmt); @@ -296,8 +292,6 @@ mark_load (gimple stmt, tree t, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, IPA_REF_LOAD, stmt); @@ -320,8 +314,6 @@ mark_store (gimple stmt, tree t, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, IPA_REF_STORE, stmt); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 88d0face010..6683d2a5df3 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1186,6 +1186,7 @@ handle_alias_pairs (void) unsigned i; struct cgraph_node *target_node; struct cgraph_node *src_node; + struct varpool_node *target_vnode; for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);) { @@ -1206,6 +1207,20 @@ handle_alias_pairs (void) cgraph_create_function_alias (p->decl, target_node->decl); VEC_unordered_remove (alias_pair, alias_pairs, i); } + else if (TREE_CODE (p->decl) == VAR_DECL + && !lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) + && (target_vnode = varpool_node_for_asm (p->target)) != NULL) + { + /* Normally EXTERNAL flag is used to mark external inlines, + however for aliases it seems to be allowed to use it w/o + any meaning. See gcc.dg/attr-alias-3.c + However for weakref we insist on EXTERNAL flag being set. + See gcc.dg/attr-alias-5.c */ + if (DECL_EXTERNAL (p->decl)) + DECL_EXTERNAL (p->decl) = 0; + varpool_create_variable_alias (p->decl, target_vnode->decl); + VEC_unordered_remove (alias_pair, alias_pairs, i); + } else { if (dump_file) diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c index f5fd03f67fb..8520bca33ac 100644 --- a/gcc/ipa-ref.c +++ b/gcc/ipa-ref.c @@ -68,7 +68,7 @@ ipa_record_reference (struct cgraph_node *refering_node, { ref->refering.varpool_node = refering_varpool_node; ref->refering_type = IPA_REF_VARPOOL; - gcc_assert (use_type == IPA_REF_ADDR); + gcc_assert (use_type == IPA_REF_ADDR || use_type == IPA_REF_ALIAS); } if (refered_node) { diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 169de382dbe..9d9cb4366a0 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -544,8 +544,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node { bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed; struct bitpack_d bp; - struct varpool_node *alias; - int count = 0; int ref; lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl); @@ -554,7 +552,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node bp_pack_value (&bp, node->force_output, 1); bp_pack_value (&bp, node->finalized, 1); bp_pack_value (&bp, node->alias, 1); - gcc_assert (!node->alias || !node->extra_name); + bp_pack_value (&bp, node->alias_of != NULL, 1); gcc_assert (node->finalized || !node->analyzed); gcc_assert (node->needed); /* Constant pool initializers can be de-unified into individual ltrans units. @@ -573,11 +571,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node set, vset), 1); bp_pack_value (&bp, boundary_p, 1); /* in_other_partition. */ } - /* Also emit any extra name aliases. */ - for (alias = node->extra_name; alias; alias = alias->next) - count++; - bp_pack_value (&bp, count != 0, 1); lto_output_bitpack (&bp); + if (node->alias_of) + lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of); if (node->same_comdat_group && !boundary_p) { ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group); @@ -588,17 +584,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node lto_output_sleb128_stream (ob->main_stream, ref); lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN, node->resolution); - - if (count) - { - lto_output_uleb128_stream (ob->main_stream, count); - for (alias = node->extra_name; alias; alias = alias->next) - { - lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl); - lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution, - LDPR_NUM_KNOWN, alias->resolution); - } - } } /* Output the varpool NODE to OB. @@ -780,7 +765,7 @@ compute_ltrans_boundary (struct lto_out_decl_state *state, for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) { struct varpool_node *vnode = vsi_node (vsi); - gcc_assert (!vnode->alias); + gcc_assert (!vnode->alias || vnode->alias_of); lto_varpool_encoder_encode (varpool_encoder, vnode); lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode); add_references (encoder, varpool_encoder, &vnode->ref_list); @@ -1054,9 +1039,8 @@ input_varpool_node (struct lto_file_decl_data *file_data, tree var_decl; struct varpool_node *node; struct bitpack_d bp; - bool aliases_p; - int count; int ref = LCC_NOT_FOUND; + bool non_null_aliasof; decl_index = lto_input_uleb128 (ib); var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index); @@ -1068,6 +1052,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, node->force_output = bp_unpack_value (&bp, 1); node->finalized = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1); + non_null_aliasof = bp_unpack_value (&bp, 1); node->analyzed = node->finalized; node->used_from_other_partition = bp_unpack_value (&bp, 1); node->in_other_partition = bp_unpack_value (&bp, 1); @@ -1076,27 +1061,19 @@ input_varpool_node (struct lto_file_decl_data *file_data, DECL_EXTERNAL (node->decl) = 1; TREE_STATIC (node->decl) = 0; } - aliases_p = bp_unpack_value (&bp, 1); if (node->finalized) varpool_mark_needed_node (node); + if (non_null_aliasof) + { + decl_index = lto_input_uleb128 (ib); + node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index); + } ref = lto_input_sleb128 (ib); /* Store a reference for now, and fix up later to be a pointer. */ node->same_comdat_group = (struct varpool_node *) (intptr_t) ref; node->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN); - if (aliases_p) - { - count = lto_input_uleb128 (ib); - for (; count > 0; count --) - { - tree decl = lto_file_decl_data_get_var_decl (file_data, - lto_input_uleb128 (ib)); - struct varpool_node *alias; - alias = varpool_extra_name_alias (decl, var_decl); - alias->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution, - LDPR_NUM_KNOWN); - } - } + return node; } diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index a28e857617d..19b0ae8bb1e 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -2557,7 +2557,7 @@ produce_symtab (struct output_block *ob, char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL); struct pointer_set_t *seen; struct cgraph_node *node; - struct varpool_node *vnode, *valias; + struct varpool_node *vnode; struct lto_output_stream stream; lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder; lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; @@ -2617,11 +2617,9 @@ produce_symtab (struct output_block *ob, && vnode->finalized && DECL_VIRTUAL_P (vnode->decl)) continue; - if (vnode->alias) + if (vnode->alias && !vnode->alias_of) continue; write_symbol (cache, &stream, vnode->decl, seen, false); - for (valias = vnode->extra_name; valias; valias = valias->next) - write_symbol (cache, &stream, valias->decl, seen, true); } for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++) { @@ -2633,11 +2631,9 @@ produce_symtab (struct output_block *ob, && vnode->finalized && DECL_VIRTUAL_P (vnode->decl)) continue; - if (vnode->alias) + if (vnode->alias && !vnode->alias_of) continue; write_symbol (cache, &stream, vnode->decl, seen, false); - for (valias = vnode->extra_name; valias; valias = valias->next) - write_symbol (cache, &stream, valias->decl, seen, true); } /* Write all aliases. */ diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c index d58da8df2db..2bbf064ee7d 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -268,32 +268,9 @@ lto_varpool_replace_node (struct varpool_node *vnode, gcc_assert (!vnode->analyzed || prevailing_node->analyzed); varpool_mark_needed_node (prevailing_node); } - /* Relink aliases. */ - if (vnode->extra_name && !vnode->alias) - { - struct varpool_node *alias, *last; - for (alias = vnode->extra_name; - alias; alias = alias->next) - { - last = alias; - alias->extra_name = prevailing_node; - } - - if (prevailing_node->extra_name) - { - last->next = prevailing_node->extra_name; - prevailing_node->extra_name->prev = last; - } - prevailing_node->extra_name = vnode->extra_name; - vnode->extra_name = NULL; - } gcc_assert (!vnode->finalized || prevailing_node->finalized); gcc_assert (!vnode->analyzed || prevailing_node->analyzed); - /* When replacing by an alias, the references goes to the original - variable. */ - if (prevailing_node->alias && prevailing_node->extra_name) - prevailing_node = prevailing_node->extra_name; ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list); /* Be sure we can garbage collect the initializer. */ @@ -438,14 +415,11 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e) if (TREE_CODE (e->decl) == FUNCTION_DECL) return (e->node && e->node->analyzed); - /* A variable should have a size. */ else if (TREE_CODE (e->decl) == VAR_DECL) { if (!e->vnode) return false; - if (e->vnode->finalized) - return true; - return e->vnode->alias && e->vnode->extra_name->finalized; + return e->vnode->finalized; } gcc_unreachable (); @@ -779,6 +753,7 @@ void lto_symtab_merge_cgraph_nodes (void) { struct cgraph_node *node; + struct varpool_node *vnode; lto_symtab_maybe_init_hash_table (); htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL); @@ -786,6 +761,9 @@ lto_symtab_merge_cgraph_nodes (void) if ((node->thunk.thunk_p || node->alias) && node->thunk.alias) node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias); + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + if (vnode->alias_of) + vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of); } /* Given the decl DECL, return the prevailing decl with the same name. */ diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index d5516e673fa..6f076dcd3e7 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -6685,6 +6685,16 @@ associate_varinfo_to_alias (struct cgraph_node *node, void *data) return false; } +/* Associate node with varinfo DATA. Worker for + varpool_for_node_and_aliases. */ +static bool +associate_varinfo_to_alias_1 (struct varpool_node *node, void *data) +{ + if (node->alias) + insert_vi_for_tree (node->decl, (varinfo_t)data); + return false; +} + /* Execute the driver for IPA PTA. */ static unsigned int ipa_pta_execute (void) @@ -6716,14 +6726,12 @@ ipa_pta_execute (void) /* Create constraints for global variables and their initializers. */ for (var = varpool_nodes; var; var = var->next) { - struct varpool_node *alias; varinfo_t vi; + if (var->alias) + continue; vi = get_vi_for_tree (var->decl); - - /* Associate the varinfo node with all aliases. */ - for (alias = var->extra_name; alias; alias = alias->next) - insert_vi_for_tree (alias->decl, vi); + varpool_for_node_and_aliases (var, associate_varinfo_to_alias_1, vi, true); } if (dump_file) diff --git a/gcc/varpool.c b/gcc/varpool.c index 43ee2290389..d223779a5c1 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -131,7 +131,7 @@ varpool_node (tree decl) struct varpool_node key, *node, **slot; gcc_assert (TREE_CODE (decl) == VAR_DECL - && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))); + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p)); if (!varpool_hash) varpool_hash = htab_create_ggc (10, hash_varpool_node, @@ -162,25 +162,14 @@ varpool_remove_node (struct varpool_node *node) gcc_assert (*slot == node); htab_clear_slot (varpool_hash, slot); gcc_assert (!varpool_assembled_nodes_queue); - if (!node->alias) - while (node->extra_name) - varpool_remove_node (node->extra_name); if (node->next) node->next->prev = node->prev; if (node->prev) node->prev->next = node->next; else { - if (node->alias && node->extra_name) - { - gcc_assert (node->extra_name->extra_name == node); - node->extra_name->extra_name = node->next; - } - else - { - gcc_assert (varpool_nodes == node); - varpool_nodes = node->next; - } + gcc_assert (varpool_nodes == node); + varpool_nodes = node->next; } if (varpool_first_unanalyzed_node == node) varpool_first_unanalyzed_node = node->next_needed; @@ -311,8 +300,6 @@ varpool_enqueue_needed_node (struct varpool_node *node) void varpool_mark_needed_node (struct varpool_node *node) { - if (node->alias && node->extra_name) - node = node->extra_name; if (!node->needed && node->finalized && !TREE_ASM_WRITTEN (node->decl)) varpool_enqueue_needed_node (node); @@ -473,7 +460,40 @@ varpool_analyze_pending_decls (void) already informed about increased alignment. */ align_variable (decl, 0); } - if (DECL_INITIAL (decl)) + if (node->alias && node->alias_of) + { + struct varpool_node *tgt = varpool_node (node->alias_of); + if (!VEC_length (ipa_ref_t, node->ref_list.references)) + ipa_record_reference (NULL, node, NULL, tgt, IPA_REF_ALIAS, NULL); + /* C++ FE sometimes change linkage flags after producing same body aliases. */ + if (node->extra_name_alias) + { + DECL_WEAK (node->decl) = DECL_WEAK (node->alias_of); + TREE_PUBLIC (node->decl) = TREE_PUBLIC (node->alias_of); + DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (node->alias_of); + if (TREE_PUBLIC (node->decl)) + { + DECL_COMDAT (node->decl) = DECL_COMDAT (node->alias_of); + DECL_COMDAT_GROUP (node->decl) = DECL_COMDAT_GROUP (node->alias_of); + if (DECL_ONE_ONLY (node->alias_of) && !node->same_comdat_group) + { + node->same_comdat_group = tgt; + if (!tgt->same_comdat_group) + tgt->same_comdat_group = node; + else + { + struct varpool_node *n; + for (n = tgt->same_comdat_group; + n->same_comdat_group != tgt; + n = n->same_comdat_group) + ; + n->same_comdat_group = node; + } + } + } + } + } + else if (DECL_INITIAL (decl)) record_references_in_initializer (decl, analyzed); if (node->same_comdat_group) { @@ -488,6 +508,23 @@ varpool_analyze_pending_decls (void) return changed; } +/* Assemble thunks and aliases asociated to NODE. */ + +static void +assemble_aliases (struct varpool_node *node) +{ + int i; + struct ipa_ref *ref; + for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++) + if (ref->use == IPA_REF_ALIAS) + { + struct varpool_node *alias = ipa_ref_refering_varpool_node (ref); + assemble_alias (alias->decl, + DECL_ASSEMBLER_NAME (alias->alias_of)); + assemble_aliases (alias); + } +} + /* Output one variable, if necessary. Return whether we output it. */ bool varpool_assemble_decl (struct varpool_node *node) @@ -503,25 +540,13 @@ varpool_assemble_decl (struct varpool_node *node) assemble_variable (decl, 0, 1, 0); if (TREE_ASM_WRITTEN (decl)) { - struct varpool_node *alias; - node->next_needed = varpool_assembled_nodes_queue; node->prev_needed = NULL; if (varpool_assembled_nodes_queue) varpool_assembled_nodes_queue->prev_needed = node; varpool_assembled_nodes_queue = node; node->finalized = 1; - - /* Also emit any extra name aliases. */ - for (alias = node->extra_name; alias; alias = alias->next) - { - /* Update linkage fields in case they've changed. */ - DECL_WEAK (alias->decl) = DECL_WEAK (decl); - TREE_PUBLIC (alias->decl) = TREE_PUBLIC (decl); - DECL_VISIBILITY (alias->decl) = DECL_VISIBILITY (decl); - assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (decl)); - } - + assemble_aliases (node); return true; } } @@ -670,38 +695,36 @@ add_new_static_var (tree type) Extra name aliases are output whenever DECL is output. */ struct varpool_node * -varpool_extra_name_alias (tree alias, tree decl) +varpool_create_variable_alias (tree alias, tree decl) { - struct varpool_node key, *alias_node, *decl_node, **slot; - -#ifndef ASM_OUTPUT_DEF - /* If aliases aren't supported by the assembler, fail. */ - return NULL; -#endif + struct varpool_node *alias_node; gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL); - /* Make sure the hash table has been created. */ - decl_node = varpool_node (decl); - - key.decl = alias; + alias_node = varpool_node (alias); + alias_node->alias = 1; + alias_node->finalized = 1; + alias_node->alias_of = decl; + if (decide_is_variable_needed (alias_node, alias) + || alias_node->needed) + varpool_mark_needed_node (alias_node); + return alias_node; +} - slot = (struct varpool_node **) htab_find_slot (varpool_hash, &key, INSERT); +/* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. + Extra name aliases are output whenever DECL is output. */ - /* If the varpool_node has been already created, fail. */ - if (*slot) - return NULL; +struct varpool_node * +varpool_extra_name_alias (tree alias, tree decl) +{ + struct varpool_node *alias_node; - alias_node = ggc_alloc_cleared_varpool_node (); - alias_node->decl = alias; - alias_node->alias = 1; - alias_node->extra_name = decl_node; - alias_node->next = decl_node->extra_name; - ipa_empty_ref_list (&alias_node->ref_list); - if (decl_node->extra_name) - decl_node->extra_name->prev = alias_node; - decl_node->extra_name = alias_node; - *slot = alias_node; +#ifndef ASM_OUTPUT_DEF + /* If aliases aren't supported by the assembler, fail. */ + return NULL; +#endif + alias_node = varpool_create_variable_alias (alias, decl); + alias_node->extra_name_alias = true; return alias_node; } @@ -711,17 +734,38 @@ varpool_extra_name_alias (tree alias, tree decl) bool varpool_used_from_object_file_p (struct varpool_node *node) { - struct varpool_node *alias; - if (!TREE_PUBLIC (node->decl)) return false; if (resolution_used_from_other_file_p (node->resolution)) return true; - for (alias = node->extra_name; alias; alias = alias->next) - if (TREE_PUBLIC (alias->decl) - && resolution_used_from_other_file_p (alias->resolution)) - return true; return false; } +/* Call calback on NODE and aliases asociated to NODE. + When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are + skipped. */ + +bool +varpool_for_node_and_aliases (struct varpool_node *node, + bool (*callback) (struct varpool_node *, void *), + void *data, + bool include_overwritable) +{ + int i; + struct ipa_ref *ref; + + if (callback (node, data)) + return true; + for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++) + if (ref->use == IPA_REF_ALIAS) + { + struct varpool_node *alias = ipa_ref_refering_varpool_node (ref); + if (include_overwritable + || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE) + if (varpool_for_node_and_aliases (alias, callback, data, + include_overwritable)) + return true; + } + return false; +} #include "gt-varpool.h" -- 2.30.2