This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: New target vector routine and version_id attribute for HP-UX
- From: Steve Ellcey <sje at cup dot hp dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 18 Jan 2007 14:55:56 -0800 (PST)
- Subject: Patch: New target vector routine and version_id attribute for HP-UX
- Reply-to: sje at cup dot hp dot com
This patch is to implement a version_id attribute that HP-UX uses for
function level versioning. To implement it I created a new target
routine, globalize_decl_name, that is like globalize_label but takes a
decl instead of a name. The main changes (outside of ia64.c) are in
varasm.c. I removed the use of ASM_MAKE_LABEL_LINKONCE because no one
ever sets this macro anymore (and it is undocumented) and I changed
globalize_decl to use globalize_decl_name instead of globalize_label.
I also moved the GLOBAL_ASM_OP ifdef around default_globalize_label to be
inside the routine. Since default_globalize_label is put in the target
vector (unless overridden) it should always be defined, even if it does
nothing.
Tested on IA64 HP-UX and Linux, OK for checkin?
Steve Ellcey
sje@cup.hp.com
ChangeLog:
2007-01-18 Steve Ellcey <sje@cup.hp.com>
* target.h (globalize_decl_name): New.
* target-def.h (TARGET_ASM_GLOBALIZE_DECL_NAME): New.
* output.h (default_globalize_decl_name): New.
* varasm.c (globalize_decl): Use globalize_decl_name instead of
globalize_label. Remove use of ASM_MAKE_LABEL_LINKONCE.
(default_globalize_label): Move ifdefs to inside routine.
(default_globalize_decl_name): New.
* config/ia64/ia64.c (ia64_globalize_decl_name): New.
(ia64_handle_version_id_attribute): New.
(TARGET_ASM_GLOBALIZE_DECL_NAME): New.
(ia64_asm_output_external): Use globalize_decl_name instead
of globalize_label.
Testsuite ChangeLog:
2007-01-18 Steve Ellcey <sje@cup.hp.com>
* gcc.target/ia64/versionid-1.c: New test.
* gcc.target/ia64/versionid-2.c: New test.
Index: target.h
===================================================================
--- target.h (revision 120890)
+++ target.h (working copy)
@@ -113,6 +113,9 @@ struct gcc_target
/* Output code that will globalize a label. */
void (* globalize_label) (FILE *, const char *);
+ /* Output code that will globalise a declaration. */
+ void (* globalize_decl_name) (FILE *, tree);
+
/* Output code that will emit a label for unwind info, if this
target requires such labels. Second argument is the decl the
unwind info is associated with, third is a boolean: true if
Index: target-def.h
===================================================================
--- target-def.h (revision 120890)
+++ target-def.h (working copy)
@@ -64,6 +64,10 @@ Foundation, 51 Franklin Street, Fifth Fl
#define TARGET_ASM_GLOBALIZE_LABEL default_globalize_label
#endif
+#ifndef TARGET_ASM_GLOBALIZE_DECL_NAME
+#define TARGET_ASM_GLOBALIZE_DECL_NAME default_globalize_decl_name
+#endif
+
#ifndef TARGET_ASM_EMIT_UNWIND_LABEL
#define TARGET_ASM_EMIT_UNWIND_LABEL default_emit_unwind_label
#endif
@@ -253,6 +257,7 @@ Foundation, 51 Franklin Street, Fifth Fl
TARGET_ASM_UNALIGNED_INT_OP, \
TARGET_ASM_INTEGER, \
TARGET_ASM_GLOBALIZE_LABEL, \
+ TARGET_ASM_GLOBALIZE_DECL_NAME, \
TARGET_ASM_EMIT_UNWIND_LABEL, \
TARGET_ASM_EMIT_EXCEPT_TABLE_LABEL, \
TARGET_UNWIND_EMIT, \
Index: output.h
===================================================================
--- output.h (revision 120890)
+++ output.h (working copy)
@@ -612,6 +612,7 @@ extern bool default_use_anchors_for_symb
extern bool default_binds_local_p (tree);
extern bool default_binds_local_p_1 (tree, int);
extern void default_globalize_label (FILE *, const char *);
+extern void default_globalize_decl_name (FILE *, tree);
extern void default_emit_unwind_label (FILE *, tree, int, int);
extern void default_emit_except_table_label (FILE *);
extern void default_internal_label (FILE *, const char *, unsigned long);
Index: varasm.c
===================================================================
--- varasm.c (revision 120890)
+++ varasm.c (working copy)
@@ -4739,11 +4739,11 @@ weak_finish (void)
static void
globalize_decl (tree decl)
{
- const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
if (DECL_WEAK (decl))
{
+ const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
tree *p, t;
#ifdef ASM_WEAKEN_DECL
@@ -4775,12 +4775,9 @@ globalize_decl (tree decl)
return;
}
-#elif defined(ASM_MAKE_LABEL_LINKONCE)
- if (DECL_ONE_ONLY (decl))
- ASM_MAKE_LABEL_LINKONCE (asm_out_file, name);
#endif
- targetm.asm_out.globalize_label (asm_out_file, name);
+ targetm.asm_out.globalize_decl_name (asm_out_file, decl);
}
/* We have to be able to tell cgraph about the needed-ness of the target
@@ -5906,15 +5903,27 @@ default_valid_pointer_mode (enum machine
/* Default function to output code that will globalize a label. A
target must define GLOBAL_ASM_OP or provide its own function to
globalize a label. */
-#ifdef GLOBAL_ASM_OP
void
default_globalize_label (FILE * stream, const char *name)
{
+#ifdef GLOBAL_ASM_OP
fputs (GLOBAL_ASM_OP, stream);
assemble_name (stream, name);
putc ('\n', stream);
-}
#endif /* GLOBAL_ASM_OP */
+}
+
+/* Default function to output code that will globalize a declaration. */
+void
+default_globalize_decl_name (FILE * stream, tree decl)
+{
+ const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+#if defined(ASM_MAKE_LABEL_LINKONCE)
+ if (DECL_ONE_ONLY (decl))
+ ASM_MAKE_LABEL_LINKONCE (asm_out_file, name);
+#endif
+ targetm.asm_out.globalize_label (stream, name);
+}
/* Default function to output a label for unwind information. The
default is to do nothing. A target that needs nonlocal labels for
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c (revision 120890)
+++ config/ia64/ia64.c (working copy)
@@ -242,6 +242,7 @@ static void bundling (FILE *, int, rtx,
static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static void ia64_file_start (void);
+static void ia64_globalize_decl_name (FILE *, tree);
static section *ia64_select_rtx_section (enum machine_mode, rtx,
unsigned HOST_WIDE_INT);
@@ -265,6 +266,7 @@ static void ia64_vms_init_libfuncs (void
ATTRIBUTE_UNUSED;
static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
+static tree ia64_handle_version_id_attribute (tree *, tree, tree, int, bool *);
static void ia64_encode_section_info (tree, rtx, int);
static rtx ia64_struct_value_rtx (tree, int);
static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
@@ -282,6 +284,8 @@ static const struct attribute_spec ia64_
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "syscall_linkage", 0, 0, false, true, true, NULL },
{ "model", 1, 1, true, false, false, ia64_handle_model_attribute },
+ { "version_id", 1, 1, true, false, false,
+ ia64_handle_version_id_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -391,6 +395,9 @@ static const struct attribute_spec ia64_
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START ia64_file_start
+#undef TARGET_ASM_GLOBALIZE_DECL_NAME
+#define TARGET_ASM_GLOBALIZE_DECL_NAME ia64_globalize_decl_name
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS ia64_rtx_costs
#undef TARGET_ADDRESS_COST
@@ -2226,6 +2233,24 @@ emit_safe_across_calls (void)
fputc ('\n', asm_out_file);
}
+/* Globalize a declaration. */
+
+static void
+ia64_globalize_decl_name (FILE * stream, tree decl)
+{
+ const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ tree version_attr = lookup_attribute ("version_id", DECL_ATTRIBUTES (decl));
+ if (version_attr)
+ {
+ tree v = TREE_VALUE (TREE_VALUE (version_attr));
+ const char *p = TREE_STRING_POINTER (v);
+ fprintf (stream, "\t.alias %s#, \"%s{%s}\"\n", name, name, p);
+ }
+ targetm.asm_out.globalize_label (stream, name);
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function");
+}
+
/* Helper function for ia64_compute_frame_size: find an appropriate general
register to spill some special register to. SPECIAL_SPILL_MASK contains
bits in GR0 to GR31 that have already been allocated by this routine.
@@ -9189,10 +9214,7 @@ ia64_asm_output_external (FILE *file, tr
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);
- }
+ (*targetm.asm_out.globalize_decl_name) (file, decl);
else if (need_visibility && !TARGET_GNU_AS)
(*targetm.asm_out.globalize_label) (file, name);
}
@@ -9778,4 +9800,28 @@ ia64_optimization_options (int level ATT
}
+/* HP-UX version_id attribute.
+ For object foo, if the version_id is set to 1234 put out an alias
+ of '.alias unique-name "foo{1234}" We can't use "foo{1234}"
+ in anything other than an alias statement because it is an illegal
+ symbol name. */
+
+static tree
+ia64_handle_version_id_attribute (tree *node ATTRIBUTE_UNUSED,
+ tree name ATTRIBUTE_UNUSED,
+ tree args,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
+{
+ tree arg = TREE_VALUE (args);
+
+ if (TREE_CODE (arg) != STRING_CST)
+ {
+ error("version attribute is not a string");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ return NULL_TREE;
+}
+
#include "gt-ia64.h"
Index: testsuite/gcc.target/ia64/versionid-1.c
===================================================================
--- testsuite/gcc.target/ia64/versionid-1.c (revision 0)
+++ testsuite/gcc.target/ia64/versionid-1.c (revision 0)
@@ -0,0 +1,10 @@
+/* { dg-do compile { target ia64-*-hpux* } } */
+
+extern int foo () __attribute__((version_id ("20040821")));
+
+int bar(int i)
+{
+ return (foo() + 1);
+}
+
+/* { dg-final { scan-assembler "alias.*foo.*foo{20040821}" } } */
Index: testsuite/gcc.target/ia64/versionid-2.c
===================================================================
--- testsuite/gcc.target/ia64/versionid-2.c (revision 0)
+++ testsuite/gcc.target/ia64/versionid-2.c (revision 0)
@@ -0,0 +1,10 @@
+/* { dg-do compile { target ia64-*-hpux* } } */
+
+extern int foo () __attribute__((version_id ("20040821")));
+
+int foo(int i)
+{
+ return (1);
+}
+
+/* { dg-final { scan-assembler "alias.*foo.*foo{20040821}" } } */