diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 41c4187c5d6..842b5ae1ef4 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -109,11 +109,17 @@ extern int check_float_value PARAMS ((enum machine_mode, #ifdef HAVE_MACHINE_MODES extern enum avms_arg_type alpha_arg_type PARAMS ((enum machine_mode)); #endif +#ifdef RTX_CODE extern rtx alpha_arg_info_reg_val PARAMS ((CUMULATIVE_ARGS)); +#endif +#ifdef BUFSIZ extern void alpha_write_linkage PARAMS ((FILE *)); +#endif #endif /* OPEN_VMS */ -extern void alpha_need_linkage PARAMS ((const char *, int)); +#ifdef RTX_CODE +extern rtx alpha_need_linkage PARAMS ((const char *, int)); +#endif #ifdef TREE_CODE extern tree alpha_build_va_list PARAMS ((void)); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index f467c45b2b8..ed708788d7c 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -3722,9 +3722,12 @@ function_arg (cum, mode, type, named) int named ATTRIBUTE_UNUSED; { int basereg; + int num_args; +#ifndef OPEN_VMS if (cum >= 6) return NULL_RTX; + num_args = cum; /* VOID is passed as a special flag for "last argument". */ if (type == void_type_node) @@ -3733,6 +3736,14 @@ function_arg (cum, mode, type, named) return NULL_RTX; else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named)) basereg = 16; +#else + if (mode == VOIDmode) + return alpha_arg_info_reg_val (cum); + + num_args = cum.num_args; + if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type)) + return NULL_RTX; +#endif /* OPEN_VMS */ else if (TARGET_FPREGS && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT || GET_MODE_CLASS (mode) == MODE_FLOAT)) @@ -3740,7 +3751,7 @@ function_arg (cum, mode, type, named) else basereg = 16; - return gen_rtx_REG (mode, cum + basereg); + return gen_rtx_REG (mode, num_args + basereg); } tree @@ -5866,109 +5877,165 @@ alpha_arg_info_reg_val (cum) return GEN_INT (regval); } +#include + /* Structure to collect function names for final output in link section. */ enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; - -struct alpha_links { - struct alpha_links *next; - char *name; +struct alpha_links +{ + rtx linkage; enum links_kind kind; }; -static struct alpha_links *alpha_links_base = 0; +static splay_tree alpha_links; + +static int mark_alpha_links_node PARAMS ((splay_tree_node, void *)); +static void mark_alpha_links PARAMS ((void *)); +static int alpha_write_one_linkage PARAMS ((splay_tree_node, void *)); + +/* Protect alpha_links from garbage collection. */ + +static int +mark_alpha_links_node (node, data) + splay_tree_node node; + void *data ATTRIBUTE_UNUSED; +{ + struct alpha_links *links = (struct alpha_links *) node->value; + ggc_mark_rtx (links->linkage); + return 0; +} + +static void +mark_alpha_links (ptr) + void *ptr; +{ + splay_tree tree = *(splay_tree *) ptr; + splay_tree_foreach (tree, mark_alpha_links_node, NULL); +} /* Make (or fake) .linkage entry for function call. - IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */ + IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. -void + Return an SYMBOL_REF rtx for the linkage. */ + +rtx alpha_need_linkage (name, is_local) const char *name; int is_local; { - rtx x; - struct alpha_links *lptr, *nptr; + splay_tree_node node; + struct alpha_links *al; if (name[0] == '*') name++; - /* Is this name already defined ? */ + if (alpha_links) + { + /* Is this name already defined? */ - for (lptr = alpha_links_base; lptr; lptr = lptr->next) - if (strcmp (lptr->name, name) == 0) - { - if (is_local) - { - /* Defined here but external assumed. */ - if (lptr->kind == KIND_EXTERN) - lptr->kind = KIND_LOCAL; - } - else - { - /* Used here but unused assumed. */ - if (lptr->kind == KIND_UNUSED) - lptr->kind = KIND_LOCAL; - } - return; - } + node = splay_tree_lookup (alpha_links, (splay_tree_key) name); + if (node) + { + al = (struct alpha_links *) node->value; + if (is_local) + { + /* Defined here but external assumed. */ + if (al->kind == KIND_EXTERN) + al->kind = KIND_LOCAL; + } + else + { + /* Used here but unused assumed. */ + if (al->kind == KIND_UNUSED) + al->kind = KIND_LOCAL; + } + return al->linkage; + } + } + else + { + alpha_links = splay_tree_new ((splay_tree_compare_fn) strcmp, + (splay_tree_delete_key_fn) free, + (splay_tree_delete_key_fn) free); + ggc_add_root (&alpha_links, 1, 1, mark_alpha_links); + } - nptr = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); - nptr->next = alpha_links_base; - nptr->name = xstrdup (name); + al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); + name = xstrdup (name); /* Assume external if no definition. */ - nptr->kind = (is_local ? KIND_UNUSED : KIND_EXTERN); + al->kind = (is_local ? KIND_UNUSED : KIND_EXTERN); - /* Ensure we have an IDENTIFIER so assemble_name can mark is used. */ + /* Ensure we have an IDENTIFIER so assemble_name can mark it used. */ get_identifier (name); - alpha_links_base = nptr; + /* Construct a SYMBOL_REF for us to call. */ + { + size_t name_len = strlen (name); + char *linksym = ggc_alloc_string (NULL, name_len + 6); - return; + linksym[0] = '$'; + memcpy (linksym + 1, name, name_len); + memcpy (linksym + 1 + name_len, "..lk", 5); + al->linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); + } + + splay_tree_insert (alpha_links, (splay_tree_key) name, + (splay_tree_value) al); + + return al->linkage; } +static int +alpha_write_one_linkage (node, data) + splay_tree_node node; + void *data; +{ + const char *name = (const char *) node->key; + struct alpha_links *links = (struct alpha_links *) node->value; + FILE *stream = (FILE *) data; + + if (links->kind == KIND_UNUSED + || ! TREE_SYMBOL_REFERENCED (get_identifier (name))) + return 0; + + fprintf (stream, "$%s..lk:\n", name); + if (links->kind == KIND_LOCAL) + { + /* Local and used, build linkage pair. */ + fprintf (stream, "\t.quad %s..en\n", name); + fprintf (stream, "\t.quad %s\n", name); + } + else + { + /* External and used, request linkage pair. */ + fprintf (stream, "\t.linkage %s\n", name); + } + + return 0; +} void alpha_write_linkage (stream) FILE *stream; { - struct alpha_links *lptr, *nptr; - readonly_section (); - fprintf (stream, "\t.align 3\n"); - - for (lptr = alpha_links_base; lptr; lptr = nptr) - { - nptr = lptr->next; - - if (lptr->kind == KIND_UNUSED - || ! TREE_SYMBOL_REFERENCED (get_identifier (lptr->name))) - continue; - - fprintf (stream, "$%s..lk:\n", lptr->name); - if (lptr->kind == KIND_LOCAL) - { - /* Local and used, build linkage pair. */ - fprintf (stream, "\t.quad %s..en\n", lptr->name); - fprintf (stream, "\t.quad %s\n", lptr->name); - } - else - /* External and used, request linkage pair. */ - fprintf (stream, "\t.linkage %s\n", lptr->name); - } + splay_tree_foreach (alpha_links, alpha_write_one_linkage, stream); } #else -void +rtx alpha_need_linkage (name, is_local) const char *name ATTRIBUTE_UNUSED; int is_local ATTRIBUTE_UNUSED; { + return NULL_RTX; } #endif /* OPEN_VMS */ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 520c2e09904..dfef1506b08 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -3914,24 +3914,9 @@ emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]); if (GET_CODE (operands[0]) == SYMBOL_REF) { - extern char *savealloc (); - const char *symbol = XSTR (operands[0], 0); - char *linksym; - rtx linkage; - - if (*symbol == '*') - symbol++; - linksym = savealloc (strlen (symbol) + 6); - - alpha_need_linkage (symbol, 0); - - linksym[0] = '$'; - strcpy (linksym+1, symbol); - strcat (linksym, \"..lk\"); - linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); + rtx linkage = alpha_need_linkage (XSTR (operands[0], 0), 0); emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); - operands[2] = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); } @@ -3939,7 +3924,6 @@ { emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, plus_constant (operands[0], 8))); - operands[2] = operands[0]; } @@ -4035,23 +4019,9 @@ emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]); if (GET_CODE (operands[1]) == SYMBOL_REF) { - extern char *savealloc (); - const char *symbol = XSTR (operands[1], 0); - char *linksym; - rtx linkage; - - if (*symbol == '*') - symbol++; - linksym = savealloc (strlen (symbol) + 6); - - alpha_need_linkage (symbol, 0); - linksym[0] = '$'; - strcpy (linksym+1, symbol); - strcat (linksym, \"..lk\"); - linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); + rtx linkage = alpha_need_linkage (XSTR (operands[1], 0), 0); emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); - operands[3] = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); } @@ -4059,7 +4029,6 @@ { emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, plus_constant (operands[1], 8))); - operands[3] = operands[1]; } }") diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h index f67deca5c27..296359796f4 100644 --- a/gcc/config/alpha/elf.h +++ b/gcc/config/alpha/elf.h @@ -66,8 +66,6 @@ do { \ } \ } while (0) -extern void output_file_directive (); - /* Attach a special .ident directive to the end of the file to identify the version of GCC which compiled this code. The format of the .ident string is patterned after the ones produced by native svr4 @@ -265,6 +263,11 @@ do { \ SECTION_FUNCTION_TEMPLATE(sbss_section, in_sbss, SBSS_SECTION_ASM_OP) \ SECTION_FUNCTION_TEMPLATE(sdata_section, in_sdata, SDATA_SECTION_ASM_OP) +extern void ctors_section PARAMS ((void)); +extern void dtors_section PARAMS ((void)); +extern void sbss_section PARAMS ((void)); +extern void sdata_section PARAMS ((void)); + #undef READONLY_DATA_SECTION #define READONLY_DATA_SECTION() const_section () @@ -282,7 +285,6 @@ const_section () \ } #define SECTION_FUNCTION_TEMPLATE(FN, ENUM, OP) \ -void FN PARAMS ((void)); \ void FN () \ { \ if (in_section != ENUM) \ diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h index b40a3914e26..923cb2bd48a 100644 --- a/gcc/config/alpha/vms.h +++ b/gcc/config/alpha/vms.h @@ -155,41 +155,6 @@ typedef struct {int num_args; enum avms_arg_type atypes[6];} avms_arg_info; (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64; \ (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64; -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -extern enum avms_arg_type alpha_arg_type (); - -/* Determine where to put an argument to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode (or VOIDmode for no more args). - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). - - On Alpha the first 6 words of args are normally in registers - and the rest are pushed. */ - -extern struct rtx_def *alpha_arg_info_reg_val (); -#undef FUNCTION_ARG -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -((MODE) == VOIDmode ? alpha_arg_info_reg_val (CUM) \ - : ((CUM.num_args) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE) \ - ? gen_rtx_REG ((MODE), \ - ((CUM).num_args + 16 \ - + ((TARGET_FPREGS \ - && (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ - || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \ - * 32))) \ - : 0)) - #undef FUNCTION_ARG_ADVANCE #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ if (MUST_PASS_IN_STACK (MODE, TYPE)) \ @@ -333,6 +298,12 @@ dtors_section () \ } \ } +extern void readonly_section PARAMS ((void)); +extern void link_section PARAMS ((void)); +extern void literals_section PARAMS ((void)); +extern void ctors_section PARAMS ((void)); +extern void dtors_section PARAMS ((void)); + #undef ASM_OUTPUT_ADDR_DIFF_ELT #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) abort () @@ -419,7 +390,6 @@ do { \ #define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, NAME, ARGS) \ (vms_valid_decl_attribute_p (DECL, ATTRIBUTES, NAME, ARGS)) -extern int vms_valid_decl_attribute_p (); #undef SDB_DEBUGGING_INFO #undef MIPS_DEBUGGING_INFO