This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the EGCS project.
va_list: alpha
- To: gcc-patches@gcc.gnu.org
- Subject: va_list: alpha
- From: Richard Henderson <rth@cygnus.com>
- Date: Sun, 25 Jul 1999 22:55:54 -0700
Unlike most of the other ports, Alpha will no longer work without
the header patches, since I removed __builtin_saveregs. This will
only be temporary.
r~
* 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.
Index: alpha.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.90
diff -c -p -d -r1.90 alpha.c
*** alpha.c 1999/06/25 11:34:14 1.90
--- alpha.c 1999/07/26 05:45:35
*************** alpha_initialize_trampoline (tramp, fnad
*** 3083,3183 ****
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;
{
! 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. */
if (TARGET_OPEN_VMS)
! addr = plus_constant (virtual_incoming_args_rtx,
! 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
! a separate field. */
! if (TARGET_OPEN_VMS)
! addr = plus_constant (addr, INTVAL (argsize));
! addr = force_operand (addr, NULL_RTX);
! #ifdef POINTERS_EXTEND_UNSIGNED
! addr = convert_memory_address (ptr_mode, addr);
! #endif
if (TARGET_OPEN_VMS)
! return addr;
! 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
! 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);
}
}
/* This page contains routines that are used to determine what the function
--- 3083,3214 ----
emit_insn (gen_imb ());
}
! tree
! alpha_build_va_list ()
{
! tree base, ofs, record;
! if (TARGET_OPEN_VMS)
! 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
! 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
Index: alpha.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.h,v
retrieving revision 1.70
diff -c -p -d -r1.70 alpha.h
*** alpha.h 1999/06/25 05:12:42 1.70
--- alpha.h 1999/07/26 05:45:35
*************** extern int alpha_memory_latency;
*** 1161,1179 ****
{ \
if (! (NO_RTL)) \
{ \
move_block_from_reg \
! (16 + CUM, \
! gen_rtx (MEM, BLKmode, \
! plus_constant (virtual_incoming_args_rtx, \
! ((CUM) + 6)* UNITS_PER_WORD)), \
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
move_block_from_reg \
! (16 + (TARGET_FPREGS ? 32 : 0) + CUM, \
! gen_rtx (MEM, BLKmode, \
! plus_constant (virtual_incoming_args_rtx, \
! (CUM) * UNITS_PER_WORD)), \
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
- emit_insn (gen_blockage ()); \
} \
PRETEND_SIZE = 12 * UNITS_PER_WORD; \
} \
--- 1161,1182 ----
{ \
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, 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, tmp, \
6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \
} \
PRETEND_SIZE = 12 * UNITS_PER_WORD; \
} \
*************** extern struct rtx_def *alpha_emit_set_lo
*** 1189,1199 ****
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! */
--- 1192,1197 ----
*************** do { \
*** 2348,2353 ****
--- 2346,2363 ----
{"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
*************** extern int alpha_expand_block_move ();
*** 2548,2550 ****
--- 2558,2563 ----
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 ();