Commit e257a17c by Jan Hubicka Committed by Jan Hubicka

varasm.c (set_implicit_section): New function.


	* varasm.c (set_implicit_section): New function.
	(resolve_unique_section): Use it to set implicit section
	for aliases, too.
	(get_named_text_section): Use symtab_get_node (decl)->implicit_section
	(default_function_section): Likewise.
	(decl_binds_to_current_def_p): Constify argument.
	* varasm.h (decl_binds_to_current_def_p): Update prototype.
	* asan.c (asan_protect_global): Use symtab_get_node (decl)->implicit_section.
	* symtab.c (dump_symtab_base): Dump implicit sections.
	(verify_symtab_base): Verify sanity of sectoins and comdats.
	(symtab_resolve_alias): Alias share the section of its target.
	(set_section_1): New function.
	(symtab_node::set_section): Move here, recurse to aliases.
	(verify_symtab): Check for duplicated symtab lists.
	* tree-core.h (implicit_section_name_p): Remove.
	* tree-vect-data-refs.c: Include varasm.h.
	(vect_can_force_dr_alignment_p): Fix conditional on when
	decl bints to current definition; use
	symtab_get_node (decl)->implicit_section.
	* cgraph.c (cgraph_make_node_local_1): Fix section set.
	* cgraph.h (struct symtab_node): Add implicit_section.
	(set_section): Rename to ...
	(set_section_for_node): ... this one.
	(set_section): Declare.
	* tree.h (DECL_HAS_IMPLICIT_SECTION_NAME_P): Remove.
	* lto-cgraph.c (lto_output_node, lto_output_varpool_node,
	input_overwrite_node, input_varpool_node): Stream implicit_section.
	* ipa.c (symtab_remove_unreachable_nodes): Do not check symtab before
	removal; it will fail in LTO.
	
	* vtable-class-hierarchy.c: Use symtab_get_node (var_decl)->implicit_section.
	* optimize.c (cdtor_comdat_group): Fix handling of aliases.
	(maybe_clone_body): Move symbol across comdat groups.
	* method.c (use_thunk): Copy implicit section flag.

	* go/go-gcc.cc (Gcc_backend::global_variable_set_init): Use
	symtab_get_node(var_decl)->implicit_section.

	* lto.c (read_cgraph_and_symbols): Remove unreachable symbols.
	(do_whole_program_analysis): Use verify_symtab.

