This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Weak functions on powerpc64-linux
On Tue, Feb 26, 2002 at 03:57:56PM -0800, Richard Henderson wrote:
> On Tue, Feb 26, 2002 at 09:51:21PM +1030, Alan Modra wrote:
> > struct weak_syms
> > {
> > struct weak_syms * next;
> > + const tree decl;
>
> Generally ok, but you're going to need to mark this for
> garbage collection.
Thanks for the tip. Here's a revised diff, which also takes note of
David's suggestion regarding moving ASM_WEAKEN_DECL to rs6000.h.
* doc/tm.texi (ASM_WEAKEN_DECL): Document.
(ASM_WEAKEN_LABEL): Mention ASM_WEAKEN_DECL.
(SUPPORTS_WEAK): Likewise.
* output.h (add_weak): Add tree param.
* varasm.c (add_weak): Likewise. Save decl.
(struct weak_syms): Add decl field.
(mark_weak_decls): New function.
(init_varasm_once): ggc_add_root mark_weak_decls.
(assemble_start_function): Use ASM_WEAKEN_DECL.
(assemble_variable): Likewise.
(assemble_alias): Likewise.
(declare_weak): Pass decl to add_weak.
(weak_finish): Use ASM_WEAKEN_DECL. Try to find decl.
(remove_from_pending_weak_list): Declare and define for
ASM_WEAKEN_DECL.
* c-pragma.c (handle_pragma_weak): Adjust add_weak call.
* c-pragma.h (HANDLE_PRAGMA_WEAK): Define if ASM_WEAKEN_DECL too.
* defaults.h (SUPPORTS_WEAK): Likewise.
* config/rs6000/linux64.h (ASM_DECLARE_FUNCTION_NAME): Don't emit
.weak for code sym. Do emit .size for descriptor sym.
(ASM_DECLARE_FUNCTION_SIZE): Define.
(ASM_OUTPUT_DEF_FROM_DECLS): Define.
* config/rs6000/rs6000.h (ASM_WEAKEN_DECL): Define.
(ASM_OUTPUT_DEF_FROM_DECLS): Constify name. Don't emit .weak here.
Tested on powerpc64-linux. powerpc-linux bootstrap in progress.
--
Alan Modra
IBM OzLabs - Linux Technology Centre
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/doc/tm.texi gcc-ppc64-31/gcc/doc/tm.texi
--- gcc-ppc64-31.orig/gcc/doc/tm.texi Mon Feb 18 15:29:55 2002
+++ gcc-ppc64-31/gcc/doc/tm.texi Thu Feb 28 00:19:05 2002
@@ -6174,7 +6174,7 @@ itself; before and after that, output th
for making that name global, and a newline.
@findex ASM_WEAKEN_LABEL
-@item ASM_WEAKEN_LABEL
+@item ASM_WEAKEN_LABEL (@var{stream}, @var{name})
A C statement (sans semicolon) to output to the stdio stream
@var{stream} some commands that will make the label @var{name} weak;
that is, available for reference from other files but only used if
@@ -6183,18 +6183,29 @@ no other definition is available. Use t
itself; before and after that, output the additional assembler syntax
for making that name weak, and a newline.
-If you don't define this macro, GCC will not support weak
-symbols and you should not define the @code{SUPPORTS_WEAK} macro.
+If you don't define this macro or @code{ASM_WEAKEN_DECL}, GCC will not
+support weak symbols and you should not define the @code{SUPPORTS_WEAK}
+macro.
+
+@findex ASM_WEAKEN_DECL
+@item ASM_WEAKEN_DECL (@var{stream}, @var{decl}, @var{name}, @var{value})
+Combines (and replaces) the function of @code{ASM_WEAKEN_LABEL} and
+@code{ASM_OUTPUT_WEAK_ALIAS}, allowing access to the associated function
+or variable decl. If @var{value} is not @code{NULL}, this C statement
+should output to the stdio stream @var{stream} assembler code which
+defines (equates) the weak symbol @var{name} to have the value
+@var{value}. If @var{value} is @code{NULL}, it should output commands
+to make @var{name} weak.
@findex SUPPORTS_WEAK
@item SUPPORTS_WEAK
A C expression which evaluates to true if the target supports weak symbols.
If you don't define this macro, @file{defaults.h} provides a default
-definition. If @code{ASM_WEAKEN_LABEL} is defined, the default
-definition is @samp{1}; otherwise, it is @samp{0}. Define this macro if
-you want to control weak symbol support with a compiler flag such as
-@option{-melf}.
+definition. If either @code{ASM_WEAKEN_LABEL} or @code{ASM_WEAKEN_DECL}
+is defined, the default definition is @samp{1}; otherwise, it is
+@samp{0}. Define this macro if you want to control weak symbol support
+with a compiler flag such as @option{-melf}.
@findex MAKE_DECL_ONE_ONLY (@var{decl})
@item MAKE_DECL_ONE_ONLY
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/c-pragma.c gcc-ppc64-31/gcc/c-pragma.c
--- gcc-ppc64-31.orig/gcc/c-pragma.c Thu Nov 15 22:39:42 2001
+++ gcc-ppc64-31/gcc/c-pragma.c Tue Feb 26 18:44:39 2002
@@ -298,7 +298,8 @@ handle_pragma_weak (dummy)
if (t != CPP_EOF)
warning ("junk at end of #pragma weak");
- add_weak (IDENTIFIER_POINTER (name), value ? IDENTIFIER_POINTER (value) : 0);
+ add_weak (NULL_TREE, IDENTIFIER_POINTER (name),
+ value ? IDENTIFIER_POINTER (value) : NULL);
}
#endif
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/c-pragma.h gcc-ppc64-31/gcc/c-pragma.h
--- gcc-ppc64-31.orig/gcc/c-pragma.h Sun Jan 20 00:11:57 2002
+++ gcc-ppc64-31/gcc/c-pragma.h Thu Feb 28 00:19:11 2002
@@ -23,9 +23,8 @@ Software Foundation, 59 Temple Place - S
#define GCC_C_PRAGMA_H
#ifdef HANDLE_SYSV_PRAGMA
-/* Support #pragma weak iff ASM_WEAKEN_LABEL and ASM_OUTPUT_WEAK_ALIAS are
- defined. */
-#if defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_WEAK_ALIAS)
+#if ((defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_WEAK_ALIAS)) \
+ || defined (ASM_WEAKEN_DECL))
#define HANDLE_PRAGMA_WEAK SUPPORTS_WEAK
#endif
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/defaults.h gcc-ppc64-31/gcc/defaults.h
--- gcc-ppc64-31.orig/gcc/defaults.h Tue Dec 18 11:27:10 2001
+++ gcc-ppc64-31/gcc/defaults.h Thu Feb 28 00:19:10 2002
@@ -158,7 +158,7 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNA
/* This determines whether or not we support weak symbols. */
#ifndef SUPPORTS_WEAK
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
#define SUPPORTS_WEAK 1
#else
#define SUPPORTS_WEAK 0
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/output.h gcc-ppc64-31/gcc/output.h
--- gcc-ppc64-31.orig/gcc/output.h Mon Feb 18 15:28:24 2002
+++ gcc-ppc64-31/gcc/output.h Wed Feb 27 21:43:29 2002
@@ -137,7 +137,7 @@ extern const char *get_insn_template PAR
/* Add function NAME to the weak symbols list. VALUE is a weak alias
associated with NAME. */
-extern int add_weak PARAMS ((const char *, const char *));
+extern int add_weak PARAMS ((tree, const char *, const char *));
/* Functions in flow.c */
extern void allocate_for_life_analysis PARAMS ((void));
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/varasm.c gcc-ppc64-31/gcc/varasm.c
--- gcc-ppc64-31.orig/gcc/varasm.c Thu Feb 21 10:49:53 2002
+++ gcc-ppc64-31/gcc/varasm.c Thu Feb 28 00:19:08 2002
@@ -42,6 +42,7 @@ Software Foundation, 59 Temple Place - S
#include "obstack.h"
#include "hashtab.h"
#include "c-pragma.h"
+#include "c-tree.h"
#include "ggc.h"
#include "langhooks.h"
#include "tm_p.h"
@@ -166,7 +167,8 @@ static unsigned HOST_WIDE_INT array_size
static unsigned min_align PARAMS ((unsigned, unsigned));
static void output_constructor PARAMS ((tree, HOST_WIDE_INT,
unsigned int));
-#ifdef ASM_WEAKEN_LABEL
+static void mark_weak_decls PARAMS ((void *));
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
static void remove_from_pending_weak_list PARAMS ((const char *));
#endif
static int in_named_entry_eq PARAMS ((const PTR, const PTR));
@@ -1237,10 +1239,14 @@ assemble_start_function (decl, fnname)
weak_global_object_name = name;
}
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
if (DECL_WEAK (decl))
{
+#ifdef ASM_WEAKEN_DECL
+ ASM_WEAKEN_DECL (asm_out_file, decl, fnname, 0);
+#else
ASM_WEAKEN_LABEL (asm_out_file, fnname);
+#endif
/* Remove this function from the pending weak list so that
we do not emit multiple .weak directives for it. */
remove_from_pending_weak_list
@@ -1644,10 +1650,14 @@ assemble_variable (decl, top_level, at_e
/* First make the assembler name(s) global if appropriate. */
if (TREE_PUBLIC (decl) && DECL_NAME (decl))
{
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
if (DECL_WEAK (decl))
{
+#ifdef ASM_WEAKEN_DECL
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
+#else
ASM_WEAKEN_LABEL (asm_out_file, name);
+#endif
/* Remove this variable from the pending weak list so that
we do not emit multiple .weak directives for it. */
remove_from_pending_weak_list
@@ -5012,17 +5022,41 @@ output_constructor (exp, size, align)
struct weak_syms
{
struct weak_syms * next;
+ tree decl;
const char * name;
const char * value;
};
static struct weak_syms * weak_decls;
+/* Mark weak_decls for garbage collection. */
+
+static void
+mark_weak_decls (arg)
+ void *arg;
+{
+ struct weak_syms *t;
+
+ for (t = *(struct weak_syms **) arg; t != NULL; t = t->next)
+ {
+ tree decl = t->decl;
+ if (decl == NULL_TREE)
+ {
+ tree name = get_identifier (t->name);
+ if (name)
+ decl = lookup_name (name);
+ t->decl = decl;
+ }
+ ggc_mark_tree (decl);
+ }
+}
+
/* Add function NAME to the weak symbols list. VALUE is a weak alias
associated with NAME. */
int
-add_weak (name, value)
+add_weak (decl, name, value)
+ tree decl;
const char *name;
const char *value;
{
@@ -5034,6 +5068,7 @@ add_weak (name, value)
return 0;
weak->next = weak_decls;
+ weak->decl = decl;
weak->name = name;
weak->value = value;
weak_decls = weak;
@@ -5052,7 +5087,7 @@ declare_weak (decl)
else if (TREE_ASM_WRITTEN (decl))
error_with_decl (decl, "weak declaration of `%s' must precede definition");
else if (SUPPORTS_WEAK)
- add_weak (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), NULL);
+ add_weak (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), NULL);
else
warning_with_decl (decl, "weak declaration of `%s' not supported");
@@ -5067,8 +5102,18 @@ weak_finish ()
if (SUPPORTS_WEAK)
{
struct weak_syms *t;
- for (t = weak_decls; t; t = t->next)
+ for (t = weak_decls; t != NULL; t = t->next)
{
+#ifdef ASM_WEAKEN_DECL
+ tree decl = t->decl;
+ if (decl == NULL_TREE)
+ {
+ tree name = get_identifier (t->name);
+ if (name)
+ decl = lookup_name (name);
+ }
+ ASM_WEAKEN_DECL (asm_out_file, decl, t->name, t->value);
+#else
#ifdef ASM_OUTPUT_WEAK_ALIAS
ASM_OUTPUT_WEAK_ALIAS (asm_out_file, t->name, t->value);
#else
@@ -5078,6 +5123,7 @@ weak_finish ()
ASM_WEAKEN_LABEL (asm_out_file, t->name);
#endif
#endif
+#endif
}
}
}
@@ -5085,7 +5131,7 @@ weak_finish ()
/* Remove NAME from the pending list of weak symbols. This prevents
the compiler from emitting multiple .weak directives which confuses
some assemblers. */
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
static void
remove_from_pending_weak_list (name)
const char *name;
@@ -5105,7 +5151,7 @@ remove_from_pending_weak_list (name)
p = &(t->next);
}
}
-#endif /* ASM_WEAKEN_LABEL */
+#endif /* defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL) */
/* Emit an assembler directive to make the symbol for DECL an alias to
the symbol for TARGET. */
@@ -5127,10 +5173,14 @@ assemble_alias (decl, target)
if (TREE_PUBLIC (decl))
{
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
if (DECL_WEAK (decl))
- {
+ {
+#ifdef ASM_WEAKEN_DECL
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
+#else
ASM_WEAKEN_LABEL (asm_out_file, name);
+#endif
/* Remove this function from the pending weak list so that
we do not emit multiple .weak directives for it. */
remove_from_pending_weak_list
@@ -5147,12 +5197,16 @@ assemble_alias (decl, target)
ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target));
#endif
TREE_ASM_WRITTEN (decl) = 1;
-#else
-#ifdef ASM_OUTPUT_WEAK_ALIAS
+#else /* !ASM_OUTPUT_DEF */
+#if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
if (! DECL_WEAK (decl))
warning ("only weak aliases are supported in this configuration");
+#ifdef ASM_WEAKEN_DECL
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
+#else
ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
+#endif
TREE_ASM_WRITTEN (decl) = 1;
#else
warning ("alias definitions not supported in this configuration; ignored");
@@ -5213,6 +5267,7 @@ init_varasm_once ()
mark_const_hash_entry);
ggc_add_root (&const_str_htab, 1, sizeof const_str_htab,
mark_const_str_htab);
+ ggc_add_root (&weak_decls, 1, sizeof weak_decls, mark_weak_decls);
const_alias_set = new_alias_set ();
}
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/config/rs6000/linux64.h gcc-ppc64-31/gcc/config/rs6000/linux64.h
--- gcc-ppc64-31.orig/gcc/config/rs6000/linux64.h Thu Feb 21 00:05:15 2002
+++ gcc-ppc64-31/gcc/config/rs6000/linux64.h Thu Feb 28 01:07:39 2002
@@ -250,31 +250,73 @@ do { \
fputs (DOUBLE_INT_ASM_OP, (FILE)); \
putc ('.', (FILE)); \
assemble_name ((FILE), (NAME)); \
- putc ('\n', (FILE)); \
- fputs (DOUBLE_INT_ASM_OP, (FILE)); \
- fputs (".TOC.@tocbase, 0\n\t.previous\n", (FILE)); \
- \
- if (TREE_PUBLIC (DECL)) \
+ fputs (",.TOC.@tocbase,0\n\t.previous\n\t.size\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputs (",24\n\t.type\t.", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputs (",@function\n", (FILE)); \
+ if (TREE_PUBLIC (DECL) && ! DECL_WEAK (DECL)) \
{ \
- if (DECL_WEAK (DECL)) \
- fputs ("\t.weak\t", (FILE)); \
- else \
- fputs ("\t.globl\t", (FILE)); \
- putc ('.', (FILE)); \
+ fputs ("\t.globl\t.", (FILE)); \
assemble_name ((FILE), (NAME)); \
putc ('\n', (FILE)); \
} \
- fputs (TYPE_ASM_OP, (FILE)); \
- putc ('.', (FILE)); \
- assemble_name ((FILE), (NAME)); \
- putc (',', (FILE)); \
- fprintf ((FILE), TYPE_OPERAND_FMT, "function"); \
- putc ('\n', (FILE)); \
ASM_DECLARE_RESULT ((FILE), DECL_RESULT (DECL)); \
putc ('.', (FILE)); \
ASM_OUTPUT_LABEL ((FILE), (NAME)); \
} \
while (0)
+
+/* This is how to declare the size of a function. */
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ { \
+ char label[256]; \
+ static int labelno; \
+ \
+ labelno++; \
+ \
+ ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
+ ASM_OUTPUT_INTERNAL_LABEL ((FILE), "Lfe", labelno); \
+ \
+ fputs ("\t.size\t.", (FILE)); \
+ assemble_name ((FILE), (FNAME)); \
+ putc (',', (FILE)); \
+ assemble_name ((FILE), label); \
+ fputs ("-.", (FILE)); \
+ assemble_name ((FILE), (FNAME)); \
+ putc ('\n', (FILE)); \
+ } \
+ } \
+ while (0)
+
+/* This implements the `alias' attribute. */
+#undef ASM_OUTPUT_DEF_FROM_DECLS
+#define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL, TARGET) \
+ do \
+ { \
+ const char *alias = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ const char *name = IDENTIFIER_POINTER (TARGET); \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ { \
+ if (TREE_PUBLIC (DECL) && ! DECL_WEAK (DECL)) \
+ { \
+ fputs ("\t.globl\t.", (FILE)); \
+ assemble_name ((FILE), alias); \
+ putc ('\n', (FILE)); \
+ } \
+ fputs ("\t.set\t.", (FILE)); \
+ assemble_name ((FILE), alias); \
+ fputs (",.", (FILE)); \
+ assemble_name ((FILE), name); \
+ fputc ('\n', (FILE)); \
+ } \
+ ASM_OUTPUT_DEF ((FILE), alias, name); \
+ } \
+ while (0)
/* Return non-zero if this entry is to be written into the constant
pool in a special way. We do so if this is a SYMBOL_REF, LABEL_REF
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/config/rs6000/rs6000.h gcc-ppc64-31/gcc/config/rs6000/rs6000.h
--- gcc-ppc64-31.orig/gcc/config/rs6000/rs6000.h Thu Feb 21 18:45:18 2002
+++ gcc-ppc64-31/gcc/config/rs6000/rs6000.h Thu Feb 28 01:07:42 2002
@@ -2422,23 +2425,48 @@ extern int toc_initialized;
#define RS6000_WEAK 0
#endif
-/* This implementes the `alias' attribute. */
+#if RS6000_WEAK
+/* Used in lieu of ASM_WEAKEN_LABEL. */
+#define ASM_WEAKEN_DECL(FILE, DECL, NAME, VAL) \
+ do \
+ { \
+ fputs ("\t.weak\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \
+ && DEFAULT_ABI == ABI_AIX) \
+ { \
+ fputs (",.", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ } \
+ fputc ('\n', (FILE)); \
+ if (VAL) \
+ { \
+ ASM_OUTPUT_DEF ((FILE), (NAME), (VAL)); \
+ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \
+ && DEFAULT_ABI == ABI_AIX) \
+ { \
+ fputs ("\t.set\t.", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputs (",.", (FILE)); \
+ assemble_name ((FILE), (VAL)); \
+ fputc ('\n', (FILE)); \
+ } \
+ } \
+ } \
+ while (0)
+#endif
+
+/* This implements the `alias' attribute. */
#define ASM_OUTPUT_DEF_FROM_DECLS(FILE,decl,target) \
do { \
const char * alias = XSTR (XEXP (DECL_RTL (decl), 0), 0); \
- char * name = IDENTIFIER_POINTER (target); \
+ const char * name = IDENTIFIER_POINTER (target); \
if (TREE_CODE (decl) == FUNCTION_DECL \
&& DEFAULT_ABI == ABI_AIX) \
{ \
if (TREE_PUBLIC (decl)) \
{ \
- if (RS6000_WEAK && DECL_WEAK (decl)) \
- { \
- fputs ("\t.weak .", FILE); \
- assemble_name (FILE, alias); \
- putc ('\n', FILE); \
- } \
- else \
+ if (!RS6000_WEAK || !DECL_WEAK (decl)) \
{ \
fputs ("\t.globl .", FILE); \
assemble_name (FILE, alias); \