summaryrefslogtreecommitdiff
path: root/gcc/symtab.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-26 18:39:06 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-26 18:39:06 +0000
commit21543d4cd558cada630271a0cf3075ad7ce94cbf (patch)
tree08bdb3f3e0a9d0f71e72bb56d9ddb7b916e7dfeb /gcc/symtab.c
parented0bc1ffb674fe93d0df68654b5bb76869f0bc8c (diff)
downloadgcc-21543d4cd558cada630271a0cf3075ad7ce94cbf.tar.gz
2013-06-26 Basile Starynkevitch <basile@starynkevitch.net>
{{merged with trunk [4.9] svn rev. 196654-200426}} MELT branch merged with trunk rev. 200426 using svnmerge.py [gcc/] 2013-06-26 Basile Starynkevitch <basile@starynkevitch.net> {{merge with trunk [4.9] svn rev. 196654-200426}} * melt-runtime.c (melt_val2passflag): TODO_ggc_collect & TODO_do_not_ggc_collect are conditionalized. * melt/generated/warmelt-first+03.cc: Manually remove calls to MELT_TRACE_EXIT_LOCATION macro. * melt/generated/warmelt-base+03.cc: Ditto. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@200430 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/symtab.c')
-rw-r--r--gcc/symtab.c308
1 files changed, 271 insertions, 37 deletions
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 7388b2c046a..85d47a81a1f 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -102,7 +102,7 @@ eq_assembler_name (const void *p1, const void *p2)
/* Insert NODE to assembler name hash. */
static void
-insert_to_assembler_name_hash (symtab_node node)
+insert_to_assembler_name_hash (symtab_node node, bool with_clones)
{
if (is_a <varpool_node> (node) && DECL_HARD_REGISTER (node->symbol.decl))
return;
@@ -111,6 +111,9 @@ insert_to_assembler_name_hash (symtab_node node)
if (assembler_name_hash)
{
void **aslot;
+ struct cgraph_node *cnode;
+ tree decl = node->symbol.decl;
+
tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
aslot = htab_find_slot_with_hash (assembler_name_hash, name,
@@ -121,6 +124,13 @@ insert_to_assembler_name_hash (symtab_node node)
if (*aslot != NULL)
((symtab_node)*aslot)->symbol.previous_sharing_asm_name = node;
*aslot = node;
+
+ /* Update also possible inline clones sharing a decl. */
+ cnode = dyn_cast <cgraph_node> (node);
+ if (cnode && cnode->clones && with_clones)
+ for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone)
+ if (cnode->symbol.decl == decl)
+ insert_to_assembler_name_hash ((symtab_node) cnode, true);
}
}
@@ -128,10 +138,13 @@ insert_to_assembler_name_hash (symtab_node node)
/* Remove NODE from assembler name hash. */
static void
-unlink_from_assembler_name_hash (symtab_node node)
+unlink_from_assembler_name_hash (symtab_node node, bool with_clones)
{
if (assembler_name_hash)
{
+ struct cgraph_node *cnode;
+ tree decl = node->symbol.decl;
+
if (node->symbol.next_sharing_asm_name)
node->symbol.next_sharing_asm_name->symbol.previous_sharing_asm_name
= node->symbol.previous_sharing_asm_name;
@@ -155,6 +168,13 @@ unlink_from_assembler_name_hash (symtab_node node)
}
node->symbol.next_sharing_asm_name = NULL;
node->symbol.previous_sharing_asm_name = NULL;
+
+ /* Update also possible inline clones sharing a decl. */
+ cnode = dyn_cast <cgraph_node> (node);
+ if (cnode && cnode->clones && with_clones)
+ for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone)
+ if (cnode->symbol.decl == decl)
+ unlink_from_assembler_name_hash ((symtab_node) cnode, true);
}
}
@@ -163,8 +183,8 @@ unlink_from_assembler_name_hash (symtab_node node)
void
symtab_prevail_in_asm_name_hash (symtab_node node)
{
- unlink_from_assembler_name_hash (node);
- insert_to_assembler_name_hash (node);
+ unlink_from_assembler_name_hash (node, false);
+ insert_to_assembler_name_hash (node, false);
}
@@ -196,7 +216,7 @@ symtab_register_node (symtab_node node)
/* Be sure to do this last; C++ FE might create new nodes via
DECL_ASSEMBLER_NAME langhook! */
- insert_to_assembler_name_hash (node);
+ insert_to_assembler_name_hash (node, false);
}
/* Make NODE to be the one symtab hash is pointing to. Used when reshaping tree
@@ -249,7 +269,11 @@ symtab_unregister_node (symtab_node node)
node->symbol.previous = NULL;
slot = htab_find_slot (symtab_hash, node, NO_INSERT);
- if (*slot == node)
+
+ /* During LTO symtab merging we temporarily corrupt decl to symtab node
+ hash. */
+ gcc_assert ((slot && *slot) || in_lto_p);
+ if (slot && *slot && *slot == node)
{
symtab_node replacement_node = NULL;
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
@@ -259,7 +283,7 @@ symtab_unregister_node (symtab_node node)
else
*slot = replacement_node;
}
- unlink_from_assembler_name_hash (node);
+ unlink_from_assembler_name_hash (node, false);
}
/* Return symbol table node associated with DECL, if any,
@@ -271,10 +295,14 @@ symtab_get_node (const_tree decl)
symtab_node *slot;
struct symtab_node_base key;
+#ifdef ENABLE_CHECKING
+ /* Check that we are called for sane type of object - functions
+ and static or external variables. */
gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
|| (TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
|| in_lto_p)));
+#endif
if (!symtab_hash)
return NULL;
@@ -312,7 +340,7 @@ symtab_initialize_asm_name_hash (void)
htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
NULL);
FOR_EACH_SYMBOL (node)
- insert_to_assembler_name_hash (node);
+ insert_to_assembler_name_hash (node, false);
}
}
@@ -355,7 +383,7 @@ change_decl_assembler_name (tree decl, tree name)
{
SET_DECL_ASSEMBLER_NAME (decl, name);
if (node)
- insert_to_assembler_name_hash (node);
+ insert_to_assembler_name_hash (node, true);
}
else
{
@@ -363,14 +391,14 @@ change_decl_assembler_name (tree decl, tree name)
return;
if (node)
- unlink_from_assembler_name_hash (node);
+ unlink_from_assembler_name_hash (node, true);
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
&& DECL_RTL_SET_P (decl))
warning (0, "%D renamed after being referenced in assembly", decl);
SET_DECL_ASSEMBLER_NAME (decl, name);
if (node)
- insert_to_assembler_name_hash (node);
+ insert_to_assembler_name_hash (node, true);
}
}
@@ -453,15 +481,35 @@ dump_symtab_base (FILE *f, symtab_node node)
node->symbol.order,
symtab_node_name (node));
dump_addr (f, " @", (void *)node);
- fprintf (f, "\n Type: %s\n", symtab_type_names[node->symbol.type]);
- fprintf (f, " Visibility:");
-
+ fprintf (f, "\n Type: %s", symtab_type_names[node->symbol.type]);
+
+ if (node->symbol.definition)
+ fprintf (f, " definition");
+ if (node->symbol.analyzed)
+ fprintf (f, " analyzed");
+ if (node->symbol.alias)
+ fprintf (f, " alias");
+ if (node->symbol.weakref)
+ fprintf (f, " weakref");
+ 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");
if (node->symbol.used_from_other_partition)
fprintf (f, " used_from_other_partition");
if (node->symbol.force_output)
fprintf (f, " force_output");
+ if (node->symbol.forced_by_abi)
+ fprintf (f, " forced_by_abi");
+ if (node->symbol.externally_visible)
+ fprintf (f, " externally_visible");
if (node->symbol.resolution != LDPR_UNKNOWN)
fprintf (f, " %s",
ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]);
@@ -601,11 +649,23 @@ verify_symtab_base (symtab_node node)
error_found = true;
}
- hashed_node = symtab_get_node (node->symbol.decl);
- if (!hashed_node)
+ if (cgraph_state != CGRAPH_LTO_STREAMING)
{
- error ("node not found in symtab decl hashtable");
- error_found = true;
+ hashed_node = symtab_get_node (node->symbol.decl);
+ if (!hashed_node)
+ {
+ error ("node not found in symtab decl hashtable");
+ error_found = true;
+ }
+ if (hashed_node != node
+ && (!is_a <cgraph_node> (node)
+ || !dyn_cast <cgraph_node> (node)->clone_of
+ || dyn_cast <cgraph_node> (node)->clone_of->symbol.decl
+ != node->symbol.decl))
+ {
+ error ("node differs from symtab decl hashtable");
+ error_found = true;
+ }
}
if (assembler_name_hash)
{
@@ -633,6 +693,28 @@ verify_symtab_base (symtab_node node)
&& node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name != node)
{
error ("double linked list of assembler names corrupted");
+ error_found = true;
+ }
+ if (node->symbol.analyzed && !node->symbol.definition)
+ {
+ 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
+ && !node->symbol.weakref)
+ {
+ error ("node is alias but not definition");
+ error_found = true;
+ }
+ if (node->symbol.weakref && !node->symbol.alias)
+ {
+ error ("node is weakref but not an alias");
+ error_found = true;
}
if (node->symbol.same_comdat_group)
{
@@ -725,6 +807,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)
{
@@ -736,23 +819,6 @@ symtab_make_decl_local (tree decl)
if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl))
{
- /* It is possible that we are linking against library defining same COMDAT
- function. To avoid conflict we need to rename our local name of the
- function just in the case WHOPR partitioning decide to make it hidden
- to avoid cross partition references. */
- if (flag_wpa)
- {
- const char *old_name;
- symtab_node node = symtab_get_node (decl);
- old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- change_decl_assembler_name (decl,
- clone_function_name (decl, "local"));
- if (node->symbol.lto_file_data)
- lto_record_renamed_decl (node->symbol.lto_file_data,
- old_name,
- IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (decl)));
- }
DECL_SECTION_NAME (decl) = 0;
DECL_COMDAT (decl) = 0;
}
@@ -762,8 +828,6 @@ symtab_make_decl_local (tree decl)
DECL_VISIBILITY_SPECIFIED (decl) = 0;
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
TREE_PUBLIC (decl) = 0;
- DECL_VISIBILITY_SPECIFIED (decl) = 0;
- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
if (!DECL_RTL_SET_P (decl))
return;
@@ -780,4 +844,174 @@ 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. */
+
+symtab_node
+symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
+{
+ bool weakref_p = false;
+
+ if (!node->symbol.alias)
+ {
+ if (availability)
+ *availability = symtab_node_availability (node);
+ return node;
+ }
+
+ /* To determine visibility of the target, we follow ELF semantic of aliases.
+ Here alias is an alternative assembler name of a given definition. Its
+ availablity prevails the availablity of its target (i.e. static alias of
+ weak definition is available.
+
+ Weakref is a different animal (and not part of ELF per se). It is just
+ alternative name of a given symbol used within one complation unit
+ and is translated prior hitting the object file. It inherits the
+ visibility of its target (i.e. weakref of non-overwritable definition
+ is non-overwritable, while weakref of weak definition is weak).
+
+ If we ever get into supporting targets with different semantics, a target
+ hook will be needed here. */
+
+ if (availability)
+ {
+ weakref_p = node->symbol.weakref;
+ if (!weakref_p)
+ *availability = symtab_node_availability (node);
+ else
+ *availability = AVAIL_LOCAL;
+ }
+ while (node)
+ {
+ if (node->symbol.alias && node->symbol.analyzed)
+ node = symtab_alias_target (node);
+ else
+ {
+ if (!availability)
+ ;
+ else if (node->symbol.analyzed)
+ {
+ if (weakref_p)
+ {
+ enum availability a = symtab_node_availability (node);
+ if (a < *availability)
+ *availability = a;
+ }
+ }
+ else
+ *availability = AVAIL_NOT_AVAILABLE;
+ return node;
+ }
+ if (node && availability && weakref_p)
+ {
+ enum availability a = symtab_node_availability (node);
+ if (a < *availability)
+ *availability = a;
+ weakref_p = node->symbol.weakref;
+ }
+ }
+ if (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;
+
+ 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"