summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/ia64/hpux.h11
-rw-r--r--gcc/config/ia64/ia64-protos.h2
-rw-r--r--gcc/config/ia64/ia64.c82
-rw-r--r--gcc/config/ia64/ia64.h2
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. */