diff --git a/contrib/gcc/cgraphunit.c b/contrib/gcc/cgraphunit.c index 6d6ce2f1b42d..0d3ed477f9dc 100644 --- a/contrib/gcc/cgraphunit.c +++ b/contrib/gcc/cgraphunit.c @@ -1536,6 +1536,8 @@ cgraph_optimize (void) return; } + process_pending_assemble_externals (); + /* Frontend may output common variables after the unit has been finalized. It is safe to deal with them here as they are always zero initialized. */ cgraph_varpool_analyze_pending_decls (); diff --git a/contrib/gcc/config/elfos.h b/contrib/gcc/config/elfos.h index 96a8e850b006..a2bd49f909ad 100644 --- a/contrib/gcc/config/elfos.h +++ b/contrib/gcc/config/elfos.h @@ -496,13 +496,3 @@ Boston, MA 02110-1301, USA. */ fprintf ((FILE), "\"\n"); \ } \ while (0) - -/* A C statement (sans semicolon) to output to the stdio stream STREAM - any text necessary for declaring the name of an external symbol - named NAME whch is referenced in this compilation but not defined. - It is needed to properly support non-default visibility. */ - -#ifndef ASM_OUTPUT_EXTERNAL -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ - default_elf_asm_output_external (FILE, DECL, NAME) -#endif diff --git a/contrib/gcc/config/ia64/hpux.h b/contrib/gcc/config/ia64/hpux.h index bdf3968e95cd..996b7d21aa01 100644 --- a/contrib/gcc/config/ia64/hpux.h +++ b/contrib/gcc/config/ia64/hpux.h @@ -144,6 +144,10 @@ do { \ definitions, so do not use them in gthr-posix.h. */ #define GTHREAD_USE_WEAK 0 +/* Put out the needed function declarations at the end. */ + +#define TARGET_ASM_FILE_END ia64_hpux_file_end + #undef CTORS_SECTION_ASM_OP #define CTORS_SECTION_ASM_OP "\t.section\t.init_array,\t\"aw\",\"init_array\"" diff --git a/contrib/gcc/config/ia64/ia64.c b/contrib/gcc/config/ia64/ia64.c index 2bbc9a707c1f..6ddff326a5cb 100644 --- a/contrib/gcc/config/ia64/ia64.c +++ b/contrib/gcc/config/ia64/ia64.c @@ -250,6 +250,10 @@ static section *ia64_select_rtx_section (enum machine_mode, rtx, static void ia64_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; static unsigned int ia64_section_type_flags (tree, const char *, int); +static void ia64_hpux_add_extern_decl (tree decl) + ATTRIBUTE_UNUSED; +static void ia64_hpux_file_end (void) + ATTRIBUTE_UNUSED; static void ia64_init_libfuncs (void) ATTRIBUTE_UNUSED; static void ia64_hpux_init_libfuncs (void) @@ -5010,6 +5014,49 @@ ia64_secondary_reload_class (enum reg_class class, return NO_REGS; } + +/* Emit text to declare externally defined variables and functions, because + the Intel assembler does not support undefined externals. */ + +void +ia64_asm_output_external (FILE *file, tree decl, const char *name) +{ + int save_referenced; + + /* GNU as does not need anything here, but the HP linker does need + something for external functions. */ + + if (TARGET_GNU_AS + && (!TARGET_HPUX_LD + || TREE_CODE (decl) != FUNCTION_DECL + || strstr (name, "__builtin_") == name)) + return; + + /* ??? The Intel assembler creates a reference that needs to be satisfied by + the linker when we do this, so we need to be careful not to do this for + builtin functions which have no library equivalent. Unfortunately, we + can't tell here whether or not a function will actually be called by + expand_expr, so we pull in library functions even if we may not need + them later. */ + if (! strcmp (name, "__builtin_next_arg") + || ! strcmp (name, "alloca") + || ! strcmp (name, "__builtin_constant_p") + || ! strcmp (name, "__builtin_args_info")) + return; + + if (TARGET_HPUX_LD) + ia64_hpux_add_extern_decl (decl); + else + { + /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and + restore it. */ + save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)); + if (TREE_CODE (decl) == FUNCTION_DECL) + ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); + (*targetm.asm_out.globalize_label) (file, name); + TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced; + } +} /* Parse the -mfixed-range= option string. */ @@ -9176,33 +9223,55 @@ ia64_hpux_function_arg_padding (enum machine_mode mode, tree type) return DEFAULT_FUNCTION_ARG_PADDING (mode, type); } -/* Emit text to declare externally defined variables and functions, because - the Intel assembler does not support undefined externals. */ +/* Linked list of all external functions that are to be emitted by GCC. + We output the name if and only if TREE_SYMBOL_REFERENCED is set in + order to avoid putting out names that are never really used. */ -void -ia64_asm_output_external (FILE *file, tree decl, const char *name) +struct extern_func_list GTY(()) { - /* We output the name if and only if TREE_SYMBOL_REFERENCED is - set in order to avoid putting out names that are never really - used. */ - if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) - { - /* maybe_assemble_visibility will return 1 if the assembler - visibility directive is outputed. */ - int need_visibility = ((*targetm.binds_local_p) (decl) - && maybe_assemble_visibility (decl)); + struct extern_func_list *next; + tree decl; +}; - /* GNU as does not need anything here, but the HP linker does - need something for external functions. */ - if ((TARGET_HPUX_LD || !TARGET_GNU_AS) - && TREE_CODE (decl) == FUNCTION_DECL) - { - ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); - (*targetm.asm_out.globalize_label) (file, name); - } - else if (need_visibility && !TARGET_GNU_AS) - (*targetm.asm_out.globalize_label) (file, name); +static GTY(()) struct extern_func_list *extern_func_head; + +static void +ia64_hpux_add_extern_decl (tree decl) +{ + struct extern_func_list *p = ggc_alloc (sizeof (struct extern_func_list)); + + p->decl = decl; + p->next = extern_func_head; + extern_func_head = p; +} + +/* Print out the list of used global functions. */ + +static void +ia64_hpux_file_end (void) +{ + struct extern_func_list *p; + + for (p = extern_func_head; p; p = p->next) + { + tree decl = p->decl; + tree id = DECL_ASSEMBLER_NAME (decl); + + gcc_assert (id); + + if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id)) + { + const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); + + TREE_ASM_WRITTEN (decl) = 1; + (*targetm.asm_out.globalize_label) (asm_out_file, name); + fputs (TYPE_ASM_OP, asm_out_file); + assemble_name (asm_out_file, name); + fprintf (asm_out_file, "," TYPE_OPERAND_FMT "\n", "function"); + } } + + extern_func_head = 0; } /* Set SImode div/mod functions, init_integral_libfuncs only initializes diff --git a/contrib/gcc/output.h b/contrib/gcc/output.h index 1d9b837e2d75..fda098bc3e61 100644 --- a/contrib/gcc/output.h +++ b/contrib/gcc/output.h @@ -200,9 +200,9 @@ extern void assemble_variable (tree, int, int, int); DONT_OUTPUT_DATA is from assemble_variable. */ extern void align_variable (tree decl, bool dont_output_data); -/* Queue for outputing something to declare an external symbol to the - assembler. (Most assemblers don't need this, so we normally output - nothing.) Do nothing if DECL is not external. */ +/* Output something to declare an external symbol to the assembler. + (Most assemblers don't need this, so we normally output nothing.) + Do nothing if DECL is not external. */ extern void assemble_external (tree); /* Assemble code to leave SIZE bytes of zeros. */ @@ -607,10 +607,6 @@ extern void default_file_start (void); extern void file_end_indicate_exec_stack (void); extern bool default_valid_pointer_mode (enum machine_mode); -extern void default_elf_asm_output_external (FILE *file, tree, - const char *); -extern int maybe_assemble_visibility (tree); - extern int default_address_cost (rtx); /* dbxout helper functions */ diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c index 0b73a48df3b3..49458c89e766 100644 --- a/contrib/gcc/toplev.c +++ b/contrib/gcc/toplev.c @@ -1080,7 +1080,9 @@ compile_file (void) dw2_output_indirect_constants (); - /* Flush any pending external directives. */ + /* Flush any pending external directives. cgraph did this for + assemble_external calls from the front end, but the RTL + expander can also generate them. */ process_pending_assemble_externals (); /* Attach a special .ident directive to the end of the file to identify diff --git a/contrib/gcc/varasm.c b/contrib/gcc/varasm.c index d17207121fef..60a17fcdf2dc 100644 --- a/contrib/gcc/varasm.c +++ b/contrib/gcc/varasm.c @@ -126,6 +126,7 @@ static unsigned HOST_WIDE_INT array_size_for_constructor (tree); static unsigned min_align (unsigned, unsigned); static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int); static void globalize_decl (tree); +static void maybe_assemble_visibility (tree); #ifdef BSS_SECTION_ASM_OP #ifdef ASM_OUTPUT_BSS static void asm_output_bss (FILE *, tree, const char *, @@ -1956,10 +1957,11 @@ assemble_external (tree decl ATTRIBUTE_UNUSED) if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) return; - /* We want to output external symbols at very last to check if they - are references or not. */ - pending_assemble_externals = tree_cons (0, decl, - pending_assemble_externals); + if (flag_unit_at_a_time) + pending_assemble_externals = tree_cons (0, decl, + pending_assemble_externals); + else + assemble_external_real (decl); #endif } @@ -5062,18 +5064,13 @@ default_assemble_visibility (tree decl, int vis) /* A helper function to call assemble_visibility when needed for a decl. */ -int +static void maybe_assemble_visibility (tree decl) { enum symbol_visibility vis = DECL_VISIBILITY (decl); if (vis != VISIBILITY_DEFAULT) - { - targetm.asm_out.visibility (decl, vis); - return 1; - } - else - return 0; + targetm.asm_out.visibility (decl, vis); } /* Returns 1 if the target configuration supports defining public symbols @@ -6227,19 +6224,4 @@ output_object_blocks (void) htab_traverse (object_block_htab, output_object_block_htab, NULL); } -/* Emit text to declare externally defined symbols. It is needed to - properly support non-default visibility. */ -void -default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED, - tree decl, - const char *name ATTRIBUTE_UNUSED) -{ - /* We output the name if and only if TREE_SYMBOL_REFERENCED is - set in order to avoid putting out names that are never really - used. */ - if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) - && targetm.binds_local_p (decl)) - maybe_assemble_visibility (decl); -} - #include "gt-varasm.h"