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:
parent
820964cd73
commit
63966b3bc6
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
|
Loading…
Reference in New Issue
Block a user