diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 709fbf54363..ab35fcff585 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2002-08-14 Douglas B Rupp + + * config/alpha/alpha-protos.h: Update. + + * config/alpha/alpha.c: (LINKAGE_SYMBOL_REF_P): New macro. + (alpha_legitimate_address_p): Test LINKAGE_SYMBOL_REF_P. + (alpha_linkage_symbol_p): New static function. + (print_operand_address): Print linkage operand. + + (alpha_funcs_num, alpha_funcs_tree, alpha_links_tree): New static + variables. + (reloc_kind): New enum. + (struct alpha_funcs): New struct. + (struct alpha_links): Add reloc_kind field. Rename links_kind field. + + (alpha_need_linkage): Rewrite. + (alpha_use_linkage): New global function. + (alpha_write_linkage): Rewrite and make static. + (alpha_write_one_linkage): Rewrite + + (alpha_start_function): Remove procedure descriptor output. + (alpha_end_function): Write linkages at end of each function. + + * config/alpha/alpha.md (call_vms, call_value_vms): Rewrite. + (call_vms_1, call_value_vms_1): Rewrite. + + * config/alpha/vms.h (ASM_FILE_END): Remove. + 2002-08-14 Richard Henderson * ggc-page.c (RTL_SIZE): New. diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index a2cfc924b2a..e52e4f461bc 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -159,13 +159,13 @@ extern void alpha_emit_xfloating_cvt PARAMS ((enum rtx_code, rtx[])); #endif extern rtx alpha_need_linkage PARAMS ((const char *, int)); +extern rtx alpha_use_linkage PARAMS ((rtx, tree, int, int)); #if TARGET_ABI_OPEN_VMS #ifdef HAVE_MACHINE_MODES extern enum avms_arg_type alpha_arg_type PARAMS ((enum machine_mode)); #endif extern rtx alpha_arg_info_reg_val PARAMS ((CUMULATIVE_ARGS)); -extern void alpha_write_linkage PARAMS ((FILE *)); #endif /* TARGET_ABI_OPEN_VMS */ extern rtx unicosmk_add_call_info_word PARAMS ((rtx)); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 99dee6bae6b..7fa6ba03337 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -188,6 +188,13 @@ static void alpha_elf_select_rtx_section PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT)); #endif +#if TARGET_ABI_OPEN_VMS +static bool alpha_linkage_symbol_p + PARAMS ((const char *symname)); +static void alpha_write_linkage + PARAMS ((FILE *, const char *, tree)); +#endif + static struct machine_function * alpha_init_machine_status PARAMS ((void)); @@ -1938,6 +1945,28 @@ alpha_strip_name_encoding (str) return str; } +#if TARGET_ABI_OPEN_VMS +static bool +alpha_linkage_symbol_p (symname) + const char *symname; +{ + int symlen = strlen (symname); + + if (symlen > 4) + return strcmp (&symname [symlen - 4], "..lk") == 0; + + return false; +} + +#define LINKAGE_SYMBOL_REF_P(X) \ + ((GET_CODE (X) == SYMBOL_REF \ + && alpha_linkage_symbol_p (XSTR (X, 0))) \ + || (GET_CODE (X) == CONST \ + && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ + && alpha_linkage_symbol_p (XSTR (XEXP (XEXP (X, 0), 0), 0)))) +#endif + /* legitimate_address_p recognizes an RTL expression that is a valid memory address for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. @@ -1977,6 +2006,11 @@ alpha_legitimate_address_p (mode, x, strict) if (CONSTANT_ADDRESS_P (x)) return true; +#if TARGET_ABI_OPEN_VMS + if (LINKAGE_SYMBOL_REF_P (x)) + return true; +#endif + /* Register plus a small constant offset is valid. */ if (GET_CODE (x) == PLUS) { @@ -5929,6 +5963,24 @@ print_operand_address (file, addr) basereg = subreg_regno (addr); else if (GET_CODE (addr) == CONST_INT) offset = INTVAL (addr); + +#if TARGET_ABI_OPEN_VMS + else if (GET_CODE (addr) == SYMBOL_REF) + { + fprintf (file, "%s", XSTR (addr, 0)); + return; + } + else if (GET_CODE (addr) == CONST + && GET_CODE (XEXP (addr, 0)) == PLUS + && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF) + { + fprintf (file, "%s+%d", + XSTR (XEXP (XEXP (addr, 0), 0), 0), + INTVAL (XEXP (XEXP (addr, 0), 1))); + return; + } +#endif + else abort (); @@ -7432,18 +7484,6 @@ alpha_start_function (file, fnname, decl) fputs ("\t.ascii \"", file); assemble_name (file, fnname); fputs ("\\0\"\n", file); - - link_section (); - fprintf (file, "\t.align 3\n"); - fputs ("\t.name ", file); - assemble_name (file, fnname); - fputs ("..na\n", file); - ASM_OUTPUT_LABEL (file, fnname); - fprintf (file, "\t.pdesc "); - assemble_name (file, fnname); - fprintf (file, "..en,%s\n", - alpha_procedure_type == PT_STACK ? "stack" - : alpha_procedure_type == PT_REGISTER ? "reg" : "null"); alpha_need_linkage (fnname, 1); text_section (); #endif @@ -7729,6 +7769,39 @@ alpha_expand_epilogue () } } } + +#if TARGET_ABI_OPEN_VMS +#include + +/* Structure to collect function names for final output + in link section. */ + +enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; +enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR}; + +struct alpha_funcs +{ + int num; + splay_tree links; +}; + +struct alpha_links +{ + int num; + rtx linkage; + enum links_kind lkind; + enum reloc_kind rkind; +}; + +static splay_tree alpha_funcs_tree; +static splay_tree alpha_links_tree; + +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 *)); + +static int alpha_funcs_num; +#endif /* Output the rest of the textual info surrounding the epilogue. */ @@ -7747,6 +7820,10 @@ alpha_end_function (file, fnname, decl) } inside_function = FALSE; +#if TARGET_ABI_OPEN_VMS + alpha_write_linkage (file, fnname, decl); +#endif + /* Show that we know this function if it is called again. Do this only for functions whose symbols bind locally. @@ -8931,25 +9008,6 @@ 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 -{ - rtx linkage; - enum links_kind kind; -}; - -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 @@ -8983,46 +9041,67 @@ alpha_need_linkage (name, is_local) { splay_tree_node node; struct alpha_links *al; + struct alpha_funcs *cfaf; if (name[0] == '*') name++; - if (alpha_links) + if (is_local) + { + alpha_funcs_tree = splay_tree_new + ((splay_tree_compare_fn) splay_tree_compare_pointers, + (splay_tree_delete_key_fn) free, + (splay_tree_delete_key_fn) free); + + cfaf = (struct alpha_funcs *) xmalloc (sizeof (struct alpha_funcs)); + + cfaf->links = 0; + cfaf->num = ++alpha_funcs_num; + + splay_tree_insert (alpha_funcs_tree, + (splay_tree_key) current_function_decl, + (splay_tree_value) cfaf); + + } + + if (alpha_links_tree) { /* Is this name already defined? */ - node = splay_tree_lookup (alpha_links, (splay_tree_key) name); + node = splay_tree_lookup (alpha_links_tree, (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; + if (al->lkind == KIND_EXTERN) + al->lkind = KIND_LOCAL; } else { /* Used here but unused assumed. */ - if (al->kind == KIND_UNUSED) - al->kind = KIND_LOCAL; + if (al->lkind == KIND_UNUSED) + al->lkind = 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); + alpha_links_tree = 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_tree, 1, 1, mark_alpha_links); } al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); name = xstrdup (name); /* Assume external if no definition. */ - al->kind = (is_local ? KIND_UNUSED : KIND_EXTERN); + al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN); /* Ensure we have an IDENTIFIER so assemble_name can mark it used. */ get_identifier (name); @@ -9038,50 +9117,165 @@ alpha_need_linkage (name, is_local) ggc_alloc_string (linksym, name_len + 5)); } - splay_tree_insert (alpha_links, (splay_tree_key) name, + splay_tree_insert (alpha_links_tree, (splay_tree_key) name, (splay_tree_value) al); return al->linkage; } +rtx +alpha_use_linkage (linkage, cfundecl, lflag, rflag) + rtx linkage; + tree cfundecl; + int lflag; + int rflag; +{ + splay_tree_node cfunnode; + struct alpha_funcs *cfaf; + struct alpha_links *al; + const char *name = XSTR (linkage, 0); + + cfaf = (struct alpha_funcs *) 0; + al = (struct alpha_links *) 0; + + cfunnode = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) cfundecl); + cfaf = (struct alpha_funcs *) cfunnode->value; + + if (cfaf->links) + { + splay_tree_node lnode; + + /* Is this name already defined? */ + + lnode = splay_tree_lookup (cfaf->links, (splay_tree_key) name); + if (lnode) + al = (struct alpha_links *) lnode->value; + } + else + { + cfaf->links = splay_tree_new + ((splay_tree_compare_fn) strcmp, + (splay_tree_delete_key_fn) free, + (splay_tree_delete_key_fn) free); + ggc_add_root (&cfaf->links, 1, 1, mark_alpha_links); + } + + if (!al) + { + size_t name_len; + size_t buflen; + char buf [512]; + char *linksym; + splay_tree_node node = 0; + struct alpha_links *anl; + + if (name[0] == '*') + name++; + + name_len = strlen (name); + + al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); + al->num = cfaf->num; + + node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name); + if (node) + { + anl = (struct alpha_links *) node->value; + al->lkind = anl->lkind; + } + + sprintf (buf, "$%d..%s..lk", cfaf->num, name); + buflen = strlen (buf); + linksym = alloca (buflen + 1); + memcpy (linksym, buf, buflen + 1); + + al->linkage = gen_rtx_SYMBOL_REF + (Pmode, ggc_alloc_string (linksym, buflen + 1)); + + splay_tree_insert (cfaf->links, (splay_tree_key) name, + (splay_tree_value) al); + } + + if (rflag) + al->rkind = KIND_CODEADDR; + else + al->rkind = KIND_LINKAGE; + + if (lflag) + return gen_rtx_MEM (Pmode, plus_constant (al->linkage, 8)); + else + return al->linkage; +} + static int alpha_write_one_linkage (node, data) splay_tree_node node; void *data; { const char *const name = (const char *) node->key; - struct alpha_links *links = (struct alpha_links *) node->value; + struct alpha_links *link = (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) + fprintf (stream, "$%d..%s..lk:\n", link->num, name); + if (link->rkind == KIND_CODEADDR) { - /* Local and used, build linkage pair. */ - fprintf (stream, "\t.quad %s..en\n", name); - fprintf (stream, "\t.quad %s\n", name); + if (link->lkind == KIND_LOCAL) + { + /* Local and used */ + fprintf (stream, "\t.quad %s..en\n", name); + } + else + { + /* External and used, request code address. */ + fprintf (stream, "\t.code_address %s\n", name); + } } else { - /* External and used, request linkage pair. */ - fprintf (stream, "\t.linkage %s\n", name); + if (link->lkind == 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; +static void +alpha_write_linkage (stream, funname, fundecl) + FILE *stream; + const char *funname; + tree fundecl; { - if (alpha_links) + splay_tree_node node; + struct alpha_funcs *func; + + link_section (); + fprintf (stream, "\t.align 3\n"); + node = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) fundecl); + func = (struct alpha_funcs *) node->value; + + fputs ("\t.name ", stream); + assemble_name (stream, funname); + fputs ("..na\n", stream); + ASM_OUTPUT_LABEL (stream, funname); + fprintf (stream, "\t.pdesc "); + assemble_name (stream, funname); + fprintf (stream, "..en,%s\n", + alpha_procedure_type == PT_STACK ? "stack" + : alpha_procedure_type == PT_REGISTER ? "reg" : "null"); + + if (func->links) { - readonly_data_section (); - fprintf (stream, "\t.align 3\n"); - splay_tree_foreach (alpha_links, alpha_write_one_linkage, stream); + splay_tree_foreach (func->links, alpha_write_one_linkage, stream); + /* splay_tree_delete (func->links); */ } } @@ -9174,6 +9368,16 @@ alpha_need_linkage (name, is_local) return NULL_RTX; } +rtx +alpha_use_linkage (linkage, cfundecl, lflag, rflag) + rtx linkage ATTRIBUTE_UNUSED; + tree cfundecl ATTRIBUTE_UNUSED; + int lflag ATTRIBUTE_UNUSED; + int rflag ATTRIBUTE_UNUSED; +{ + return NULL_RTX; +} + #endif /* TARGET_ABI_OPEN_VMS */ #if TARGET_ABI_UNICOSMK diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index c955a9d75a7..7e3b3754c09 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -4429,11 +4429,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]); if (GET_CODE (operands[0]) == SYMBOL_REF) { - rtx linkage = alpha_need_linkage (XSTR (operands[0], 0), 0); + 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))); + operands[2] = const0_rtx; } else { @@ -4531,11 +4529,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]); if (GET_CODE (operands[1]) == SYMBOL_REF) { - rtx linkage = alpha_need_linkage (XSTR (operands[1], 0), 0); + 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))); + operands[3] = const0_rtx; } else { @@ -4720,17 +4716,31 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" [(set_attr "type" "jsr") (set_attr "length" "*,*,12")]) +; GAS relies on the order and position of instructions output below in order +; to generate relocs for VMS link to potentially optimize the call. +; Please do not molest. (define_insn "*call_vms_1" [(call (mem:DI (match_operand:DI 0 "call_operand" "r,s")) (match_operand 1 "" "")) - (use (match_operand:DI 2 "nonimmediate_operand" "r,m")) + (use (match_operand:DI 2 "nonmemory_operand" "r,n")) (use (reg:DI 25)) (use (reg:DI 26)) (clobber (reg:DI 27))] "TARGET_ABI_OPEN_VMS" - "@ - mov %2,$27\;jsr $26,0\;ldq $27,0($29) - ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)" + "* +{ + switch (which_alternative) + { + case 0: + return \"mov %2,$27\;jsr $26,0\;ldq $27,0($29)\"; + case 1: + operands [2] = alpha_use_linkage (operands [0], cfun->decl, 1, 0); + operands [3] = alpha_use_linkage (operands [0], cfun->decl, 0, 0); + return \"ldq $26,%3\;ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)\"; + default: + abort(); + } +}" [(set_attr "type" "jsr") (set_attr "length" "12,16")]) @@ -7896,18 +7906,32 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" [(set_attr "type" "jsr") (set_attr "length" "*,*,12")]) +; GAS relies on the order and position of instructions output below in order +; to generate relocs for VMS link to potentially optimize the call. +; Please do not molest. (define_insn "*call_value_vms_1" [(set (match_operand 0 "" "") (call (mem:DI (match_operand:DI 1 "call_operand" "r,s")) (match_operand 2 "" ""))) - (use (match_operand:DI 3 "nonimmediate_operand" "r,m")) + (use (match_operand:DI 3 "nonmemory_operand" "r,n")) (use (reg:DI 25)) (use (reg:DI 26)) (clobber (reg:DI 27))] "TARGET_ABI_OPEN_VMS" - "@ - mov %3,$27\;jsr $26,0\;ldq $27,0($29) - ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)" + "* +{ + switch (which_alternative) + { + case 0: + return \"mov %3,$27\;jsr $26,0\;ldq $27,0($29)\"; + case 1: + operands [3] = alpha_use_linkage (operands [1], cfun->decl, 1, 0); + operands [4] = alpha_use_linkage (operands [1], cfun->decl, 0, 0); + return \"ldq $26,%4\;ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)\"; + default: + abort(); + } +}" [(set_attr "type" "jsr") (set_attr "length" "12,16")]) diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h index 03dd491c823..b0da28a3cdf 100644 --- a/gcc/config/alpha/vms.h +++ b/gcc/config/alpha/vms.h @@ -300,8 +300,6 @@ extern void literals_section PARAMS ((void)); #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ fprintf (FILE, "\t.quad $L%d\n", (VALUE)) -#define ASM_FILE_END(FILE) alpha_write_linkage (FILE); - #undef CASE_VECTOR_MODE #define CASE_VECTOR_MODE DImode #undef CASE_VECTOR_PC_RELATIVE