+
+/* Return symbol used to separate symbol name from suffix. */
+
+char
+symbol_table::symbol_suffix_separator ()
+{
+#ifndef NO_DOT_IN_LABEL
+ return '.';
+#elif !defined NO_DOLLAR_IN_LABEL
+ return '$';
+#else
+ return '_';
+#endif
+}
+
+/* Return true when references to this symbol from REF must bind to current
+ definition in final executable. */
+
+bool
+symtab_node::binds_to_current_def_p (symtab_node *ref)
+{
+ if (!definition)
+ return false;
+ if (transparent_alias)
+ return definition
+ && get_alias_target()->binds_to_current_def_p (ref);
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
+ if (cnode && cnode->ifunc_resolver)
+ return false;
+ if (decl_binds_to_current_def_p (decl))
+ return true;
+
+ /* Inline clones always binds locally. */
+ if (cnode && cnode->inlined_to)
+ return true;
+
+ if (DECL_EXTERNAL (decl))
+ return false;
+
+ gcc_assert (externally_visible);
+
+ if (ref)
+ {
+ cgraph_node *cref = dyn_cast <cgraph_node *> (ref);
+ if (cref)
+ ref = cref->inlined_to;
+ }
+
+ /* If this is a reference from symbol itself and there are no aliases, we
+ may be sure that the symbol was not interposed by something else because
+ the symbol itself would be unreachable otherwise. This is important
+ to optimize recursive functions well.
+
+ This assumption may be broken by inlining: if symbol is interposable
+ but the body is available (i.e. declared inline), inliner may make
+ the body reachable even with interposition. */
+ if (this == ref && !has_aliases_p ()
+ && (!cnode
+ || symtab->state >= IPA_SSA_AFTER_INLINING
+ || get_availability () >= AVAIL_INTERPOSABLE))
+ return true;
+
+
+ /* References within one comdat group are always bound in a group. */
+ if (ref
+ && symtab->state >= IPA_SSA_AFTER_INLINING
+ && get_comdat_group ()
+ && get_comdat_group () == ref->get_comdat_group ())
+ return true;
+
+ return false;
+}
+
+/* Return true if symbol should be output to the symbol table. */
+
+bool
+symtab_node::output_to_lto_symbol_table_p (void)
+{
+ /* Only externally visible symbols matter. */
+ if (!TREE_PUBLIC (decl))
+ return false;
+ if (!real_symbol_p ())
+ return false;
+ /* FIXME: variables probably should not be considered as real symbols at
+ first place. */
+ if (VAR_P (decl) && DECL_HARD_REGISTER (decl))
+ return false;
+ if (TREE_CODE (decl) == FUNCTION_DECL && !definition
+ && fndecl_built_in_p (decl))
+ {
+ /* Builtins like those for most math functions have actual implementations
+ in libraries so make sure to output references into the symbol table to
+ make those libraries referenced. Note this is incomplete handling for
+ now and only covers math functions. */
+ if (builtin_with_linkage_p (decl))
+ return true;
+ else
+ return false;
+ }
+
+ /* We have real symbol that should be in symbol table. However try to trim
+ down the references to libraries bit more because linker will otherwise
+ bring unnecessary object files into the final link.
+ FIXME: The following checks can easily be confused i.e. by self recursive
+ function or self-referring variable. */
+
+ /* We keep external functions in symtab for sake of inlining
+ and devirtualization. We do not want to see them in symbol table as
+ references unless they are really used. */
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
+ if (cnode && (!definition || DECL_EXTERNAL (decl))
+ && cnode->callers)
+ return true;
+
+ /* Ignore all references from external vars initializers - they are not really
+ part of the compilation unit until they are used by folding. Some symbols,
+ like references to external construction vtables cannot be referred to at
+ all. We decide this at can_refer_decl_in_current_unit_p. */
+ if (!definition || DECL_EXTERNAL (decl))
+ {
+ int i;
+ struct ipa_ref *ref;
+ for (i = 0; iterate_referring (i, ref); i++)
+ {
+ if (ref->use == IPA_REF_ALIAS)
+ continue;
+ if (is_a <cgraph_node *> (ref->referring))
+ return true;
+ if (!DECL_EXTERNAL (ref->referring->decl))
+ return true;
+ }
+ return false;
+ }
+ return true;
+}