alpha.h (EXPAND_BUILTIN_SAVEREGS): Delete.

* alpha.h (EXPAND_BUILTIN_SAVEREGS): Delete.
        (BUILD_VA_LIST_TYPE): New.
        (EXPAND_BUILTIN_VA_START): New.
        (EXPAND_BUILTIN_VA_ARG): New.
        * alpha.c (alpha_builtin_saveregs): Delete.
        (alpha_build_va_list): New.
        (alpha_va_start): New.
        (alpha_va_arg): New.

From-SVN: r28252
This commit is contained in:
Richard Henderson 1999-07-25 22:48:39 -07:00 committed by Richard Henderson
parent 820964cd73
commit 63966b3bc6
3 changed files with 150 additions and 95 deletions

View File

@ -1,3 +1,14 @@
Sun Jul 25 22:45:55 1999 Richard Henderson <rth@cygnus.com>
* alpha.h (EXPAND_BUILTIN_SAVEREGS): Delete.
(BUILD_VA_LIST_TYPE): New.
(EXPAND_BUILTIN_VA_START): New.
(EXPAND_BUILTIN_VA_ARG): New.
* alpha.c (alpha_builtin_saveregs): Delete.
(alpha_build_va_list): New.
(alpha_va_start): New.
(alpha_va_arg): New.
Sun Jul 25 21:40:33 1999 Jeffrey A Law (law@cygnus.com)
* gcc.texi: More changes related to list conversion.

View File

