alpha-protos.h: Update.

* 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.

From-SVN: r56338
This commit is contained in:
Douglas B Rupp 2002-08-15 05:04:27 +00:00 committed by Douglas Rupp
parent d1f1cc6a0f
commit 1330f7d5b6
5 changed files with 335 additions and 81 deletions

View File

@ -1,3 +1,31 @@
2002-08-14 Douglas B Rupp <rupp@gnat.com>
* 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 <rth@redhat.com>
* ggc-page.c (RTL_SIZE): New.

View File

@ -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));

View File

@ -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 <splay-tree.h>
/* 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 <splay-tree.h>
/* 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

View File

@ -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")])

View File

@ -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