aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-common.c27
-rw-r--r--gcc/config/aoutos.h15
-rw-r--r--gcc/config/sparc/sunos4.h15
-rw-r--r--gcc/toplev.c4
-rw-r--r--gcc/varasm.c94
5 files changed, 138 insertions, 17 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 1c1a5da57e3..18d6265b710 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -30,7 +30,7 @@ extern struct obstack permanent_obstack;
enum attrs {A_PACKED, A_NOCOMMON, A_NORETURN, A_CONST, A_T_UNION,
A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
- A_FORMAT};
+ A_FORMAT, A_WEAK, A_ALIAS};
static void declare_hidden_char_array PROTO((char *, char *));
static void add_attribute PROTO((enum attrs, char *,
@@ -258,6 +258,8 @@ init_attributes ()
add_attribute (A_SECTION, "section", 1, 1, 1);
add_attribute (A_ALIGNED, "aligned", 0, 1, 0);
add_attribute (A_FORMAT, "format", 3, 3, 1);
+ add_attribute (A_WEAK, "weak", 0, 0, 1);
+ add_attribute (A_ALIAS, "alias", 1, 1, 1);
}
/* Process the attributes listed in ATTRIBUTES and PREFIX_ATTRIBUTES
@@ -606,6 +608,29 @@ decl_attributes (node, attributes, prefix_attributes)
is_scan, format_num, first_arg_num);
break;
}
+
+ case A_WEAK:
+ declare_weak (decl);
+ break;
+
+ case A_ALIAS:
+ if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+ || TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))
+ error_with_decl (decl,
+ "`%s' defined both normally and as an alias");
+ else if (decl_function_context (decl) == 0)
+ {
+ tree id = get_identifier (TREE_STRING_POINTER
+ (TREE_VALUE (args)));
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ DECL_INITIAL (decl) = error_mark_node;
+ else
+ DECL_EXTERNAL (decl) = 0;
+ assemble_alias (decl, id);
+ }
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
}
}
}
diff --git a/gcc/config/aoutos.h b/gcc/config/aoutos.h
index b398965e7ad..f7bfc905982 100644
--- a/gcc/config/aoutos.h
+++ b/gcc/config/aoutos.h
@@ -85,3 +85,18 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
fputc ('\n', FILE); \
} \
} while (0)
+
+/* If we're using GNU as and ld, we support weak symbols. */
+
+#define HANDLE_PRAGMA_WEAK flag_gnu_linker
+#define WEAK_ASM_OP ".weak"
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+ do { if (flag_gnu_linker) \
+ { \
+ fprintf ((FILE), "\t%s\t", ".set"); \
+ assemble_name (FILE, LABEL1); \
+ fprintf (FILE, ","); \
+ assemble_name (FILE, LABEL2); \
+ fprintf (FILE, "\n"); \
+ } \
+ } while (0)
diff --git a/gcc/config/sparc/sunos4.h b/gcc/config/sparc/sunos4.h
index c7bcaad12c4..fd108e85db8 100644
--- a/gcc/config/sparc/sunos4.h
+++ b/gcc/config/sparc/sunos4.h
@@ -20,3 +20,18 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define SUNOS4_SHARED_LIBRARIES 1
#include "sparc/sparc.h"
+
+/* If we're using GNU as and ld, we support weak symbols. */
+
+#define HANDLE_PRAGMA_WEAK flag_gnu_linker
+#define WEAK_ASM_OP ".weak"
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+ do { if (flag_gnu_linker) \
+ { \
+ fprintf ((FILE), "\t%s\t", ".set"); \
+ assemble_name (FILE, LABEL1); \
+ fprintf (FILE, ","); \
+ assemble_name (FILE, LABEL2); \
+ fprintf (FILE, "\n"); \
+ } \
+ } while (0)
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 988e2c670e4..b6afc47f30c 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2574,6 +2574,10 @@ compile_file (name)
}
}
+ /* Write out any pending weak symbol declarations. */
+
+ weak_finish ();
+
/* Do dbx symbols */
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index a54c5dfdf4c..c4249a9c5d2 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -97,8 +97,13 @@ int size_directive_output;
tree last_assemble_variable_decl;
/* Nonzero if at least one function definition has been seen. */
+
static int function_defined;
+/* Any weak symbol declarations waiting to be emitted. */
+
+static tree weak_decls;
+
struct addr_const;
struct constant_descriptor;
struct rtx_const;
@@ -3911,12 +3916,13 @@ output_constructor (exp, size)
assemble_zeros (size - total_bytes);
}
-
-#ifdef HANDLE_SYSV_PRAGMA
-
/* Support #pragma weak by default if WEAK_ASM_OP and ASM_OUTPUT_DEF
are defined. */
-#if defined (WEAK_ASM_OP) && defined (ASM_OUTPUT_DEF)
+#if !defined (HANDLE_PRAGMA_WEAK) && defined (WEAK_ASM_OP) && defined (ASM_OUTPUT_DEF)
+#define HANDLE_PRAGMA_WEAK 1
+#endif
+
+#if defined (HANDLE_SYSV_PRAGMA) && defined (HANDLE_PRAGMA_WEAK)
/* See c-pragma.c for an identical definition. */
enum pragma_state
@@ -3943,21 +3949,77 @@ handle_pragma_weak (what, asm_out_file, name, value)
{
if (what == ps_name || what == ps_value)
{
- fprintf (asm_out_file, "\t%s\t", WEAK_ASM_OP);
-
- if (output_bytecode)
- BC_OUTPUT_LABELREF (asm_out_file, name);
- else
- ASM_OUTPUT_LABELREF (asm_out_file, name);
-
- fputc ('\n', asm_out_file);
- if (what == ps_value)
- ASM_OUTPUT_DEF (asm_out_file, name, value);
+ weak_decls = perm_tree_cons (what == ps_value ? value : NULL_TREE,
+ name, weak_decls);
}
else if (! (what == ps_done || what == ps_start))
warning ("malformed `#pragma weak'");
}
-#endif /* HANDLE_PRAGMA_WEAK or (WEAK_ASM_OP and SET_ASM_OP) */
+#endif /* HANDLE_SYSV_PRAGMA && HANDLE_PRAGMA_WEAK */
+
+/* Declare DECL to be a weak symbol. */
+
+void
+declare_weak (decl)
+ tree decl;
+{
+ if (! TREE_PUBLIC (decl))
+ error_with_decl (decl, "weak declaration of `%s' must be public");
+ else
+ weak_decls = perm_tree_cons (NULL_TREE, DECL_ASSEMBLER_NAME (decl),
+ weak_decls);
+}
+
+/* Emit any pending weak declarations. */
+
+void
+weak_finish ()
+{
+#ifdef HANDLE_PRAGMA_WEAK
+ if (HANDLE_PRAGMA_WEAK)
+ {
+ tree t;
+ for (t = weak_decls; t; t = TREE_CHAIN (t))
+ {
+ tree decl = TREE_VALUE (t);
+ char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
-#endif /* WEAK_ASM_OP && ASM_OUTPUT_DEF */
+ fprintf (asm_out_file, "\t%s\t", WEAK_ASM_OP);
+
+ if (output_bytecode)
+ BC_OUTPUT_LABELREF (asm_out_file, name);
+ else
+ ASM_OUTPUT_LABELREF (asm_out_file, name);
+
+ fputc ('\n', asm_out_file);
+ }
+ }
+#endif
+}
+
+void
+assemble_alias (decl, target)
+ tree decl, target;
+{
+#ifdef ASM_OUTPUT_DEF
+ char *name;
+
+ make_decl_rtl (decl, (char*)0, 1);
+ name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+
+ /* Make name accessible from other files, if appropriate. */
+
+ if (TREE_PUBLIC (decl))
+ {
+ if (output_bytecode)
+ BC_GLOBALIZE_LABEL (asm_out_file, name);
+ else
+ ASM_GLOBALIZE_LABEL (asm_out_file, name);
+ }
+
+ ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target));
+#else
+ warning ("alias definitions not supported in this configuration");
+#endif
+}