Commit 221cf9ab by Olivier Hainque Committed by Douglas Rupp

alpha.c (struct machine_function): New flag for VMS, uses_condition_handler.


	* config/alpha/alpha.c (struct machine_function): New flag for VMS,
	uses_condition_handler.
	(alpha_expand_builtin_establish_vms_condition_handler): New expander.
	(alpha_expand_builtin_revert_vms_condition_handler): New expander.
	(enum alpha_builtin): New ALPHA_BUILTIN_REVERT_VMS_CONDITION_HANDLER
	and ALPHA_BUILTIN_ESTABLISH_VMS_CONDITION_HANDLER values.
	(code_for_builtin): New insn codes for the new alpha_builtins.
	(alpha_init_builtins): Register the new functions as BUILT_IN_MD.
	(alpha_sa_size): Account for uses_condition_handler.
	(alpha_expand_prologue): Likewise.
	(alpha_start_function): Likewise.
	(alpha_expand_epilogue): Likewise.
	* config/alpha/alpha-protos.h: Prototype the new alpha.c builtin
	establish/revert expanders.
	* config/alpha/alpha.h (DWARF_FRAME_REGNUM): Define.
	* config/alpha/alpha.md	(builtin_establish_vms_condition_handler):
	New expander, resorting to the alpha.c associated function.
	(builtin_revert_vms_condition_handler): Likewise.
	* config/alpha/vms-gcc_shell_handler.c: New file. Implements
	__gcc_shell_handler, the static VMS condition handler used as
	an indirection wrapper to the current dynamically established
	handler.
	* config/alpha/vms-unwind.h: Complete rewrite.
	* config/alpha/t-vms (LIB2FUNCS_EXTRA): Add vms-gcc_shell_handler.c
	* config/alpha/vms.h (MD_UNWIND_SUPPORT):
	

Co-Authored-By: Douglas B Rupp <rupp@gnat.com>