@ -3083,101 +3083,132 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
emit_insn (gen_imb ());
}
/* Do what is necessary for `va_start'. The argument is ignored;
We look at the current function to determine if stdarg or varargs
is used and fill in an initial va_list. A pointer to this constructor
is returned. */
struct rtx_def *
alpha_builtin_saveregs (arglist)
tree arglist ATTRIBUTE_UNUSED;
tree
alpha_build_va_list ()
{
rtx block, addr, dest, argsize;
tree fntype = TREE_TYPE (current_function_decl);
int stdarg = (TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
!= void_type_node));
/* Compute the current position into the args, taking into account
both registers and memory. Both of these are already included in
NUM_ARGS. */
argsize = GEN_INT (NUM_ARGS * UNITS_PER_WORD);
/* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48,
storing fp arg registers in the first 48 bytes, and the integer arg
registers in the next 48 bytes. This is only done, however, if any
integer registers need to be stored.
If no integer registers need be stored, then we must subtract 48 in
order to account for the integer arg registers which are counted in
argsize above, but which are not actually stored on the stack. */
tree base, ofs, record;
if (TARGET_OPEN_VMS)
addr = plus_constant (virtual_incoming_args_rtx,
NUM_ARGS <= 5 + stdarg
? UNITS_PER_WORD : - 6 * UNITS_PER_WORD);
return ptr_type_node;
record = make_node (RECORD_TYPE);
/* C++? SET_IS_AGGR_TYPE (record, 1); */
ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
integer_type_node);
DECL_FIELD_CONTEXT (ofs) = record;
base = build_decl (FIELD_DECL, get_identifier ("__base"),
ptr_type_node);
DECL_FIELD_CONTEXT (base) = record;
TREE_CHAIN (base) = ofs;
TYPE_FIELDS (record) = base;
layout_type (record);
return record;
}
void
alpha_va_start (stdarg_p, valist, nextarg)
int stdarg_p;
tree valist;
rtx nextarg ATTRIBUTE_UNUSED;
{
HOST_WIDE_INT offset;
tree t, offset_field, base_field;
if (TARGET_OPEN_VMS)
std_expand_builtin_va_start (stdarg_p, valist, nextarg);
/* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
up by 48, storing fp arg registers in the first 48 bytes, and the
integer arg registers in the next 48 bytes. This is only done,
however, if any integer registers need to be stored.
If no integer registers need be stored, then we must subtract 48
in order to account for the integer arg registers which are counted
in argsize above, but which are not actually stored on the stack. */
if (NUM_ARGS <= 5 + stdarg_p)
offset = 6 * UNITS_PER_WORD;
else
addr = (NUM_ARGS <= 5 + stdarg
? plus_constant (virtual_incoming_args_rtx,
6 * UNITS_PER_WORD)
: plus_constant (virtual_incoming_args_rtx,
- (6 * UNITS_PER_WORD)));
offset = -6 * UNITS_PER_WORD;
/* For VMS, we include the argsize, while on Unix, it's handled as
a separate field. */
if (TARGET_OPEN_VMS)
addr = plus_constant (addr, INTVAL (argsize));
base_field = TYPE_FIELDS (TREE_TYPE (valist));
offset_field = TREE_CHAIN (base_field);
addr = force_operand (addr, NULL_RTX);
base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
valist, base_field);
offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
valist, offset_field);
#ifdef POINTERS_EXTEND_UNSIGNED
addr = convert_memory_address (ptr_mode, addr);
#endif
t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
t = build (PLUS_EXPR, ptr_type_node, t, build_int_2 (offset, 0));
t = build (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build_int_2 (NUM_ARGS*UNITS_PER_WORD, 0);
t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
rtx
alpha_va_arg (valist, type)
tree valist, type;
{
HOST_WIDE_INT tsize;
rtx addr;
tree t;
tree offset_field, base_field, addr_tree, addend;
tree wide_type, wide_ofs;
if (TARGET_OPEN_VMS)
return addr;
else
return std_expand_builtin_va_arg (valist, type);
tsize = ((TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT + 7) / 8) * 8;
base_field = TYPE_FIELDS (TREE_TYPE (valist));
offset_field = TREE_CHAIN (base_field);
base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
valist, base_field);
offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
valist, offset_field);
wide_type = make_signed_type (64);
wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
addend = wide_ofs;
if (FLOAT_TYPE_P (type))
{
/* Allocate the va_list constructor */
block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
RTX_UNCHANGING_P (block) = 1;
RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
tree fpaddend, cond;
/* Store the address of the first integer register in the __base
member. */
fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
addend, build_int_2 (-6*8, 0)));
dest = change_address (block, ptr_mode, XEXP (block, 0));
emit_move_insn (dest, addr);
cond = fold (build (LT_EXPR, integer_type_node,
wide_ofs, build_int_2 (6*8, 0)));
if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
dest, ptr_mode,
GEN_INT (GET_MODE_SIZE (ptr_mode)),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));
/* Store the argsize as the __va_offset member. */
dest = change_address (block, TYPE_MODE (integer_type_node),
plus_constant (XEXP (block, 0),
POINTER_SIZE/BITS_PER_UNIT));
emit_move_insn (dest, argsize);
if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
dest, ptr_mode,
GEN_INT (GET_MODE_SIZE
(TYPE_MODE (integer_type_node))),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));
/* Return the address of the va_list constructor, but don't put it in a
register. Doing so would fail when not optimizing and produce worse
code when optimizing. */
return XEXP (block, 0);
addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
fpaddend, addend));
}
addr_tree = build (PLUS_EXPR, TREE_TYPE (base_field),
base_field, addend);
addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
addr = copy_to_reg (addr);
t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
build (PLUS_EXPR, TREE_TYPE (offset_field),
offset_field, build_int_2 (tsize, 0)));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
return addr;
}
/* This page contains routines that are used to determine what the function

View File

@ -1161,19 +1161,22 @@ extern int alpha_memory_latency;
{ \
if (! (NO_RTL)) \
{ \
rtx tmp; int set = get_varargs_alias_set (); \
tmp = gen_rtx_MEM (BLKmode, \
plus_constant (virtual_incoming_args_rtx, \
((CUM) + 6)* UNITS_PER_WORD)); \
MEM_ALIAS_SET (tmp) = set; \
move_block_from_reg \
(16 + CUM, \
gen_rtx (MEM, BLKmode, \
plus_constant (virtual_incoming_args_rtx, \
((CUM) + 6)* UNITS_PER_WORD)), \
(16 + CUM, tmp, \
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
\
tmp = gen_rtx_MEM (BLKmode, \
plus_constant (virtual_incoming_args_rtx, \
(CUM) * UNITS_PER_WORD)); \
MEM_ALIAS_SET (tmp) = set; \
move_block_from_reg \
(16 + (TARGET_FPREGS ? 32 : 0) + CUM, \
gen_rtx (MEM, BLKmode, \
plus_constant (virtual_incoming_args_rtx, \
(CUM) * UNITS_PER_WORD)), \
(16 + (TARGET_FPREGS ? 32 : 0) + CUM, tmp, \
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
emit_insn (gen_blockage ()); \
} \
PRETEND_SIZE = 12 * UNITS_PER_WORD; \
} \
@ -1189,11 +1192,6 @@ extern struct rtx_def *alpha_emit_set_long_const ();
extern struct rtx_def *alpha_emit_conditional_branch ();
extern struct rtx_def *alpha_emit_conditional_move ();
/* Generate necessary RTL for __builtin_saveregs().
ARGLIST is the argument list; see expr.c. */
extern struct rtx_def *alpha_builtin_saveregs ();
#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) alpha_builtin_saveregs (ARGLIST)
/* Define the information needed to generate branch and scc insns. This is
stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */
@ -2348,6 +2346,18 @@ do { \
{"reg_not_elim_operand", {SUBREG, REG}}, \
{"reg_no_subreg_operand", {REG}},
/* Define the `__builtin_va_list' type for the ABI. */
#define BUILD_VA_LIST_TYPE(VALIST) \
(VALIST) = alpha_build_va_list ()
/* Implement `va_start' for varargs and stdarg. */
#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
alpha_va_start (stdarg, valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
alpha_va_arg (valist, type)
/* Tell collect that the object format is ECOFF. */
#define OBJECT_FORMAT_COFF
#define EXTENDED_COFF
@ -2548,3 +2558,6 @@ extern int alpha_expand_block_move ();
extern int alpha_expand_block_clear ();
extern void alpha_expand_prologue ();
extern void alpha_expand_epilogue ();
extern union tree_node *alpha_build_va_list ();
extern void alpha_va_start ();
extern struct rtx_def *alpha_va_arg ();