diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-26 18:39:06 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-26 18:39:06 +0000 |
commit | 21543d4cd558cada630271a0cf3075ad7ce94cbf (patch) | |
tree | 08bdb3f3e0a9d0f71e72bb56d9ddb7b916e7dfeb /gcc/symtab.c | |
parent | ed0bc1ffb674fe93d0df68654b5bb76869f0bc8c (diff) | |
download | gcc-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.c | 308 |
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" |