aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c94
1 files changed, 78 insertions, 16 deletions
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
+}