/* Output one variable, if necessary. Return whether we output it. */ bool varpool_assemble_decl (struct varpool_node *node) { tree decl = node->decl; if (!TREE_ASM_WRITTEN (decl) && !node->alias && !DECL_EXTERNAL (decl) && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl))) { assemble_variable (decl, 0, 1, 0); if (TREE_ASM_WRITTEN (decl)) { struct varpool_node *alias; node->next_needed = varpool_assembled_nodes_queue; varpool_assembled_nodes_queue = node; node->finalized = 1; /* Also emit any extra name aliases. */ for (alias = node->extra_name; alias; alias = alias->next) { /* Update linkage fields in case they've changed. */ DECL_WEAK (alias->decl) = DECL_WEAK (decl); TREE_PUBLIC (alias->decl) = TREE_PUBLIC (decl); DECL_VISIBILITY (alias->decl) = DECL_VISIBILITY (decl); assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (decl)); } return true; } } return false; }
static void assemble_aliases (struct varpool_node *node) { int i; struct ipa_ref *ref; for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { struct varpool_node *alias = ipa_ref_refering_varpool_node (ref); assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (alias->alias_of)); assemble_aliases (alias); } }
static tree make_alias_for_thunk (tree function) { tree alias; char buf[256]; ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno); thunk_labelno++; alias = make_alias_for (function, get_identifier (buf)); if (!flag_syntax_only) assemble_alias (alias, DECL_ASSEMBLER_NAME (function)); return alias; }
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; }
void rest_of_decl_compilation (tree decl, int top_level, int at_end) { /* We deferred calling assemble_alias so that we could collect other attributes such as visibility. Emit the alias now. */ { tree alias; alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)); if (alias) { alias = TREE_VALUE (TREE_VALUE (alias)); alias = get_identifier (TREE_STRING_POINTER (alias)); assemble_alias (decl, alias); } } /* Emit tm_* attributes for declarations now */ { tree tm_attribute; tm_attribute = lookup_attribute ("tm_wrapper", DECL_ATTRIBUTES (decl)); if (tm_attribute == NULL) tm_attribute = lookup_attribute ("transaction_wrap", DECL_ATTRIBUTES (decl)); if (tm_attribute) { tm_attribute = TREE_VALUE (TREE_VALUE (tm_attribute)); tm_attribute = get_identifier (TREE_STRING_POINTER (tm_attribute)); assemble_tm_wrapper (decl, tm_attribute); } if (has_tm_pure_attribute(decl)) { assemble_tm_pure (decl); } if (has_tm_callable_attribute(decl)) { assemble_tm_callable (decl); } } /* Can't defer this, because it needs to happen before any later function definitions are processed. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && DECL_REGISTER (decl)) /* LLVM LOCAL begin */ #ifndef ENABLE_LLVM make_decl_rtl (decl); #else make_decl_llvm (decl); #endif /* LLVM LOCAL end */ /* Forward declarations for nested functions are not "external", but we need to treat them as if they were. */ if (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) { timevar_push (TV_VARCONST); /* Don't output anything when a tentative file-scope definition is seen. But at end of compilation, do output code for them. We do output all variables when unit-at-a-time is active and rely on callgraph code to defer them except for forward declarations (see gcc.c-torture/compile/920624-1.c) */ if ((at_end || !DECL_DEFER_OUTPUT (decl) || DECL_INITIAL (decl)) && !DECL_EXTERNAL (decl)) { if (TREE_CODE (decl) != FUNCTION_DECL) cgraph_varpool_finalize_decl (decl); else assemble_variable (decl, top_level, at_end, 0); } #ifdef ASM_FINISH_DECLARE_OBJECT if (decl == last_assemble_variable_decl) { ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl, top_level, at_end); } #endif timevar_pop (TV_VARCONST); } else if (TREE_CODE (decl) == TYPE_DECL /* Like in rest_of_type_compilation, avoid confusing the debug information machinery when there are errors. */ && !(sorrycount || errorcount)) { /* LLVM LOCAL begin */ #ifndef ENABLE_LLVM timevar_push (TV_SYMOUT); debug_hooks->type_decl (decl, !top_level); timevar_pop (TV_SYMOUT); #else llvm_emit_typedef (decl); #endif /* LLVM LOCAL end */ } /* Let cgraph know about the existence of variables. */ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) cgraph_varpool_node (decl); }
void rest_of_decl_compilation (tree decl, int top_level, int at_end) { /* We deferred calling assemble_alias so that we could collect other attributes such as visibility. Emit the alias now. */ { tree alias; alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)); if (alias) { alias = TREE_VALUE (TREE_VALUE (alias)); alias = get_identifier (TREE_STRING_POINTER (alias)); assemble_alias (decl, alias); #ifdef KEY // Put aliases into the list of decls emitted by g++ so that we can // iterate through the list when expanding aliases to WHIRL. An alias // can be expanded only if its target, which can be another alias, is // expanded. Bug 4393. if (flag_spin_file) gspin_gxx_emits_decl(decl); #endif } } /* Can't defer this, because it needs to happen before any later function definitions are processed. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && DECL_REGISTER (decl)) make_decl_rtl (decl); /* Forward declarations for nested functions are not "external", but we need to treat them as if they were. */ if (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) { timevar_push (TV_VARCONST); /* Don't output anything when a tentative file-scope definition is seen. But at end of compilation, do output code for them. We do output all variables when unit-at-a-time is active and rely on callgraph code to defer them except for forward declarations (see gcc.c-torture/compile/920624-1.c) */ if ((at_end || !DECL_DEFER_OUTPUT (decl) || DECL_INITIAL (decl)) && !DECL_EXTERNAL (decl)) { if (TREE_CODE (decl) != FUNCTION_DECL) cgraph_varpool_finalize_decl (decl); else assemble_variable (decl, top_level, at_end, 0); } #ifdef ASM_FINISH_DECLARE_OBJECT if (decl == last_assemble_variable_decl) { ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl, top_level, at_end); } #endif timevar_pop (TV_VARCONST); } else if (TREE_CODE (decl) == TYPE_DECL /* Like in rest_of_type_compilation, avoid confusing the debug information machinery when there are errors. */ && !(sorrycount || errorcount)) { timevar_push (TV_SYMOUT); debug_hooks->type_decl (decl, !top_level); timevar_pop (TV_SYMOUT); } /* Let cgraph know about the existence of variables. */ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) cgraph_varpool_node (decl); }