From-SVN: r211434
parent 58170a66
2014-06-10 Jan Hubicka <hubicka@ucw.cz>
* varasm.c (set_implicit_section): New function.
(resolve_unique_section): Use it to set implicit section
for aliases, too.
(get_named_text_section): Use symtab_get_node (decl)->implicit_section
(default_function_section): Likewise.
(decl_binds_to_current_def_p): Constify argument.
* varasm.h (decl_binds_to_current_def_p): Update prototype.
* asan.c (asan_protect_global): Use symtab_get_node (decl)->implicit_section.
* symtab.c (dump_symtab_base): Dump implicit sections.
(verify_symtab_base): Verify sanity of sectoins and comdats.
(symtab_resolve_alias): Alias share the section of its target.
(set_section_1): New function.
(symtab_node::set_section): Move here, recurse to aliases.
(verify_symtab): Check for duplicated symtab lists.
* tree-core.h (implicit_section_name_p): Remove.
* tree-vect-data-refs.c: Include varasm.h.
(vect_can_force_dr_alignment_p): Fix conditional on when
decl bints to current definition; use
symtab_get_node (decl)->implicit_section.
* cgraph.c (cgraph_make_node_local_1): Fix section set.
* cgraph.h (struct symtab_node): Add implicit_section.
(set_section): Rename to ...
(set_section_for_node): ... this one.
(set_section): Declare.
* tree.h (DECL_HAS_IMPLICIT_SECTION_NAME_P): Remove.
* lto-cgraph.c (lto_output_node, lto_output_varpool_node,
input_overwrite_node, input_varpool_node): Stream implicit_section.
* ipa.c (symtab_remove_unreachable_nodes): Do not check symtab before
removal; it will fail in LTO.
2014-06-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com> 2014-06-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/aarch64/aarch64-simd.md (move_lo_quad_<mode>): * config/aarch64/aarch64-simd.md (move_lo_quad_<mode>):
......
...@@ -1289,7 +1289,7 @@ asan_protect_global (tree decl) ...@@ -1289,7 +1289,7 @@ asan_protect_global (tree decl)
to be an array of such vars, putting padding in there to be an array of such vars, putting padding in there
breaks this assumption. */ breaks this assumption. */
|| (DECL_SECTION_NAME (decl) != NULL_TREE || (DECL_SECTION_NAME (decl) != NULL_TREE
&& !DECL_HAS_IMPLICIT_SECTION_NAME_P (decl)) && !symtab_get_node (decl)->implicit_section)
|| DECL_SIZE (decl) == 0 || DECL_SIZE (decl) == 0
|| ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT || ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT
|| !valid_constant_size_p (DECL_SIZE_UNIT (decl)) || !valid_constant_size_p (DECL_SIZE_UNIT (decl))
......
...@@ -2264,7 +2264,7 @@ cgraph_make_node_local_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) ...@@ -2264,7 +2264,7 @@ cgraph_make_node_local_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
node->externally_visible = false; node->externally_visible = false;
node->forced_by_abi = false; node->forced_by_abi = false;
node->local.local = true; node->local.local = true;
node->set_comdat_group (NULL); node->set_section (NULL);
node->unique_name = (node->resolution == LDPR_PREVAILING_DEF_IRONLY node->unique_name = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
|| node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP); || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
node->resolution = LDPR_PREVAILING_DEF_IRONLY; node->resolution = LDPR_PREVAILING_DEF_IRONLY;
......
...@@ -93,6 +93,9 @@ public: ...@@ -93,6 +93,9 @@ public:
unsigned forced_by_abi : 1; unsigned forced_by_abi : 1;
/* True when the name is known to be unique and thus it does not need mangling. */ /* True when the name is known to be unique and thus it does not need mangling. */
unsigned unique_name : 1; unsigned unique_name : 1;
/* Specify whether the section was set by user or by
compiler via -ffunction-sections. */
unsigned implicit_section : 1;
/* True when body and other characteristics have been removed by /* True when body and other characteristics have been removed by
symtab_remove_unreachable_nodes. */ symtab_remove_unreachable_nodes. */
unsigned body_removed : 1; unsigned body_removed : 1;
...@@ -162,17 +165,29 @@ public: ...@@ -162,17 +165,29 @@ public:
comdat_group_ = group; comdat_group_ = group;
} }
/* Return section. */ /* Return section as STRING_CST. */
tree get_section () tree get_section_name ()
{ {
return section_; return section_;
} }
/* Set section. */ /* Return section as string. */
void set_section (tree section) const char * get_section ()
{
if (!section_)
return NULL;
return TREE_STRING_POINTER (section_);
}
/* Set section, do not recurse into aliases.
When one wants to change section of symbol and its aliases,
use set_section */
void set_section_for_node (tree section)
{ {
gcc_checking_assert (!section || TREE_CODE (section) == STRING_CST); gcc_checking_assert (!section || TREE_CODE (section) == STRING_CST);
section_ = section; section_ = section;
if (!section)
implicit_section = false;
} }
/* Vectors of referring and referenced entities. */ /* Vectors of referring and referenced entities. */
...@@ -193,6 +208,9 @@ public: ...@@ -193,6 +208,9 @@ public:
/* Section name. Again can be private, if allowed. */ /* Section name. Again can be private, if allowed. */
tree section_; tree section_;
/* Set section for symbol and its aliases. */
void set_section (tree section);
}; };
enum availability enum availability
......
2014-06-10 Jan Hubicka <hubicka@ucw.cz>
* vtable-class-hierarchy.c: Use symtab_get_node (var_decl)->implicit_section.
* optimize.c (cdtor_comdat_group): Fix handling of aliases.
(maybe_clone_body): Move symbol across comdat groups.
* method.c (use_thunk): Copy implicit section flag.
2014-06-09 Paolo Carlini <paolo.carlini@oracle.com> 2014-06-09 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/22556 PR c++/22556
......
...@@ -356,14 +356,27 @@ use_thunk (tree thunk_fndecl, bool emit_p) ...@@ -356,14 +356,27 @@ use_thunk (tree thunk_fndecl, bool emit_p)
if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function) if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)
&& targetm_common.have_named_sections) && targetm_common.have_named_sections)
{ {
resolve_unique_section (function, 0, flag_function_sections); tree fn = function;
struct symtab_node *symbol;
if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function)) if ((symbol = symtab_get_node (function))
&& symbol->alias)
{
if (symbol->analyzed)
fn = symtab_alias_ultimate_target (symtab_get_node (function))->decl;
else
fn = symtab_get_node (function)->alias_target;
}
resolve_unique_section (fn, 0, flag_function_sections);
if (DECL_SECTION_NAME (fn) != NULL && DECL_ONE_ONLY (fn))
{ {
resolve_unique_section (thunk_fndecl, 0, flag_function_sections); resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
/* Output the thunk into the same section as function. */ /* Output the thunk into the same section as function. */
set_decl_section_name (thunk_fndecl, DECL_SECTION_NAME (function)); set_decl_section_name (thunk_fndecl, DECL_SECTION_NAME (fn));
symtab_get_node (thunk_fndecl)->implicit_section
= symtab_get_node (fn)->implicit_section;
} }
} }
......
...@@ -191,7 +191,7 @@ cdtor_comdat_group (tree complete, tree base) ...@@ -191,7 +191,7 @@ cdtor_comdat_group (tree complete, tree base)
diff_seen = true; diff_seen = true;
} }
grp_name[idx] = '\0'; grp_name[idx] = '\0';
gcc_assert (diff_seen); gcc_assert (diff_seen || symtab_get_node (complete)->alias);
return get_identifier (grp_name); return get_identifier (grp_name);
} }
...@@ -553,6 +553,8 @@ maybe_clone_body (tree fn) ...@@ -553,6 +553,8 @@ maybe_clone_body (tree fn)
*[CD][12]*. */ *[CD][12]*. */
comdat_group = cdtor_comdat_group (fns[1], fns[0]); comdat_group = cdtor_comdat_group (fns[1], fns[0]);
cgraph_get_create_node (fns[0])->set_comdat_group (comdat_group); cgraph_get_create_node (fns[0])->set_comdat_group (comdat_group);
if (symtab_get_node (clone)->same_comdat_group)
symtab_remove_from_same_comdat_group (symtab_get_node (clone));
symtab_add_to_same_comdat_group (symtab_get_node (clone), symtab_add_to_same_comdat_group (symtab_get_node (clone),
symtab_get_node (fns[0])); symtab_get_node (fns[0]));
} }
......
...@@ -1249,7 +1249,7 @@ vtable_find_or_create_map_decl (tree base_type) ...@@ -1249,7 +1249,7 @@ vtable_find_or_create_map_decl (tree base_type)
set_decl_section_name (var_decl, build_string (strlen (".vtable_map_vars"), set_decl_section_name (var_decl, build_string (strlen (".vtable_map_vars"),
".vtable_map_vars")); ".vtable_map_vars"));
DECL_HAS_IMPLICIT_SECTION_NAME_P (var_decl) = true; symtab_get_node (var_decl)->implicit_section = true;
DECL_INITIAL (var_decl) = initial_value; DECL_INITIAL (var_decl) = initial_value;
comdat_linkage (var_decl); comdat_linkage (var_decl);
......
2014-06-10 Jan Hubicka <hubicka@ucw.cz>
* go/go-gcc.cc (Gcc_backend::global_variable_set_init): Use
symtab_get_node(var_decl)->implicit_section.
2014-06-07 Jan Hubicka <hubicka@ucw.cz> 2014-06-07 Jan Hubicka <hubicka@ucw.cz>
* go-gcc.cc (global_variable_set_init): Use * go-gcc.cc (global_variable_set_init): Use
......
...@@ -2374,7 +2374,8 @@ Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr) ...@@ -2374,7 +2374,8 @@ Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr)
// If this variable goes in a unique section, it may need to go into // If this variable goes in a unique section, it may need to go into
// a different one now that DECL_INITIAL is set. // a different one now that DECL_INITIAL is set.
if (DECL_HAS_IMPLICIT_SECTION_NAME_P (var_decl)) if (symtab_get_node(var_decl)
&& symtab_get_node(var_decl)->implicit_section)
{ {
set_decl_section_name (var_decl, NULL); set_decl_section_name (var_decl, NULL);
resolve_unique_section (var_decl, resolve_unique_section (var_decl,
......
...@@ -512,7 +512,8 @@ function_and_variable_visibility (bool whole_program) ...@@ -512,7 +512,8 @@ function_and_variable_visibility (bool whole_program)
next = next->same_comdat_group) next = next->same_comdat_group)
{ {
next->set_comdat_group (NULL); next->set_comdat_group (NULL);
next->set_section (NULL); if (!next->alias)
next->set_section (NULL);
symtab_make_decl_local (next->decl); symtab_make_decl_local (next->decl);
next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|| next->unique_name || next->unique_name
...@@ -527,7 +528,7 @@ function_and_variable_visibility (bool whole_program) ...@@ -527,7 +528,7 @@ function_and_variable_visibility (bool whole_program)
} }
if (TREE_PUBLIC (node->decl)) if (TREE_PUBLIC (node->decl))
node->set_comdat_group (NULL); node->set_comdat_group (NULL);
if (DECL_COMDAT (node->decl)) if (DECL_COMDAT (node->decl) && !node->alias)
node->set_section (NULL); node->set_section (NULL);
symtab_make_decl_local (node->decl); symtab_make_decl_local (node->decl);
} }
...@@ -646,7 +647,8 @@ function_and_variable_visibility (bool whole_program) ...@@ -646,7 +647,8 @@ function_and_variable_visibility (bool whole_program)
next = next->same_comdat_group) next = next->same_comdat_group)
{ {
next->set_comdat_group (NULL); next->set_comdat_group (NULL);
next->set_section (NULL); if (!next->alias)
next->set_section (NULL);
symtab_make_decl_local (next->decl); symtab_make_decl_local (next->decl);
next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|| next->unique_name || next->unique_name
...@@ -657,7 +659,7 @@ function_and_variable_visibility (bool whole_program) ...@@ -657,7 +659,7 @@ function_and_variable_visibility (bool whole_program)
} }
if (TREE_PUBLIC (vnode->decl)) if (TREE_PUBLIC (vnode->decl))
vnode->set_comdat_group (NULL); vnode->set_comdat_group (NULL);
if (DECL_COMDAT (vnode->decl)) if (DECL_COMDAT (vnode->decl) && !vnode->alias)
vnode->set_section (NULL); vnode->set_section (NULL);
symtab_make_decl_local (vnode->decl); symtab_make_decl_local (vnode->decl);
vnode->resolution = LDPR_PREVAILING_DEF_IRONLY; vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
......
...@@ -281,9 +281,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -281,9 +281,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
struct pointer_set_t *reachable_call_targets = pointer_set_create (); struct pointer_set_t *reachable_call_targets = pointer_set_create ();
timevar_push (TV_IPA_UNREACHABLE); timevar_push (TV_IPA_UNREACHABLE);
#ifdef ENABLE_CHECKING
verify_symtab ();
#endif
if (optimize && flag_devirtualize) if (optimize && flag_devirtualize)
build_type_inheritance_graph (); build_type_inheritance_graph ();
if (file) if (file)
......
...@@ -501,10 +501,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, ...@@ -501,10 +501,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_hwi_stream (ob->main_stream, ref); streamer_write_hwi_stream (ob->main_stream, ref);
} }
group = node->get_section (); section = node->get_section ();
if (group) if (!section)
section = TREE_STRING_POINTER (group);
else
section = ""; section = "";
lto_output_data_stream (ob->main_stream, section, strlen (section) + 1); lto_output_data_stream (ob->main_stream, section, strlen (section) + 1);
...@@ -521,6 +519,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, ...@@ -521,6 +519,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->forced_by_abi, 1); bp_pack_value (&bp, node->forced_by_abi, 1);
bp_pack_value (&bp, node->unique_name, 1); bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp, node->body_removed, 1); bp_pack_value (&bp, node->body_removed, 1);
bp_pack_value (&bp, node->implicit_section, 1);
bp_pack_value (&bp, node->address_taken, 1); bp_pack_value (&bp, node->address_taken, 1);
bp_pack_value (&bp, tag == LTO_symtab_analyzed_node bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
&& symtab_get_symbol_partitioning_class (node) == SYMBOL_PARTITION && symtab_get_symbol_partitioning_class (node) == SYMBOL_PARTITION
...@@ -585,6 +584,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node, ...@@ -585,6 +584,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
bp_pack_value (&bp, node->forced_by_abi, 1); bp_pack_value (&bp, node->forced_by_abi, 1);
bp_pack_value (&bp, node->unique_name, 1); bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp, node->body_removed, 1); bp_pack_value (&bp, node->body_removed, 1);
bp_pack_value (&bp, node->implicit_section, 1);
bp_pack_value (&bp, node->writeonly, 1); bp_pack_value (&bp, node->writeonly, 1);
bp_pack_value (&bp, node->definition, 1); bp_pack_value (&bp, node->definition, 1);
alias_p = node->alias && (!boundary_p || node->weakref); alias_p = node->alias && (!boundary_p || node->weakref);
...@@ -631,10 +631,8 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node, ...@@ -631,10 +631,8 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
streamer_write_hwi_stream (ob->main_stream, ref); streamer_write_hwi_stream (ob->main_stream, ref);
} }
group = node->get_section (); section = node->get_section ();
if (group) if (!section)
section = TREE_STRING_POINTER (group);
else
section = ""; section = "";
lto_output_data_stream (ob->main_stream, section, strlen (section) + 1); lto_output_data_stream (ob->main_stream, section, strlen (section) + 1);
...@@ -1054,6 +1052,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, ...@@ -1054,6 +1052,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->forced_by_abi = bp_unpack_value (bp, 1); node->forced_by_abi = bp_unpack_value (bp, 1);
node->unique_name = bp_unpack_value (bp, 1); node->unique_name = bp_unpack_value (bp, 1);
node->body_removed = bp_unpack_value (bp, 1); node->body_removed = bp_unpack_value (bp, 1);
node->implicit_section = bp_unpack_value (bp, 1);
node->address_taken = bp_unpack_value (bp, 1); node->address_taken = bp_unpack_value (bp, 1);
node->used_from_other_partition = bp_unpack_value (bp, 1); node->used_from_other_partition = bp_unpack_value (bp, 1);
node->lowered = bp_unpack_value (bp, 1); node->lowered = bp_unpack_value (bp, 1);
...@@ -1194,7 +1193,7 @@ input_node (struct lto_file_decl_data *file_data, ...@@ -1194,7 +1193,7 @@ input_node (struct lto_file_decl_data *file_data,
else else
node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND; node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
if (section) if (section)
node->set_section (section); node->set_section_for_node (section);
if (node->thunk.thunk_p) if (node->thunk.thunk_p)
{ {
...@@ -1251,6 +1250,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, ...@@ -1251,6 +1250,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->forced_by_abi = bp_unpack_value (&bp, 1); node->forced_by_abi = bp_unpack_value (&bp, 1);
node->unique_name = bp_unpack_value (&bp, 1); node->unique_name = bp_unpack_value (&bp, 1);
node->body_removed = bp_unpack_value (&bp, 1); node->body_removed = bp_unpack_value (&bp, 1);
node->implicit_section = bp_unpack_value (&bp, 1);
node->writeonly = bp_unpack_value (&bp, 1); node->writeonly = bp_unpack_value (&bp, 1);
node->definition = bp_unpack_value (&bp, 1); node->definition = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1);
...@@ -1277,7 +1277,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, ...@@ -1277,7 +1277,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND; node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
section = read_string_cst (ib); section = read_string_cst (ib);
if (section) if (section)
node->set_section (section); node->set_section_for_node (section);
node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution, node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN); LDPR_NUM_KNOWN);
gcc_assert (flag_ltrans gcc_assert (flag_ltrans
......
2014-06-10 Jan Hubicka <hubicka@ucw.cz>
* lto.c (read_cgraph_and_symbols): Remove unreachable symbols.
(do_whole_program_analysis): Use verify_symtab.
2014-06-07 Jan Hubicka <hubicka@ucw.cz> 2014-06-07 Jan Hubicka <hubicka@ucw.cz>
* lto.c (mentions_vars_p_decl_with_vis, compare_tree_sccs_1, * lto.c (mentions_vars_p_decl_with_vis, compare_tree_sccs_1,
......
...@@ -3090,6 +3090,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) ...@@ -3090,6 +3090,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
dump_symtab (cgraph_dump_file); dump_symtab (cgraph_dump_file);
} }
lto_symtab_merge_symbols (); lto_symtab_merge_symbols ();
/* Removal of unreacable symbols is needed to make verify_symtab to pass;
we are still having duplicated comdat groups containing local statics.
We could also just remove them while merging. */
symtab_remove_unreachable_nodes (false, dump_file);
ggc_collect (); ggc_collect ();
cgraph_state = CGRAPH_STATE_IPA_SSA; cgraph_state = CGRAPH_STATE_IPA_SSA;
...@@ -3261,7 +3265,7 @@ do_whole_program_analysis (void) ...@@ -3261,7 +3265,7 @@ do_whole_program_analysis (void)
dump_symtab (cgraph_dump_file); dump_symtab (cgraph_dump_file);
} }
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_cgraph (); verify_symtab ();
#endif #endif
bitmap_obstack_release (NULL); bitmap_obstack_release (NULL);
......
...@@ -565,7 +565,9 @@ dump_symtab_base (FILE *f, symtab_node *node) ...@@ -565,7 +565,9 @@ dump_symtab_base (FILE *f, symtab_node *node)
fprintf (f, " one_only"); fprintf (f, " one_only");
if (node->get_section ()) if (node->get_section ())
fprintf (f, " section:%s", fprintf (f, " section:%s",
TREE_STRING_POINTER (node->get_section ())); node->get_section ());
if (node->implicit_section)
fprintf (f," (implicit_section)");
if (DECL_VISIBILITY_SPECIFIED (node->decl)) if (DECL_VISIBILITY_SPECIFIED (node->decl))
fprintf (f, " visibility_specified"); fprintf (f, " visibility_specified");
if (DECL_VISIBILITY (node->decl)) if (DECL_VISIBILITY (node->decl))
...@@ -791,6 +793,7 @@ verify_symtab_base (symtab_node *node) ...@@ -791,6 +793,7 @@ verify_symtab_base (symtab_node *node)
{ {
struct ipa_ref_list *refs = &node->ref_list; struct ipa_ref_list *refs = &node->ref_list;
struct ipa_ref *ref; struct ipa_ref *ref;
for (int i = 0; ipa_ref_list_referring_iterate (refs, i, ref); ++i) for (int i = 0; ipa_ref_list_referring_iterate (refs, i, ref); ++i)
{ {
if (!symtab_in_same_comdat_p (ref->referring, node)) if (!symtab_in_same_comdat_p (ref->referring, node))
...@@ -803,6 +806,38 @@ verify_symtab_base (symtab_node *node) ...@@ -803,6 +806,38 @@ verify_symtab_base (symtab_node *node)
} }
} }
} }
if (node->implicit_section && !node->get_section ())
{
error ("implicit_section flag is set but section isn't");
error_found = true;
}
if (node->get_section () && node->get_comdat_group ()
&& !node->implicit_section)
{
error ("Both section and comdat group is set");
error_found = true;
}
/* TODO: Add string table for sections, so we do not keep holding duplicated
strings. */
if (node->alias && node->definition
&& node->get_section () != symtab_alias_target (node)->get_section ()
&& (!node->get_section()
|| !symtab_alias_target (node)->get_section ()
|| strcmp (node->get_section(),
symtab_alias_target (node)->get_section ())))
{
error ("Alias and target's section differs");
dump_symtab_node (stderr, symtab_alias_target (node));
error_found = true;
}
if (node->alias && node->definition
&& node->get_comdat_group () != symtab_alias_target (node)->get_comdat_group ())
{
error ("Alias and target's comdat groups differs");
dump_symtab_node (stderr, symtab_alias_target (node));
error_found = true;
}
return error_found; return error_found;
} }
...@@ -832,8 +867,30 @@ DEBUG_FUNCTION void ...@@ -832,8 +867,30 @@ DEBUG_FUNCTION void
verify_symtab (void) verify_symtab (void)
{ {
symtab_node *node; symtab_node *node;
pointer_map<symtab_node *> comdat_head_map;
FOR_EACH_SYMBOL (node) FOR_EACH_SYMBOL (node)
verify_symtab_node (node); {
verify_symtab_node (node);
if (node->get_comdat_group ())
{
symtab_node **entry, *s;
bool existed;
entry = comdat_head_map.insert (node->get_comdat_group (), &existed);
if (!existed)
*entry = node;
else
for (s = (*entry)->same_comdat_group; s != NULL && s != node; s = s->same_comdat_group)
if (!s || s == *entry)
{
error ("Two symbols with same comdat_group are not linked by the same_comdat_group list.");
dump_symtab_node (stderr, *entry);
dump_symtab_node (stderr, s);
internal_error ("verify_symtab failed");
}
}
}
} }
/* Return true when RESOLUTION indicate that linker will use /* Return true when RESOLUTION indicate that linker will use
...@@ -1024,6 +1081,33 @@ fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target) ...@@ -1024,6 +1081,33 @@ fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target)
node->externally_visible = target->externally_visible; node->externally_visible = target->externally_visible;
} }
/* Worker for set_section. */
static bool
set_section_1 (struct symtab_node *n, void *s)
{
n->set_section_for_node ((tree)s);
return false;
}
/* Set section of symbol and its aliases. */
void
symtab_node::set_section (tree section)
{
gcc_assert (!this->alias);
symtab_for_node_and_aliases (this, set_section_1, section, true);
}
/* Worker for symtab_resolve_alias. */
static bool
set_implicit_section (struct symtab_node *n, void *data ATTRIBUTE_UNUSED)
{
n->implicit_section = true;
return false;
}
/* Add reference recording that NODE is alias of TARGET. /* Add reference recording that NODE is alias of TARGET.
The function can fail in the case of aliasing cycles; in this case The function can fail in the case of aliasing cycles; in this case
it returns false. */ it returns false. */
...@@ -1058,6 +1142,25 @@ symtab_resolve_alias (symtab_node *node, symtab_node *target) ...@@ -1058,6 +1142,25 @@ symtab_resolve_alias (symtab_node *node, symtab_node *target)
node->analyzed = true; node->analyzed = true;
ipa_record_reference (node, target, IPA_REF_ALIAS, NULL); ipa_record_reference (node, target, IPA_REF_ALIAS, NULL);
/* Add alias into the comdat group of its target unless it is already there. */
if (node->same_comdat_group)
symtab_remove_from_same_comdat_group (node);
node->set_comdat_group (NULL);
if (target->get_comdat_group ())
symtab_add_to_same_comdat_group (node, target);
if ((node->get_section () != target->get_section ()
|| target->get_comdat_group ())
&& node->get_section () && !node->implicit_section)
{
error ("section of alias %q+D must match section of its target",
node->decl);
}
symtab_for_node_and_aliases (node, set_section_1, target->get_section_name (), true);
if (target->implicit_section)
symtab_for_node_and_aliases (node,
set_implicit_section, NULL, true);
/* Alias targets become redundant after alias is resolved into an reference. /* Alias targets become redundant after alias is resolved into an reference.
We do not want to keep it around or we would have to mind updating them We do not want to keep it around or we would have to mind updating them
when renaming symbols. */ when renaming symbols. */
......
...@@ -1452,8 +1452,6 @@ struct GTY(()) tree_decl_with_vis { ...@@ -1452,8 +1452,6 @@ struct GTY(()) tree_decl_with_vis {
unsigned dllimport_flag : 1; unsigned dllimport_flag : 1;
/* Don't belong to VAR_DECL exclusively. */ /* Don't belong to VAR_DECL exclusively. */
unsigned weak_flag : 1; unsigned weak_flag : 1;
/* When SECTION_NAME is implied by -ffunction-section. */
unsigned implicit_section_name_p : 1;
unsigned seen_in_bind_expr : 1; unsigned seen_in_bind_expr : 1;
unsigned comdat_flag : 1; unsigned comdat_flag : 1;
...@@ -1472,7 +1470,7 @@ struct GTY(()) tree_decl_with_vis { ...@@ -1472,7 +1470,7 @@ struct GTY(()) tree_decl_with_vis {
unsigned cxx_destructor : 1; unsigned cxx_destructor : 1;
/* Belong to FUNCTION_DECL exclusively. */ /* Belong to FUNCTION_DECL exclusively. */
unsigned final : 1; unsigned final : 1;
/* 11 unused bits. */ /* 12 unused bits. */
}; };
struct GTY(()) tree_var_decl { struct GTY(()) tree_var_decl {
......
...@@ -5215,7 +5215,7 @@ vect_can_force_dr_alignment_p (const_tree decl, unsigned int alignment) ...@@ -5215,7 +5215,7 @@ vect_can_force_dr_alignment_p (const_tree decl, unsigned int alignment)
software projects. */ software projects. */
if (TREE_STATIC (decl) if (TREE_STATIC (decl)
&& DECL_SECTION_NAME (decl) != NULL_TREE && DECL_SECTION_NAME (decl) != NULL_TREE
&& !DECL_HAS_IMPLICIT_SECTION_NAME_P (decl)) && !symtab_get_node (decl)->implicit_section)
return false; return false;
if (TREE_STATIC (decl)) if (TREE_STATIC (decl))
......
...@@ -634,7 +634,7 @@ decl_section_name (const_tree node) ...@@ -634,7 +634,7 @@ decl_section_name (const_tree node)
struct symtab_node *snode = symtab_get_node (node); struct symtab_node *snode = symtab_get_node (node);
if (!snode) if (!snode)
return NULL; return NULL;
return snode->get_section (); return snode->get_section_name ();
} }
/* Set section section name of NODE to VALUE (that is expected to /* Set section section name of NODE to VALUE (that is expected to
......
...@@ -2399,11 +2399,6 @@ extern void decl_value_expr_insert (tree, tree); ...@@ -2399,11 +2399,6 @@ extern void decl_value_expr_insert (tree, tree);
#define DECL_HAS_INIT_PRIORITY_P(NODE) \ #define DECL_HAS_INIT_PRIORITY_P(NODE) \
(VAR_DECL_CHECK (NODE)->decl_with_vis.init_priority_p) (VAR_DECL_CHECK (NODE)->decl_with_vis.init_priority_p)
/* Specify whether the section name was set by user or by
compiler via -ffunction-sections. */
#define DECL_HAS_IMPLICIT_SECTION_NAME_P(NODE) \
(DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.implicit_section_name_p)
extern tree decl_debug_expr_lookup (tree); extern tree decl_debug_expr_lookup (tree);
extern void decl_debug_expr_insert (tree, tree); extern void decl_debug_expr_insert (tree, tree);
......
...@@ -418,6 +418,15 @@ get_named_section (tree decl, const char *name, int reloc) ...@@ -418,6 +418,15 @@ get_named_section (tree decl, const char *name, int reloc)
return get_section (name, flags, decl); return get_section (name, flags, decl);
} }
/* Worker for resolve_unique_section. */
static bool
set_implicit_section (struct symtab_node *n, void *data ATTRIBUTE_UNUSED)
{
n->implicit_section = true;
return false;
}
/* If required, set DECL_SECTION_NAME to a unique name. */ /* If required, set DECL_SECTION_NAME to a unique name. */
void void
...@@ -430,7 +439,9 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED, ...@@ -430,7 +439,9 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
|| DECL_COMDAT_GROUP (decl))) || DECL_COMDAT_GROUP (decl)))
{ {
targetm.asm_out.unique_section (decl, reloc); targetm.asm_out.unique_section (decl, reloc);
DECL_HAS_IMPLICIT_SECTION_NAME_P (decl) = true; if (DECL_SECTION_NAME (decl))
symtab_for_node_and_aliases (symtab_get_node (decl),
set_implicit_section, NULL, true);
} }
} }
...@@ -510,7 +521,7 @@ get_named_text_section (tree decl, ...@@ -510,7 +521,7 @@ get_named_text_section (tree decl,
buffer = ACONCAT ((stripped_name, named_section_suffix, NULL)); buffer = ACONCAT ((stripped_name, named_section_suffix, NULL));
return get_named_section (decl, buffer, 0); return get_named_section (decl, buffer, 0);
} }
else if (DECL_HAS_IMPLICIT_SECTION_NAME_P (decl)) else if (symtab_get_node (decl)->implicit_section)
{ {
const char *name; const char *name;
...@@ -539,8 +550,7 @@ default_function_section (tree decl, enum node_frequency freq, ...@@ -539,8 +550,7 @@ default_function_section (tree decl, enum node_frequency freq,
/* Old GNU linkers have buggy --gc-section support, which sometimes /* Old GNU linkers have buggy --gc-section support, which sometimes
results in .gcc_except_table* sections being garbage collected. */ results in .gcc_except_table* sections being garbage collected. */
if (decl if (decl
&& DECL_SECTION_NAME (decl) && symtab_get_node (decl)->implicit_section)
&& DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
return NULL; return NULL;
#endif #endif
...@@ -6764,7 +6774,7 @@ default_binds_local_p_1 (const_tree exp, int shlib) ...@@ -6764,7 +6774,7 @@ default_binds_local_p_1 (const_tree exp, int shlib)
definition from different object file) and when resolution info is available definition from different object file) and when resolution info is available
we simply use the knowledge passed to us by linker plugin. */ we simply use the knowledge passed to us by linker plugin. */
bool bool
decl_binds_to_current_def_p (tree decl) decl_binds_to_current_def_p (const_tree decl)
{ {
gcc_assert (DECL_P (decl)); gcc_assert (DECL_P (decl));
if (!targetm.binds_local_p (decl)) if (!targetm.binds_local_p (decl))
......
...@@ -32,7 +32,7 @@ extern void notice_global_symbol (tree); ...@@ -32,7 +32,7 @@ extern void notice_global_symbol (tree);
extern void set_user_assembler_name (tree, const char *); extern void set_user_assembler_name (tree, const char *);
extern void process_pending_assemble_externals (void); extern void process_pending_assemble_externals (void);
extern bool decl_replaceable_p (tree); extern bool decl_replaceable_p (tree);
extern bool decl_binds_to_current_def_p (tree); extern bool decl_binds_to_current_def_p (const_tree);
extern enum tls_model decl_default_tls_model (const_tree); extern enum tls_model decl_default_tls_model (const_tree);
/* Declare DECL to be a weak symbol. */ /* Declare DECL to be a weak symbol. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment