diff -uNrp gcc-4_1-branch/gcc.orig/config/elfos.h gcc-4_1-branch/gcc/config/elfos.h --- gcc-4_1-branch/gcc.orig/config/elfos.h 2005-11-30 11:16:19.000000000 +0000 +++ gcc-4_1-branch/gcc/config/elfos.h 2005-12-06 17:42:34.002991368 +0000 @@ -487,3 +487,17 @@ 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 + +#ifndef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END default_elf_asm_file_end +#endif diff -uNrp gcc-4_1-branch/gcc.orig/config/i386/i386-protos.h gcc-4_1-branch/gcc/config/i386/i386-protos.h --- gcc-4_1-branch/gcc.orig/config/i386/i386-protos.h 2005-11-30 11:15:19.000000000 +0000 +++ gcc-4_1-branch/gcc/config/i386/i386-protos.h 2005-12-06 17:42:34.002991368 +0000 @@ -28,6 +28,7 @@ extern int ix86_frame_pointer_required ( extern void ix86_setup_frame_addresses (void); extern void ix86_file_end (void); +extern void ix86_elf_file_end (void); extern HOST_WIDE_INT ix86_initial_elimination_offset (int, int); extern void ix86_expand_prologue (void); extern void ix86_expand_epilogue (int); diff -uNrp gcc-4_1-branch/gcc.orig/config/i386/i386.c gcc-4_1-branch/gcc/config/i386/i386.c --- gcc-4_1-branch/gcc.orig/config/i386/i386.c 2005-12-06 17:39:59.080543160 +0000 +++ gcc-4_1-branch/gcc/config/i386/i386.c 2005-12-06 17:42:34.010990152 +0000 @@ -4417,6 +4417,13 @@ ix86_file_end (void) file_end_indicate_exec_stack (); } +void +ix86_elf_file_end (void) +{ + ix86_file_end (); + default_elf_asm_file_end (); +} + /* Emit code for the SET_GOT patterns. */ const char * diff -uNrp gcc-4_1-branch/gcc.orig/config/i386/i386.h gcc-4_1-branch/gcc/config/i386/i386.h --- gcc-4_1-branch/gcc.orig/config/i386/i386.h 2005-11-30 11:15:19.000000000 +0000 +++ gcc-4_1-branch/gcc/config/i386/i386.h 2005-12-06 17:48:04.665722992 +0000 @@ -1513,7 +1513,7 @@ typedef struct ix86_args { #define EXPAND_BUILTIN_VA_START(VALIST, NEXTARG) \ ix86_va_start (VALIST, NEXTARG) -#define TARGET_ASM_FILE_END ix86_file_end +#define TARGET_ASM_FILE_END ix86_elf_file_end #define NEED_INDICATE_EXEC_STACK 0 /* Output assembler code to FILE to increment profiler label # LABELNO diff -uNrp gcc-4_1-branch/gcc.orig/config/rs6000/linux.h gcc-4_1-branch/gcc/config/rs6000/linux.h --- gcc-4_1-branch/gcc.orig/config/rs6000/linux.h 2005-11-30 11:15:31.000000000 +0000 +++ gcc-4_1-branch/gcc/config/rs6000/linux.h 2005-12-06 20:02:14.949860336 +0000 @@ -108,7 +108,8 @@ #define RELOCATABLE_NEEDS_FIXUP \ (target_flags & target_flags_explicit & MASK_RELOCATABLE) -#define TARGET_ASM_FILE_END file_end_indicate_exec_stack +#undef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END rs6000_elf_file_end #define TARGET_POSIX_IO diff -uNrp gcc-4_1-branch/gcc.orig/config/rs6000/linux64.h gcc-4_1-branch/gcc/config/rs6000/linux64.h --- gcc-4_1-branch/gcc.orig/config/rs6000/linux64.h 2005-11-30 11:15:31.000000000 +0000 +++ gcc-4_1-branch/gcc/config/rs6000/linux64.h 2005-12-06 20:02:03.882542824 +0000 @@ -543,7 +543,8 @@ while (0) #undef DRAFT_V4_STRUCT_RET #define DRAFT_V4_STRUCT_RET (!TARGET_64BIT) -#define TARGET_ASM_FILE_END rs6000_elf_end_indicate_exec_stack +#undef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END rs6000_elf_file_end #define TARGET_POSIX_IO diff -uNrp gcc-4_1-branch/gcc.orig/config/rs6000/rs6000.c gcc-4_1-branch/gcc/config/rs6000/rs6000.c --- gcc-4_1-branch/gcc.orig/config/rs6000/rs6000.c 2005-11-30 11:15:31.000000000 +0000 +++ gcc-4_1-branch/gcc/config/rs6000/rs6000.c 2005-12-06 20:17:39.014381176 +0000 @@ -611,7 +611,7 @@ static void rs6000_file_start (void); static unsigned int rs6000_elf_section_type_flags (tree, const char *, int); static void rs6000_elf_asm_out_constructor (rtx, int); static void rs6000_elf_asm_out_destructor (rtx, int); -static void rs6000_elf_end_indicate_exec_stack (void) ATTRIBUTE_UNUSED; +static void rs6000_elf_file_end (void) ATTRIBUTE_UNUSED; static void rs6000_elf_select_section (tree, int, unsigned HOST_WIDE_INT); static void rs6000_elf_unique_section (tree, int); static void rs6000_elf_select_rtx_section (enum machine_mode, rtx, @@ -18060,10 +18060,11 @@ rs6000_elf_declare_function_name (FILE * } static void -rs6000_elf_end_indicate_exec_stack (void) +rs6000_elf_file_end (void) { if (TARGET_32BIT) file_end_indicate_exec_stack (); + default_elf_asm_file_end (); } #endif diff -uNrp gcc-4_1-branch/gcc.orig/output.h gcc-4_1-branch/gcc/output.h --- gcc-4_1-branch/gcc.orig/output.h 2005-11-30 11:16:27.000000000 +0000 +++ gcc-4_1-branch/gcc/output.h 2005-12-06 17:42:34.018988936 +0000 @@ -586,6 +586,12 @@ 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 void default_elf_asm_output_external_1 (tree); +extern void default_elf_asm_file_end (void); +extern int maybe_assemble_visibility (tree); + extern int default_address_cost (rtx); /* dbxout helper functions */ diff -uNrp gcc-4_1-branch/gcc.orig/tree.h gcc-4_1-branch/gcc/tree.h --- gcc-4_1-branch/gcc.orig/tree.h 2005-11-30 11:16:27.000000000 +0000 +++ gcc-4_1-branch/gcc/tree.h 2005-12-06 17:42:34.022988328 +0000 @@ -4070,6 +4070,17 @@ extern void process_pending_assemble_ext extern void finish_aliases_1 (void); extern void finish_aliases_2 (void); +/* Linked list of all external symbols that are to be emitted by + GCC. */ + +struct extern_symbol_list GTY(()) +{ + struct extern_symbol_list *next; + tree decl; +}; + +extern GTY(()) struct extern_symbol_list *extern_symbol_head; + /* In stmt.c */ extern void expand_computed_goto (tree); extern bool parse_output_constraint (const char **, int, int, int, diff -uNrp gcc-4_1-branch/gcc.orig/varasm.c gcc-4_1-branch/gcc/varasm.c --- gcc-4_1-branch/gcc.orig/varasm.c 2005-11-30 11:16:27.000000000 +0000 +++ gcc-4_1-branch/gcc/varasm.c 2005-12-06 17:42:34.026987720 +0000 @@ -126,7 +126,6 @@ static unsigned HOST_WIDE_INT array_size 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); static int in_named_entry_eq (const void *, const void *); static hashval_t in_named_entry_hash (const void *); static void initialize_cold_section_name (void); @@ -4952,13 +4951,18 @@ default_assemble_visibility (tree decl, /* A helper function to call assemble_visibility when needed for a decl. */ -static void +int maybe_assemble_visibility (tree decl) { enum symbol_visibility vis = DECL_VISIBILITY (decl); if (vis != VISIBILITY_DEFAULT) - targetm.asm_out.visibility (decl, vis); + { + targetm.asm_out.visibility (decl, vis); + return 1; + } + else + return 0; } /* Returns 1 if the target configuration supports defining public symbols @@ -5725,4 +5729,64 @@ file_end_indicate_exec_stack (void) named_section_flags (".note.GNU-stack", flags); } +struct extern_symbol_list *extern_symbol_head; + +void +default_elf_asm_output_external_1 (tree decl) +{ + struct extern_symbol_list *p + = ggc_alloc (sizeof (struct extern_symbol_list)); + + p->decl = decl; + p->next = extern_symbol_head; + extern_symbol_head = p; +} + +/* 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) +{ + /* Ignore builtin functions. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && strstr (name, "__builtin_") == name) + return; + else + default_elf_asm_output_external_1 (decl); +} + +/* Print out the list of referenced global symbols with non-default + visibility. */ + +void +default_elf_asm_file_end (void) +{ + struct extern_symbol_list *p; + + for (p = extern_symbol_head; p; p = p->next) + { + tree decl = p->decl; + tree id = DECL_ASSEMBLER_NAME (decl); + + if (!id) + abort (); + + /* 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 (targetm.binds_local_p (decl) + && !TREE_ASM_WRITTEN (decl) + && TREE_SYMBOL_REFERENCED (id)) + { + maybe_assemble_visibility (decl); + TREE_ASM_WRITTEN (decl) = 1; + } + } + + extern_symbol_head = 0; +} + #include "gt-varasm.h"