From-SVN: r150612
parent b714133e
2009-08-09 Olivier Hainque <hainque@adacore.com>
Douglas B Rupp <rupp@gnat.com>
* config/alpha/alpha.c (struct machine_function): New flag for VMS,
uses_condition_handler.
(alpha_expand_builtin_establish_vms_condition_handler): New expander.
(alpha_expand_builtin_revert_vms_condition_handler): New expander.
(enum alpha_builtin): New ALPHA_BUILTIN_REVERT_VMS_CONDITION_HANDLER
and ALPHA_BUILTIN_ESTABLISH_VMS_CONDITION_HANDLER values.
(code_for_builtin): New insn codes for the new alpha_builtins.
(alpha_init_builtins): Register the new functions as BUILT_IN_MD.
(alpha_sa_size): Account for uses_condition_handler.
(alpha_expand_prologue): Likewise.
(alpha_start_function): Likewise.
(alpha_expand_epilogue): Likewise.
* config/alpha/alpha-protos.h: Prototype the new alpha.c builtin
establish/revert expanders.
* config/alpha/alpha.h (DWARF_FRAME_REGNUM): Define.
* config/alpha/alpha.md (builtin_establish_vms_condition_handler):
New expander, resorting to the alpha.c associated function.
(builtin_revert_vms_condition_handler): Likewise.
* config/alpha/vms-gcc_shell_handler.c: New file. Implements
__gcc_shell_handler, the static VMS condition handler used as
an indirection wrapper to the current dynamically established
handler.
* config/alpha/vms-unwind.h: Complete rewrite.
* config/alpha/t-vms (LIB2FUNCS_EXTRA): Add vms-gcc_shell_handler.c
* config/alpha/vms.h (MD_UNWIND_SUPPORT):
2009-08-09 Eric Botcazou <botcazou@adacore.com>
Douglas B Rupp <rupp@gnat.com>
......
......@@ -67,6 +67,9 @@ extern rtx alpha_expand_zap_mask (HOST_WIDE_INT);
extern void alpha_expand_builtin_vector_binop (rtx (*)(rtx, rtx, rtx),
enum machine_mode,
rtx, rtx, rtx);
extern void alpha_expand_builtin_establish_vms_condition_handler (rtx, rtx);
extern void alpha_expand_builtin_revert_vms_condition_handler (rtx);
extern rtx alpha_return_addr (int, rtx);
extern rtx alpha_gp_save_rtx (void);
extern void print_operand (FILE *, rtx, int);
......
......@@ -4779,6 +4779,9 @@ struct GTY(()) machine_function
/* For TARGET_LD_BUGGY_LDGP. */
struct rtx_def *gp_save_rtx;
/* For VMS condition handlers. */
bool uses_condition_handler;
};
/* How to allocate a 'struct machine_function'. */
......@@ -4790,6 +4793,63 @@ alpha_init_machine_status (void)
ggc_alloc_cleared (sizeof (struct machine_function)));
}
/* Support for frame based VMS condition handlers. */
/* A VMS condition handler may be established for a function with a call to
__builtin_establish_vms_condition_handler, and cancelled with a call to
__builtin_revert_vms_condition_handler.
The VMS Condition Handling Facility knows about the existence of a handler
from the procedure descriptor .handler field. As the VMS native compilers,
we store the user specified handler's address at a fixed location in the
stack frame and point the procedure descriptor at a common wrapper which
fetches the real handler's address and issues an indirect call.
The indirection wrapper is "__gcc_shell_handler", provided by libgcc.
We force the procedure kind to PT_STACK, and the fixed frame location is
fp+8, just before the register save area. We use the handler_data field in
the procedure descriptor to state the fp offset at which the installed
handler address can be found. */
#define VMS_COND_HANDLER_FP_OFFSET 8
/* Expand code to store the currently installed user VMS condition handler
into TARGET and install HANDLER as the new condition handler. */
void
alpha_expand_builtin_establish_vms_condition_handler (rtx target, rtx handler)
{
rtx handler_slot_address
= plus_constant (hard_frame_pointer_rtx, VMS_COND_HANDLER_FP_OFFSET);
rtx handler_slot
= gen_rtx_MEM (DImode, handler_slot_address);
emit_move_insn (target, handler_slot);
emit_move_insn (handler_slot, handler);
/* Notify the start/prologue/epilogue emitters that the condition handler
slot is needed. In addition to reserving the slot space, this will force
the procedure kind to PT_STACK so ensure that the hard_frame_pointer_rtx
use above is correct. */
cfun->machine->uses_condition_handler = true;
}
/* Expand code to store the current VMS condition handler into TARGET and
nullify it. */
void
alpha_expand_builtin_revert_vms_condition_handler (rtx target)
{
/* We implement this by establishing a null condition handler, with the tiny
side effect of setting uses_condition_handler. This is a little bit
pessimistic if no actual builtin_establish call is ever issued, which is
not a real problem and expected never to happen anyway. */
alpha_expand_builtin_establish_vms_condition_handler (target, const0_rtx);
}
/* Functions to save and restore alpha_return_addr_rtx. */
/* Start the ball rolling with RETURN_ADDR_RTX. */
......@@ -6380,6 +6440,8 @@ enum alpha_builtin
ALPHA_BUILTIN_RPCC,
ALPHA_BUILTIN_THREAD_POINTER,
ALPHA_BUILTIN_SET_THREAD_POINTER,
ALPHA_BUILTIN_ESTABLISH_VMS_CONDITION_HANDLER,
ALPHA_BUILTIN_REVERT_VMS_CONDITION_HANDLER,
/* TARGET_MAX */
ALPHA_BUILTIN_MINUB8,
......@@ -6435,6 +6497,8 @@ static enum insn_code const code_for_builtin[ALPHA_BUILTIN_max] = {
CODE_FOR_builtin_rpcc,
CODE_FOR_load_tp,
CODE_FOR_set_tp,
CODE_FOR_builtin_establish_vms_condition_handler,
CODE_FOR_builtin_revert_vms_condition_handler,
/* TARGET_MAX */
CODE_FOR_builtin_minub8,
......@@ -6580,6 +6644,21 @@ alpha_init_builtins (void)
NULL, NULL);
TREE_NOTHROW (decl) = 1;
if (TARGET_ABI_OPEN_VMS)
{
ftype = build_function_type_list (ptr_type_node, ptr_type_node,
NULL_TREE);
add_builtin_function ("__builtin_establish_vms_condition_handler", ftype,
ALPHA_BUILTIN_ESTABLISH_VMS_CONDITION_HANDLER,
BUILT_IN_MD, NULL, NULL_TREE);
ftype = build_function_type_list (ptr_type_node, void_type_node,
NULL_TREE);
add_builtin_function ("__builtin_revert_vms_condition_handler", ftype,
ALPHA_BUILTIN_REVERT_VMS_CONDITION_HANDLER,
BUILT_IN_MD, NULL, NULL_TREE);
}
alpha_v8qi_u = build_vector_type (unsigned_intQI_type_node, 8);
alpha_v8qi_s = build_vector_type (intQI_type_node, 8);
alpha_v4hi_u = build_vector_type (unsigned_intHI_type_node, 4);
......@@ -7309,7 +7388,10 @@ alpha_sa_size (void)
if (! fixed_regs[i] && call_used_regs[i] && ! df_regs_ever_live_p (i))
vms_save_fp_regno = i;
if (vms_save_fp_regno == -1 && alpha_procedure_type == PT_REGISTER)
/* A VMS condition handler requires a stack procedure in our
implementation. (not required by the calling standard). */
if ((vms_save_fp_regno == -1 && alpha_procedure_type == PT_REGISTER)
|| cfun->machine->uses_condition_handler)
vms_base_regno = REG_PV, alpha_procedure_type = PT_STACK;
else if (alpha_procedure_type == PT_NULL)
vms_base_regno = REG_PV;
......@@ -7318,9 +7400,10 @@ alpha_sa_size (void)
vms_unwind_regno = (vms_base_regno == REG_PV
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
/* If this is a stack procedure, allow space for saving FP and RA. */
/* If this is a stack procedure, allow space for saving FP, RA and
a condition handler slot if needed. */
if (alpha_procedure_type == PT_STACK)
sa_size += 2;
sa_size += 2 + cfun->machine->uses_condition_handler;
}
else
{
......@@ -7572,7 +7655,7 @@ alpha_expand_prologue (void)
+ crtl->args.pretend_args_size));
if (TARGET_ABI_OPEN_VMS)
reg_offset = 8;
reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
else
reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
......@@ -7910,7 +7993,7 @@ alpha_start_function (FILE *file, const char *fnname,
+ crtl->args.pretend_args_size));
if (TARGET_ABI_OPEN_VMS)
reg_offset = 8;
reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
else
reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
......@@ -8049,6 +8132,16 @@ alpha_start_function (FILE *file, const char *fnname,
}
#if TARGET_ABI_OPEN_VMS
/* If a user condition handler has been installed at some point, emit
the procedure descriptor bits to point the Condition Handling Facility
at the indirection wrapper, and state the fp offset at which the user
handler may be found. */
if (cfun->machine->uses_condition_handler)
{
fprintf (file, "\t.handler __gcc_shell_handler\n");
fprintf (file, "\t.handler_data %d\n", VMS_COND_HANDLER_FP_OFFSET);
}
/* Ifdef'ed cause link_section are only available then. */
switch_to_section (readonly_data_section);
fprintf (file, "\t.align 3\n");
......@@ -8120,7 +8213,7 @@ alpha_expand_epilogue (void)
if (TARGET_ABI_OPEN_VMS)
{
if (alpha_procedure_type == PT_STACK)
reg_offset = 8;
reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
else
reg_offset = 0;
}
......
......@@ -882,6 +882,12 @@ do { \
#define RETURN_ADDR_RTX alpha_return_addr
/* Provide a definition of DWARF_FRAME_REGNUM here so that fallback unwinders
can use DWARF_ALT_FRAME_RETURN_COLUMN defined below. This is just the same
as the default definition in dwarf2out.c. */
#undef DWARF_FRAME_REGNUM
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
/* Before the prologue, RA lives in $26. */
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 26)
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (26)
......
......@@ -4976,6 +4976,24 @@
return "call_pal 0x9f";
}
[(set_attr "type" "callpal")])
;; Special builtins for establishing and reverting VMS condition handlers.
(define_expand "builtin_establish_vms_condition_handler"
[(set (reg:DI 0) (match_operand:DI 0 "register_operand" ""))
(use (match_operand:DI 1 "address_operand" ""))]
"TARGET_ABI_OPEN_VMS"
{
alpha_expand_builtin_establish_vms_condition_handler (operands[0],
operands[1]);
})
(define_expand "builtin_revert_vms_condition_handler"
[(set (reg:DI 0) (match_operand:DI 0 "register_operand" ""))]
"TARGET_ABI_OPEN_VMS"
{
alpha_expand_builtin_revert_vms_condition_handler (operands[0]);
})
;; Finally, we have the basic data motion insns. The byte and word insns
;; are done via define_expand. Start with the floating-point insns, since
......
......@@ -17,6 +17,8 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
LIB2FUNCS_EXTRA = $(srcdir)/config/alpha/vms-gcc_shell_handler.c
EXTRA_PARTS = vms-dwarf2.o vms-dwarf2eh.o $(VMS_EXTRA_PARTS) \
crtbegin.o crtbeginS.o crtend.o crtendS.o
......
/* Static condition handler for Alpha/VMS.
Copyright (C) 2005-2009
Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your
option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* This file implements __gcc_shell_handler, the static VMS condition handler
used as the indirection wrapper around user level handlers installed with
establish_vms_condition_handler GCC builtin.
[ABI] in comments refers to the "HP OpenVMS calling standard" document
dated January 2005. */
#include <vms/chfdef.h>
#include <vms/pdscdef.h>
#include <vms/ssdef.h>
typedef void * ADDR;
typedef unsigned long long REG;
#define REG_AT(addr) (*(REG *)(addr))
/* Compute pointer to procedure descriptor (Procedure Value) from Frame
Pointer FP, according to the rules in [ABI-3.5.1 Current Procedure]. */
#define PV_FOR(FP) \
(((FP) != 0) \
? (((REG_AT (FP) & 0x7) == 0) ? *(PDSCDEF **)(FP) : (PDSCDEF *)(FP)) : 0)
long
__gcc_shell_handler (struct chf$signal_array *sig_arr,
struct chf$mech_array *mech_arr);
/* Helper for __gcc_shell_handler. Fetch the pointer to procedure currently
registered as the VMS condition handler for the live function with a frame
pointer FP. */
static ADDR
get_dyn_handler_pointer (REG fp)
{
/* From the frame pointer we find the procedure descriptor, and fetch
the handler_data field from there. This field contains the offset
from FP at which the address of the currently installed handler is
to be found. */
PDSCDEF * pd = PV_FOR (fp);
/* Procedure descriptor pointer for the live subprogram with FP as the frame
pointer, and to which _gcc_shell_handler is attached as a condition
handler. */
REG handler_slot_offset;
/* Offset from FP at which the address of the currently established real
condition handler is to be found. This offset is available from the
handler_data field of the procedure descriptor. */
REG handler_data_offset;
/* The handler_data field position in the procedure descriptor, which
depends on the kind of procedure at hand. */
switch (pd->pdsc$w_flags & 0xf)
{
case PDSC$K_KIND_FP_STACK: /* [3.4.2 PD for stack frame procedures] */
handler_data_offset = 40;
break;
case PDSC$K_KIND_FP_REGISTER: /* [3.4.5 PD for reg frame procedures] */
handler_data_offset = 32;
break;
default:
handler_data_offset = 0;
break;
}
/* If we couldn't determine the handler_data field position, give up. */
if (handler_data_offset == 0)
return 0;
/* Otherwise, fetch the fp offset at which the real handler address is to be
found, then fetch and return the latter in turn. */
handler_slot_offset = REG_AT ((REG)pd + handler_data_offset);
return (ADDR) REG_AT (fp + handler_slot_offset);
}
/* The static VMS condition handler for GCC code. Fetch the address of the
currently established condition handler, then resignal if there is none or
call the handler with the VMS condition arguments. */
long
__gcc_shell_handler (struct chf$signal_array *sig_arr,
struct chf$mech_array *mech_arr)
{
long ret;
long (*user_handler) (struct chf$signal_array *, struct chf$mech_array *);
user_handler = get_dyn_handler_pointer (mech_arr->chf$q_mch_frame);
if (!user_handler)
ret = SS$_RESIGNAL;
else
ret = user_handler (sig_arr, mech_arr);
return ret;
}
......@@ -287,7 +287,13 @@ do { \
#define LINK_EH_SPEC "vms-dwarf2eh.o%s "
#define LINK_GCC_C_SEQUENCE_SPEC "%G"
#ifdef IN_LIBGCC2
/* Get the definition for MD_FALLBACK_FRAME_STATE_FOR from a separate
file. This avoids having to recompile the world instead of libgcc only
when changes to this macro are exercised. */
#define MD_UNWIND_SUPPORT "config/alpha/vms-unwind.h"
#endif
/* This is how to output an assembler line
that says to advance the location counter
......
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