From 4b8af8d9841c37c89a7eae9d4f831ce4cc00801f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sun, 16 Apr 1995 06:14:00 +0000 Subject: [PATCH] attributes weak and alias From-SVN: r9391 --- gcc/c-common.c | 27 ++++++++++- gcc/config/aoutos.h | 15 +++++++ gcc/config/sparc/sunos4.h | 15 +++++++ gcc/toplev.c | 4 ++ gcc/varasm.c | 94 ++++++++++++++++++++++++++++++++------- 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 */ -#endif /* WEAK_ASM_OP && ASM_OUTPUT_DEF */ +/* 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); + + 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 +}