diff options
Diffstat (limited to 'gcc/symtab.c')
-rw-r--r-- | gcc/symtab.c | 86 |
1 files changed, 82 insertions, 4 deletions
diff --git a/gcc/symtab.c b/gcc/symtab.c index d7977f1e8d4..8158acc5bda 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -57,6 +57,10 @@ const char * const ld_plugin_symbol_resolution_names[]= "prevailing_def_ironly_exp" }; + +/* Hash table used to hold sectoons. */ +static GTY((param_is (section_hash_entry))) htab_t section_hash; + /* Hash table used to convert assembler names into nodes. */ static GTY((param_is (symtab_node))) htab_t assembler_name_hash; @@ -307,6 +311,9 @@ symtab_unregister_node (symtab_node *node) ipa_remove_all_references (&node->ref_list); ipa_remove_all_referring (&node->ref_list); + /* Remove reference to section. */ + node->set_section_for_node (NULL); + symtab_remove_from_same_comdat_group (node); if (node->previous) @@ -1081,22 +1088,92 @@ fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target) node->externally_visible = target->externally_visible; } +/* Hash sections by their names. */ + +static hashval_t +hash_section_hash_entry (const void *p) +{ + const section_hash_entry *n = (const section_hash_entry *) p; + return htab_hash_string (n->name); +} + +/* Return true if section P1 name equals to P2. */ + +static int +eq_sections (const void *p1, const void *p2) +{ + const section_hash_entry *n1 = (const section_hash_entry *) p1; + const char *name = (const char *)p2; + return n1->name == name || !strcmp (n1->name, name); +} + +/* Set section, do not recurse into aliases. + When one wants to change section of symbol and its aliases, + use set_section */ + +void +symtab_node::set_section_for_node (const char *section) +{ + const char *current = get_section (); + void **slot; + + if (current == section + || (current && section + && !strcmp (current, section))) + return; + + if (current) + { + x_section->ref_count--; + if (!x_section->ref_count) + { + slot = htab_find_slot_with_hash (section_hash, x_section->name, + htab_hash_string (x_section->name), + INSERT); + ggc_free (x_section); + htab_clear_slot (section_hash, slot); + } + x_section = NULL; + } + if (!section) + { + implicit_section = false; + return; + } + if (!section_hash) + section_hash = htab_create_ggc (10, hash_section_hash_entry, + eq_sections, NULL); + slot = htab_find_slot_with_hash (section_hash, section, + htab_hash_string (section), + INSERT); + if (*slot) + x_section = (section_hash_entry *)*slot; + else + { + int len = strlen (section); + *slot = x_section = ggc_cleared_alloc<section_hash_entry> (); + x_section->name = ggc_vec_alloc<char> (len + 1); + memcpy (x_section->name, section, len + 1); + } + x_section->ref_count++; +} + /* Worker for set_section. */ static bool set_section_1 (struct symtab_node *n, void *s) { - n->set_section_for_node ((tree)s); + n->set_section_for_node ((char *)s); return false; } /* Set section of symbol and its aliases. */ void -symtab_node::set_section (tree section) +symtab_node::set_section (const char *section) { gcc_assert (!this->alias); - symtab_for_node_and_aliases (this, set_section_1, section, true); + symtab_for_node_and_aliases (this, set_section_1, const_cast<char *>(section), true); } /* Worker for symtab_resolve_alias. */ @@ -1156,7 +1233,8 @@ symtab_resolve_alias (symtab_node *node, symtab_node *target) 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); + symtab_for_node_and_aliases (node, set_section_1, + const_cast<char *>(target->get_section ()), true); if (target->implicit_section) symtab_for_node_and_aliases (node, set_implicit_section, NULL, true); |