diff options
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/ia64/hpux.h | 11 | ||||
-rw-r--r-- | gcc/config/ia64/ia64-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 82 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 2 |
5 files changed, 101 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6df6abd98d6..3daf7425a0f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2002-09-09 Steve Ellcey <sje@cup.hp.com> + + * config/ia64/hpux.h (TARGET_HPUX_LD): New, define true. + (ASM_FILE_END) New. + * config/ia64/ia64.h (TARGET_HPUX_LD): New, define false. + * config/ia64/ia64-protos.h (ia64_hpux_asm_file_end): New. + * config/ia64/ia64.c (ia64_asm_output_external): Create list + of external functions if TARGET_HPUX_LD is true. + (ia64_hpux_add_extern_decl): New, routine to put names on + list of external functions. + (ia64_hpux_asm_file_end): Put out declarations for external + functions if and only if they are used. + 2002-09-09 John David Anglin <dave@hiauly1.hia.nrc.ca> * pa.md (exception_receiver, builtin_setjmp_receiver): Add blockage diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h index 968d0ed9147..0b639d19a60 100644 --- a/gcc/config/ia64/hpux.h +++ b/gcc/config/ia64/hpux.h @@ -127,3 +127,14 @@ do { \ #define REGISTER_TARGET_PRAGMAS(PFILE) \ cpp_register_pragma (PFILE, 0, "builtin", ia64_hpux_handle_builtin_pragma) + +/* Tell ia64.c that we are using the HP linker and we should delay output of + function extern declarations so that we don't output them for functions + which are never used (and may not be defined). */ + +#undef TARGET_HPUX_LD +#define TARGET_HPUX_LD 1 + +/* Put out the needed function declarations at the end. */ + +#define ASM_FILE_END(STREAM) ia64_hpux_asm_file_end(STREAM) diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index f4d264cef6f..0e0ef04f055 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -148,3 +148,5 @@ extern enum direction ia64_hpux_function_arg_padding PARAMS ((enum machine_mode, #ifdef GCC_C_PRAGMA_H extern void ia64_hpux_handle_builtin_pragma PARAMS ((cpp_reader *)); #endif + +extern void ia64_hpux_asm_file_end PARAMS ((FILE *)); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 08a2dfacbaf..c27a6fbb0cb 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -171,6 +171,9 @@ static void ia64_aix_unique_section PARAMS ((tree, int)) static void ia64_aix_select_rtx_section PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT)) ATTRIBUTE_UNUSED; + +static void ia64_hpux_add_extern_decl PARAMS ((const char *name)) + ATTRIBUTE_UNUSED; /* Table of valid machine attributes. */ static const struct attribute_spec ia64_attribute_table[] = @@ -4039,8 +4042,13 @@ ia64_asm_output_external (file, decl, name) { int save_referenced; - /* GNU as does not need anything here. */ - if (TARGET_GNU_AS) + /* 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 @@ -4055,13 +4063,18 @@ ia64_asm_output_external (file, decl, name) || ! strcmp (name, "__builtin_args_info")) return; - /* 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; + if (TARGET_HPUX_LD) + ia64_hpux_add_extern_decl (name); + 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. */ @@ -8050,6 +8063,57 @@ ia64_hpux_function_arg_padding (mode, type) : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY) ? downward : upward); } + +/* 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. */ + +struct extern_func_list +{ + struct extern_func_list *next; /* next external */ + char *name; /* name of the external */ +} *extern_func_head = 0; + +static void +ia64_hpux_add_extern_decl (name) + const char *name; +{ + struct extern_func_list *p; + + p = (struct extern_func_list *) xmalloc (sizeof (struct extern_func_list)); + p->name = xmalloc (strlen (name) + 1); + strcpy(p->name, name); + p->next = extern_func_head; + extern_func_head = p; +} + +/* Print out the list of used global functions. */ + +void +ia64_hpux_asm_file_end (file) + FILE *file; +{ + while (extern_func_head) + { + char *real_name; + tree decl; + + real_name = (* targetm.strip_name_encoding) (extern_func_head->name); + decl = get_identifier (real_name); + if (decl && ! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)) + { + TREE_ASM_WRITTEN (decl) = 1; + (*targetm.asm_out.globalize_label) (file, real_name); + fprintf (file, "%s", TYPE_ASM_OP); + assemble_name (file, real_name); + putc (',', file); + fprintf (file, TYPE_OPERAND_FMT, "function"); + putc ('\n', file); + } + extern_func_head = extern_func_head->next; + } +} + /* Switch to the section to which we should output X. The only thing special we do here is to honor small data. */ diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index bf5b995b157..5ab1c444baf 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -127,6 +127,8 @@ extern int ia64_tls_size; #define TARGET_TLS22 (ia64_tls_size == 22) #define TARGET_TLS64 (ia64_tls_size == 64) +#define TARGET_HPUX_LD 0 + /* This macro defines names of command options to set and clear bits in `target_flags'. Its definition is an initializer with a subgrouping for each command option. */ |