void change_decl_assembler_name (tree decl, tree name) { symtab_node node = NULL; /* We can have user ASM names on things, like global register variables, that are not in the symbol table. */ if ((TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) || TREE_CODE (decl) == FUNCTION_DECL) node = symtab_get_node (decl); if (!DECL_ASSEMBLER_NAME_SET_P (decl)) { SET_DECL_ASSEMBLER_NAME (decl, name); if (node) insert_to_assembler_name_hash (node); } else { if (name == DECL_ASSEMBLER_NAME (decl)) return; if (node) unlink_from_assembler_name_hash (node); 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); } }
tree make_alias_for (tree function, tree newid) { tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (function); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_THIS_STATIC (alias) = 1; DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_CLONED_FUNCTION (alias) = NULL_TREE; DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_NO_STATIC_CHAIN (alias) = 1; DECL_PENDING_INLINE_P (alias) = 0; DECL_INLINE (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_DEFERRED_FN (alias) = 0; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INSTANTIATED (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; DECL_INITIAL (alias) = error_mark_node; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; return alias; }
static bool decide_is_function_needed (struct cgraph_node *node, tree decl) { if (MAIN_NAME_P (DECL_NAME (decl)) && TREE_PUBLIC (decl)) { node->local.externally_visible = true; return true; } /* If the user told us it is used, then it must be so. */ if (node->local.externally_visible) return true; /* ??? If the assembler name is set by hand, it is possible to assemble the name later after finalizing the function and the fact is noticed in assemble_name then. This is arguably a bug. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) return true; /* With -fkeep-inline-functions we are keeping all inline functions except for extern inline ones. */ if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (decl) && !DECL_EXTERNAL (decl) && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))) return true; /* If we decided it was needed before, but at the time we didn't have the body of the function available, then it's still needed. We have to go back and re-check its dependencies now. */ if (node->needed) return true; /* Externally visible functions must be output. The exception is COMDAT functions that must be output only when they are needed. When not optimizing, also output the static functions. (see PR24561), but don't do so for always_inline functions, functions declared inline and nested functions. These was optimized out in the original implementation and it is unclear whether we want to change the behavior here. */ if (((TREE_PUBLIC (decl) || (!optimize && !node->local.disregard_inline_limits && !DECL_DECLARED_INLINE_P (decl) && !node->origin)) && !flag_whole_program) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; /* Constructors and destructors are reachable from the runtime by some mechanism. */ if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl)) return true; return false; }
static tree make_alias_for_thunk (tree function) { tree alias; char buf[256]; #if defined (TARGET_IS_PE_COFF) if (DECL_ONE_ONLY (function)) return function; #endif ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno); thunk_labelno++; alias = build_decl (FUNCTION_DECL, get_identifier (buf), TREE_TYPE (function)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (function); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_THIS_STATIC (alias) = 1; DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_CLONED_FUNCTION (alias) = NULL_TREE; DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_NO_STATIC_CHAIN (alias) = 1; DECL_PENDING_INLINE_P (alias) = 0; DECL_INLINE (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_DEFERRED_FN (alias) = 0; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INSTANTIATED (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; DECL_INITIAL (alias) = error_mark_node; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; if (!flag_syntax_only) assemble_alias (alias, DECL_ASSEMBLER_NAME (function)); return alias; }
/* Determine if variable DECL is needed. That is, visible to something either outside this translation unit, something magic in the system configury */ bool decide_is_variable_needed (struct varpool_node *node, tree decl) { /* If the user told us it is used, then it must be so. */ if ((node->externally_visible && !DECL_COMDAT (decl)) || node->force_output) return true; /* ??? If the assembler name is set by hand, it is possible to assemble the name later after finalizing the function and the fact is noticed in assemble_name then. This is arguably a bug. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) return true; /* Externally visible variables must be output. The exception is COMDAT variables that must be output only when they are needed. */ if (TREE_PUBLIC (decl) && !flag_whole_program && !flag_lto && !flag_whopr && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; /* When emulating tls, we actually see references to the control variable, rather than the user-level variable. */ if (!targetm.have_tls && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)) { tree control = emutls_decl (decl); if (decide_is_variable_needed (varpool_node (control), control)) return true; } /* When not reordering top level variables, we have to assume that we are going to keep everything. */ if (flag_toplevel_reorder) return false; /* We want to emit COMDAT variables only when absolutely necessary. */ if (DECL_COMDAT (decl)) return false; return true; }
void symbol_table::change_decl_assembler_name (tree decl, tree name) { symtab_node *node = NULL; /* We can have user ASM names on things, like global register variables, that are not in the symbol table. */ if ((TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) || TREE_CODE (decl) == FUNCTION_DECL) node = symtab_node::get (decl); if (!DECL_ASSEMBLER_NAME_SET_P (decl)) { SET_DECL_ASSEMBLER_NAME (decl, name); if (node) insert_to_assembler_name_hash (node, true); } else { if (name == DECL_ASSEMBLER_NAME (decl)) return; tree alias = (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) ? TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) : NULL); if (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 (alias) { IDENTIFIER_TRANSPARENT_ALIAS (name) = 1; TREE_CHAIN (name) = alias; } if (node) insert_to_assembler_name_hash (node, true); } }
tree make_alias_for (tree target, tree newid) { tree alias = build_decl (DECL_SOURCE_LOCATION (target), TREE_CODE (target), newid, TREE_TYPE (target)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (target); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (target); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (target); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; if (DECL_LANG_SPECIFIC (alias)) { DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; } DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_TEMPLATE_INSTANTIATED (alias) = 0; if (TREE_CODE (alias) == FUNCTION_DECL) { DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_PENDING_INLINE_P (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_INITIAL (alias) = error_mark_node; DECL_ARGUMENTS (alias) = copy_list (DECL_ARGUMENTS (target)); } else TREE_STATIC (alias) = 1; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; return alias; }