+2009-08-10 Olivier Hainque <hainqueu@adacore.com>
+ Douglas B Rupp <rupp@gnat.com>
+
+ * config/alpha/alpha.c (alpha_sa_size): Force procedure type to
+ PT_STACK when frame_pointer_needed on OpenVMS.
+ (alpha_pv_save_size, alpha_using_fp): Remove.
+ (alpha_vms_can_eliminate): New function. Support for CAN_ELIMINATE
+ with proper processing for PT_NULL.
+ (alpha_vms_initial_elimination_offset): New function. Support for
+ INITIAL_ELIMINATION_OFFSET with proper processing for PT_NULL.
+ (alpha_sa_size): Force procedure type to PT_STACK when
+ frame_pointer_needed on OpenVMS.
+ * config/alpha/alpha-protos.h (alpha_pv_save_size): Remove prototype.
+ (alpha_using_fp): Likewise.
+ (alpha_vms_can_eliminate): Add prototype.
+ (alpha_vms_initial_elimination_offset): Likewise.
+ * config/alpha/vms.h (CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET):
+ Call alpha_vms_can_eliminate and alpha_vms_initial_elimination_offset.
+
2009-08-10 Eric Botcazou <botcazou@adacore.com>
Douglas B Rupp <rupp@gnat.com>
extern int alpha_sa_size (void);
extern HOST_WIDE_INT alpha_initial_elimination_offset (unsigned int,
unsigned int);
-extern int alpha_pv_save_size (void);
-extern int alpha_using_fp (void);
extern void alpha_expand_prologue (void);
extern void alpha_expand_epilogue (void);
extern void alpha_output_filename (FILE *, const char *);
extern void vms_output_aligned_decl_common (FILE *, tree, const char *,
unsigned HOST_WIDE_INT,
unsigned int);
-
+extern int alpha_vms_can_eliminate (unsigned int, unsigned int);
+extern HOST_WIDE_INT alpha_vms_initial_elimination_offset (unsigned int,
+ unsigned int);
#endif
extern rtx unicosmk_add_call_info_word (rtx);
}
else if (TARGET_ABI_OPEN_VMS)
{
- /* Start by assuming we can use a register procedure if we don't
- make any calls (REG_RA not used) or need to save any
- registers and a stack procedure if we do. */
- if ((mask[0] >> REG_RA) & 1)
+ /* Start with a stack procedure if we make any calls (REG_RA used), or
+ need a frame pointer, with a register procedure if we otherwise need
+ at least a slot, and with a null procedure in other cases. */
+ if ((mask[0] >> REG_RA) & 1 || frame_pointer_needed)
alpha_procedure_type = PT_STACK;
else if (get_frame_size() != 0)
alpha_procedure_type = PT_REGISTER;
return ret;
}
+#if TARGET_ABI_OPEN_VMS
+
int
-alpha_pv_save_size (void)
+alpha_vms_can_eliminate (unsigned int from ATTRIBUTE_UNUSED, unsigned int to)
{
+ /* We need the alpha_procedure_type to decide. Evaluate it now. */
alpha_sa_size ();
- return alpha_procedure_type == PT_STACK ? 8 : 0;
+
+ switch (alpha_procedure_type)
+ {
+ case PT_NULL:
+ /* NULL procedures have no frame of their own and we only
+ know how to resolve from the current stack pointer. */
+ return to == STACK_POINTER_REGNUM;
+
+ case PT_REGISTER:
+ case PT_STACK:
+ /* We always eliminate except to the stack pointer if there is no
+ usable frame pointer at hand. */
+ return (to != STACK_POINTER_REGNUM
+ || vms_unwind_regno != HARD_FRAME_POINTER_REGNUM);
+ }
+
+ gcc_unreachable ();
}
-int
-alpha_using_fp (void)
-{
- alpha_sa_size ();
- return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM;
+/* FROM is to be eliminated for TO. Return the offset so that TO+offset
+ designates the same location as FROM. */
+
+HOST_WIDE_INT
+alpha_vms_initial_elimination_offset (unsigned int from, unsigned int to)
+{
+ /* The only possible attempts we ever expect are ARG or FRAME_PTR to
+ HARD_FRAME or STACK_PTR. We need the alpha_procedure_type to decide
+ on the proper computations and will need the register save area size
+ in most cases. */
+
+ HOST_WIDE_INT sa_size = alpha_sa_size ();
+
+ /* PT_NULL procedures have no frame of their own and we only allow
+ elimination to the stack pointer. This is the argument pointer and we
+ resolve the soft frame pointer to that as well. */
+
+ if (alpha_procedure_type == PT_NULL)
+ return 0;
+
+ /* For a PT_STACK procedure the frame layout looks as follows
+
+ -----> decreasing addresses
+
+ < size rounded up to 16 | likewise >
+ --------------#------------------------------+++--------------+++-------#
+ incoming args # pretended args | "frame" | regs sa | PV | outgoing args #
+ --------------#---------------------------------------------------------#
+ ^ ^ ^ ^
+ ARG_PTR FRAME_PTR HARD_FRAME_PTR STACK_PTR
+
+
+ PT_REGISTER procedures are similar in that they may have a frame of their
+ own. They have no regs-sa/pv/outgoing-args area.
+
+ We first compute offset to HARD_FRAME_PTR, then add what we need to get
+ to STACK_PTR if need be. */
+
+ {
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT pv_save_size = alpha_procedure_type == PT_STACK ? 8 : 0;
+
+ switch (from)
+ {
+ case FRAME_POINTER_REGNUM:
+ offset = ALPHA_ROUND (sa_size + pv_save_size);
+ break;
+ case ARG_POINTER_REGNUM:
+ offset = (ALPHA_ROUND (sa_size + pv_save_size
+ + get_frame_size ()
+ + crtl->args.pretend_args_size)
+ - crtl->args.pretend_args_size);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (to == STACK_POINTER_REGNUM)
+ offset += ALPHA_ROUND (crtl->outgoing_args_size);
+
+ return offset;
+ }
}
-#if TARGET_ABI_OPEN_VMS
#define COMMON_OBJECT "common_object"
static tree
#undef CAN_ELIMINATE
#define CAN_ELIMINATE(FROM, TO) \
-((TO) != STACK_POINTER_REGNUM || ! alpha_using_fp ())
+ (alpha_vms_can_eliminate ((FROM), (TO)))
#undef INITIAL_ELIMINATION_OFFSET
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-{ switch (FROM) \
- { \
- case FRAME_POINTER_REGNUM: \
- (OFFSET) = alpha_sa_size () + alpha_pv_save_size (); \
- break; \
- case ARG_POINTER_REGNUM: \
- (OFFSET) = (ALPHA_ROUND (alpha_sa_size () + alpha_pv_save_size () \
- + get_frame_size () \
- + crtl->args.pretend_args_size) \
- - crtl->args.pretend_args_size); \
- break; \
- default: \
- gcc_unreachable (); \
- } \
- if ((TO) == STACK_POINTER_REGNUM) \
- (OFFSET) += ALPHA_ROUND (crtl->outgoing_args_size); \
-}
+ ((OFFSET) = alpha_vms_initial_elimination_offset(FROM, TO))
+
\f
/* Define a data type for recording info about an argument list
during the scan of that argument list. This data type should