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)
|
Sun Jul 25 21:40:33 1999 Jeffrey A Law (law@cygnus.com)
|
||||||
|
|
||||||
* gcc.texi: More changes related to list conversion.
|
* 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 ());
|
emit_insn (gen_imb ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do what is necessary for `va_start'. The argument is ignored;
|
tree
|
||||||
We look at the current function to determine if stdarg or varargs
|
alpha_build_va_list ()
|
||||||
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;
|
|
||||||
{
|
{
|
||||||
rtx block, addr, dest, argsize;
|
tree base, ofs, record;
|
||||||
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. */
|
|
||||||
|
|
||||||
if (TARGET_OPEN_VMS)
|
if (TARGET_OPEN_VMS)
|
||||||
addr = plus_constant (virtual_incoming_args_rtx,
|
return ptr_type_node;
|
||||||
NUM_ARGS <= 5 + stdarg
|
|
||||||
? UNITS_PER_WORD : - 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)));
|
|
||||||
|
|
||||||
/* For VMS, we include the argsize, while on Unix, it's handled as
|
record = make_node (RECORD_TYPE);
|
||||||
a separate field. */
|
/* C++? SET_IS_AGGR_TYPE (record, 1); */
|
||||||
if (TARGET_OPEN_VMS)
|
|
||||||
addr = plus_constant (addr, INTVAL (argsize));
|
|
||||||
|
|
||||||
addr = force_operand (addr, NULL_RTX);
|
ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
|
||||||
|
integer_type_node);
|
||||||
|
DECL_FIELD_CONTEXT (ofs) = record;
|
||||||
|
|
||||||
#ifdef POINTERS_EXTEND_UNSIGNED
|
base = build_decl (FIELD_DECL, get_identifier ("__base"),
|
||||||
addr = convert_memory_address (ptr_mode, addr);
|
ptr_type_node);
|
||||||
#endif
|
DECL_FIELD_CONTEXT (base) = record;
|
||||||
|
TREE_CHAIN (base) = ofs;
|
||||||
|
|
||||||
if (TARGET_OPEN_VMS)
|
TYPE_FIELDS (record) = base;
|
||||||
return addr;
|
layout_type (record);
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* Store the address of the first integer register in the __base
|
return record;
|
||||||
member. */
|
|
||||||
|
|
||||||
dest = change_address (block, ptr_mode, XEXP (block, 0));
|
|
||||||
emit_move_insn (dest, addr);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
offset = -6 * UNITS_PER_WORD;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 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))
|
||||||
|
{
|
||||||
|
tree fpaddend, cond;
|
||||||
|
|
||||||
|
fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
|
||||||
|
addend, build_int_2 (-6*8, 0)));
|
||||||
|
|
||||||
|
cond = fold (build (LT_EXPR, integer_type_node,
|
||||||
|
wide_ofs, build_int_2 (6*8, 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
|
/* This page contains routines that are used to determine what the function
|
||||||
|
|
|
@ -1161,19 +1161,22 @@ extern int alpha_memory_latency;
|
||||||
{ \
|
{ \
|
||||||
if (! (NO_RTL)) \
|
if (! (NO_RTL)) \
|
||||||
{ \
|
{ \
|
||||||
move_block_from_reg \
|
rtx tmp; int set = get_varargs_alias_set (); \
|
||||||
(16 + CUM, \
|
tmp = gen_rtx_MEM (BLKmode, \
|
||||||
gen_rtx (MEM, BLKmode, \
|
|
||||||
plus_constant (virtual_incoming_args_rtx, \
|
plus_constant (virtual_incoming_args_rtx, \
|
||||||
((CUM) + 6)* UNITS_PER_WORD)), \
|
((CUM) + 6)* UNITS_PER_WORD)); \
|
||||||
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
|
MEM_ALIAS_SET (tmp) = set; \
|
||||||
move_block_from_reg \
|
move_block_from_reg \
|
||||||
(16 + (TARGET_FPREGS ? 32 : 0) + CUM, \
|
(16 + CUM, tmp, \
|
||||||
gen_rtx (MEM, BLKmode, \
|
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
|
||||||
plus_constant (virtual_incoming_args_rtx, \
|
\
|
||||||
(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, tmp, \
|
||||||
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
|
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
|
||||||
emit_insn (gen_blockage ()); \
|
|
||||||
} \
|
} \
|
||||||
PRETEND_SIZE = 12 * UNITS_PER_WORD; \
|
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_branch ();
|
||||||
extern struct rtx_def *alpha_emit_conditional_move ();
|
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
|
/* 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
|
stored from the compare operation. Note that we can't use "rtx" here
|
||||||
since it hasn't been defined! */
|
since it hasn't been defined! */
|
||||||
|
@ -2348,6 +2346,18 @@ do { \
|
||||||
{"reg_not_elim_operand", {SUBREG, REG}}, \
|
{"reg_not_elim_operand", {SUBREG, REG}}, \
|
||||||
{"reg_no_subreg_operand", {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. */
|
/* Tell collect that the object format is ECOFF. */
|
||||||
#define OBJECT_FORMAT_COFF
|
#define OBJECT_FORMAT_COFF
|
||||||
#define EXTENDED_COFF
|
#define EXTENDED_COFF
|
||||||
|
@ -2548,3 +2558,6 @@ extern int alpha_expand_block_move ();
|
||||||
extern int alpha_expand_block_clear ();
|
extern int alpha_expand_block_clear ();
|
||||||
extern void alpha_expand_prologue ();
|
extern void alpha_expand_prologue ();
|
||||||
extern void alpha_expand_epilogue ();
|
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