aboutsummaryrefslogtreecommitdiff
path: root/gcc/symtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/symtab.c')
-rw-r--r--gcc/symtab.c142
1 files changed, 102 insertions, 40 deletions
diff --git a/gcc/symtab.c b/gcc/symtab.c
index bc2865f..6ceec55 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -368,6 +368,36 @@ section_name_hasher::equal (section_hash_entry *n1, const char *name)
return n1->name == name || !strcmp (n1->name, name);
}
+/* Bump the reference count on ENTRY so that it is retained. */
+
+static section_hash_entry *
+retain_section_hash_entry (section_hash_entry *entry)
+{
+ entry->ref_count++;
+ return entry;
+}
+
+/* Drop the reference count on ENTRY and remove it if the reference
+ count drops to zero. */
+
+static void
+release_section_hash_entry (section_hash_entry *entry)
+{
+ if (entry)
+ {
+ entry->ref_count--;
+ if (!entry->ref_count)
+ {
+ hashval_t hash = htab_hash_string (entry->name);
+ section_hash_entry **slot
+ = symtab->section_hash->find_slot_with_hash (entry->name,
+ hash, INSERT);
+ ggc_free (entry);
+ symtab->section_hash->clear_slot (slot);
+ }
+ }
+}
+
/* Add node into symbol table. This function is not used directly, but via
cgraph/varpool node creation routines. */
@@ -408,10 +438,11 @@ symtab_node::remove_from_same_comdat_group (void)
}
/* Remove node from symbol table. This function is not used directly, but via
- cgraph/varpool node removal routines. */
+ cgraph/varpool node removal routines.
+ INFO is a clone info to attach to new root of clone tree (if any). */
void
-symtab_node::unregister (void)
+symtab_node::unregister (clone_info *info)
{
remove_all_references ();
remove_all_referring ();
@@ -430,7 +461,7 @@ symtab_node::unregister (void)
{
symtab_node *replacement_node = NULL;
if (cgraph_node *cnode = dyn_cast <cgraph_node *> (this))
- replacement_node = cnode->find_replacement ();
+ replacement_node = cnode->find_replacement (info);
decl->decl_with_vis.symtab_node = replacement_node;
}
if (!is_a <varpool_node *> (this) || !DECL_HARD_REGISTER (decl))
@@ -591,10 +622,9 @@ symtab_node::create_reference (symtab_node *referred_node,
gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
list = &ref_list;
- old_references = vec_safe_address (list->references);
- vec_safe_grow (list->references, vec_safe_length (list->references) + 1,
- true);
- ref = &list->references->last ();
+ old_references = list->references.address ();
+ list->references.safe_grow (list->references.length () + 1, false);
+ ref = &list->references.last ();
list2 = &referred_node->ref_list;
@@ -622,7 +652,7 @@ symtab_node::create_reference (symtab_node *referred_node,
ref->speculative = 0;
/* If vector was moved in memory, update pointers. */
- if (old_references != list->references->address ())
+ if (old_references != list->references.address ())
{
int i;
for (i = 0; iterate_reference(i, ref2); i++)
@@ -752,7 +782,8 @@ symtab_node::remove_stmt_references (gimple *stmt)
i++;
}
-/* Remove all stmt references in non-speculative references.
+/* Remove all stmt references in non-speculative references in THIS
+ and all clones.
Those are not maintained during inlining & cloning.
The exception are speculative references that are updated along
with callgraph edges associated with them. */
@@ -770,6 +801,13 @@ symtab_node::clear_stmts_in_references (void)
r->lto_stmt_uid = 0;
r->speculative_id = 0;
}
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
+ if (cnode)
+ {
+ if (cnode->clones)
+ for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone)
+ cnode->clear_stmts_in_references ();
+ }
}
/* Remove all references in ref list. */
@@ -777,9 +815,9 @@ symtab_node::clear_stmts_in_references (void)
void
symtab_node::remove_all_references (void)
{
- while (vec_safe_length (ref_list.references))
- ref_list.references->last ().remove_reference ();
- vec_free (ref_list.references);
+ while (ref_list.references.length ())
+ ref_list.references.last ().remove_reference ();
+ ref_list.references.release ();
}
/* Remove all referring items in ref list. */
@@ -1476,8 +1514,7 @@ symtab_node::copy_visibility_from (symtab_node *n)
DECL_DLLIMPORT_P (decl) = DECL_DLLIMPORT_P (n->decl);
resolution = n->resolution;
set_comdat_group (n->get_comdat_group ());
- call_for_symbol_and_aliases (symtab_node::set_section,
- const_cast<char *>(n->get_section ()), true);
+ set_section (*n);
externally_visible = n->externally_visible;
if (!DECL_RTL_SET_P (decl))
return;
@@ -1602,57 +1639,76 @@ void
symtab_node::set_section_for_node (const char *section)
{
const char *current = get_section ();
- section_hash_entry **slot;
if (current == section
|| (current && section
&& !strcmp (current, section)))
return;
- if (current)
- {
- x_section->ref_count--;
- if (!x_section->ref_count)
- {
- hashval_t hash = htab_hash_string (x_section->name);
- slot = symtab->section_hash->find_slot_with_hash (x_section->name,
- hash, INSERT);
- ggc_free (x_section);
- symtab->section_hash->clear_slot (slot);
- }
- x_section = NULL;
- }
+ release_section_hash_entry (x_section);
if (!section)
{
+ x_section = NULL;
implicit_section = false;
return;
}
if (!symtab->section_hash)
symtab->section_hash = hash_table<section_name_hasher>::create_ggc (10);
- slot = symtab->section_hash->find_slot_with_hash (section,
- htab_hash_string (section),
- INSERT);
+ section_hash_entry **slot = symtab->section_hash->find_slot_with_hash
+ (section, htab_hash_string (section), INSERT);
if (*slot)
- x_section = (section_hash_entry *)*slot;
+ x_section = retain_section_hash_entry (*slot);
else
{
int len = strlen (section);
*slot = x_section = ggc_cleared_alloc<section_hash_entry> ();
+ x_section->ref_count = 1;
x_section->name = ggc_vec_alloc<char> (len + 1);
memcpy (x_section->name, section, len + 1);
}
- x_section->ref_count++;
}
-/* Worker for set_section. */
+/* Set the section of node THIS to be the same as the section
+ of node OTHER. Keep reference counts of the sections
+ up-to-date as needed. */
+
+void
+symtab_node::set_section_for_node (const symtab_node &other)
+{
+ if (x_section == other.x_section)
+ return;
+ if (get_section () && other.get_section ())
+ gcc_checking_assert (strcmp (get_section (), other.get_section ()) != 0);
+ release_section_hash_entry (x_section);
+ if (other.x_section)
+ x_section = retain_section_hash_entry (other.x_section);
+ else
+ {
+ x_section = NULL;
+ implicit_section = false;
+ }
+}
+
+/* Workers for set_section. */
bool
-symtab_node::set_section (symtab_node *n, void *s)
+symtab_node::set_section_from_string (symtab_node *n, void *s)
{
n->set_section_for_node ((char *)s);
return false;
}
+/* Set the section of node N to be the same as the section
+ of node O. */
+
+bool
+symtab_node::set_section_from_node (symtab_node *n, void *o)
+{
+ const symtab_node &other = *static_cast<const symtab_node *> (o);
+ n->set_section_for_node (other);
+ return false;
+}
+
/* Set section of symbol and its aliases. */
void
@@ -1660,7 +1716,14 @@ symtab_node::set_section (const char *section)
{
gcc_assert (!this->alias || !this->analyzed);
call_for_symbol_and_aliases
- (symtab_node::set_section, const_cast<char *>(section), true);
+ (symtab_node::set_section_from_string, const_cast<char *>(section), true);
+}
+
+void
+symtab_node::set_section (const symtab_node &other)
+{
+ call_for_symbol_and_aliases
+ (symtab_node::set_section_from_node, const_cast<symtab_node *>(&other), true);
}
/* Return the initialization priority. */
@@ -1765,7 +1828,7 @@ symtab_node::resolve_alias (symtab_node *target, bool transparent)
{
symtab_node *n;
- gcc_assert (!analyzed && !vec_safe_length (ref_list.references));
+ gcc_assert (!analyzed && !ref_list.references.length ());
/* Never let cycles to creep into the symbol table alias references;
those will make alias walkers to be infinite. */
@@ -1806,8 +1869,7 @@ symtab_node::resolve_alias (symtab_node *target, bool transparent)
{
error ("section of alias %q+D must match section of its target", decl);
}
- call_for_symbol_and_aliases (symtab_node::set_section,
- const_cast<char *>(target->get_section ()), true);
+ set_section (*target);
if (target->implicit_section)
call_for_symbol_and_aliases (set_implicit_section, NULL, true);
@@ -1998,7 +2060,7 @@ symtab_node::get_partitioning_class (void)
if (DECL_ABSTRACT_P (decl))
return SYMBOL_EXTERNAL;
- if (cnode && cnode->inlined_to)
+ if (cnode && (cnode->inlined_to || cnode->declare_variant_alt))
return SYMBOL_DUPLICATE;
/* Transparent aliases are always duplicated. */