Commit 63966b3b by Richard Henderson Committed by Richard Henderson

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
parent 820964cd
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) ...@@ -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 if (TARGET_OPEN_VMS)
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) return ptr_type_node;
!= void_type_node));
/* Compute the current position into the args, taking into account record = make_node (RECORD_TYPE);
both registers and memory. Both of these are already included in /* C++? SET_IS_AGGR_TYPE (record, 1); */
NUM_ARGS. */
argsize = GEN_INT (NUM_ARGS * UNITS_PER_WORD); ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
integer_type_node);
DECL_FIELD_CONTEXT (ofs) = record;
/* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48, base = build_decl (FIELD_DECL, get_identifier ("__base"),
storing fp arg registers in the first 48 bytes, and the integer arg ptr_type_node);
registers in the next 48 bytes. This is only done, however, if any DECL_FIELD_CONTEXT (base) = record;
integer registers need to be stored. TREE_CHAIN (base) = ofs;
If no integer registers need be stored, then we must subtract 48 in TYPE_FIELDS (record) = base;
order to account for the integer arg registers which are counted in layout_type (record);
argsize above, but which are not actually stored on the stack. */
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) if (TARGET_OPEN_VMS)
addr = plus_constant (virtual_incoming_args_rtx, std_expand_builtin_va_start (stdarg_p, valist, nextarg);
NUM_ARGS <= 5 + stdarg
? UNITS_PER_WORD : - 6 * 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 (NUM_ARGS <= 5 + stdarg_p)
offset = 6 * UNITS_PER_WORD;
else else
addr = (NUM_ARGS <= 5 + stdarg offset = -6 * UNITS_PER_WORD;
? plus_constant (virtual_incoming_args_rtx,
6 * UNITS_PER_WORD) base_field = TYPE_FIELDS (TREE_TYPE (valist));
: plus_constant (virtual_incoming_args_rtx, offset_field = TREE_CHAIN (base_field);
- (6 * UNITS_PER_WORD)));
base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
/* For VMS, we include the argsize, while on Unix, it's handled as valist, base_field);
a separate 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) if (TARGET_OPEN_VMS)
addr = plus_constant (addr, INTVAL (argsize)); return std_expand_builtin_va_arg (valist, type);
addr = force_operand (addr, NULL_RTX); tsize = ((TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT + 7) / 8) * 8;
#ifdef POINTERS_EXTEND_UNSIGNED base_field = TYPE_FIELDS (TREE_TYPE (valist));
addr = convert_memory_address (ptr_mode, addr); offset_field = TREE_CHAIN (base_field);
#endif
if (TARGET_OPEN_VMS) base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
return addr; valist, base_field);
else 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 */ tree fpaddend, cond;
block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
RTX_UNCHANGING_P (block) = 1; fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
RTX_UNCHANGING_P (XEXP (block, 0)) = 1; addend, build_int_2 (-6*8, 0)));
/* Store the address of the first integer register in the __base cond = fold (build (LT_EXPR, integer_type_node,
member. */ wide_ofs, build_int_2 (6*8, 0)));
dest = change_address (block, ptr_mode, XEXP (block, 0)); addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
emit_move_insn (dest, addr); fpaddend, addend));
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);
} }
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; ...@@ -1161,19 +1161,22 @@ extern int alpha_memory_latency;
{ \ { \
if (! (NO_RTL)) \ 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 \ move_block_from_reg \
(16 + CUM, \ (16 + CUM, tmp, \
gen_rtx (MEM, BLKmode, \
plus_constant (virtual_incoming_args_rtx, \
((CUM) + 6)* UNITS_PER_WORD)), \
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \ 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 \ move_block_from_reg \
(16 + (TARGET_FPREGS ? 32 : 0) + CUM, \ (16 + (TARGET_FPREGS ? 32 : 0) + CUM, tmp, \
gen_rtx (MEM, BLKmode, \
plus_constant (virtual_incoming_args_rtx, \
(CUM) * UNITS_PER_WORD)), \
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 (); ...@@ -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 { \ ...@@ -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 (); ...@@ -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 ();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment