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;
}
/* DWARF2 EH unwinding support for Alpha VMS.
Copyright (C) 2004, 2007 Free Software Foundation, Inc.
/* Fallback frame unwinding for Alpha/VMS.
Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2009
Free Software Foundation, Inc.
This file is part of GCC.
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 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.
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.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
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.
#include <pdscdef.h>
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/>. */
#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state
#include <stdlib.h>
#include <stdio.h>
#include <vms/pdscdef.h>
#include <vms/libicb.h>
#include <vms/chfctxdef.h>
#include <vms/chfdef.h>
static _Unwind_Reason_Code
alpha_fallback_frame_state (struct _Unwind_Context *context,
_Unwind_FrameState *fs)
#define MD_FALLBACK_FRAME_STATE_FOR alpha_vms_fallback_frame_state
typedef void * ADDR;
typedef unsigned long long REG;
typedef PDSCDEF * PV;
#define REG_AT(addr) (*(REG *)(addr))
#define ADDR_AT(addr) (*(ADDR *)(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)
extern int SYS$GL_CALL_HANDL;
/* This is actually defined as a "long", but in system code where longs
are always 4bytes while GCC longs might be 8bytes. */
#define UPDATE_FS_FOR_CFA_GR(FS, GRN, LOC, CFA) \
do { \
(FS)->regs.reg[GRN].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[GRN].loc.offset = (_Unwind_Sword) ((REG) (LOC) - (REG) (CFA)); \
} while (0);
#define GIVEUP_ON_FAILURE(STATUS) \
{ if ((((STATUS) & 1) != 1)) return _URC_END_OF_STACK; }
#define DENOTES_EXC_DISPATCHER(PV) ((PV) == (ADDR) (REG) SYS$GL_CALL_HANDL)
#define RA_COLUMN (DWARF_ALT_FRAME_RETURN_COLUMN)
static int
alpha_vms_fallback_frame_state (struct _Unwind_Context *context,
_Unwind_FrameState *fs)
{
PDSCDEF *pv = *((PDSCDEF **) context->reg [29]);
static int eh_debug = -1;
/* Our goal is to update FS to reflect the state one step up CONTEXT, that
is: the CFA, return address and *saved* registers locations associated
with the function designated by CONTEXT->ra. We are called when the
libgcc unwinder has not found any dwarf FDE for this address, which
typically happens when trying to propagate a language exception through a
signal global vector or frame based handler.
The CONTEXT->reg[] entries reflect the state/location of register saves
so designate values live at the CONTEXT->ra point. Of precious value to
us here is the frame pointer (r29), which gets us a procedure value. */
PV pv = (context->reg[29] != 0) ? PV_FOR (ADDR_AT (context->reg[29])) : 0;
int pkind = pv ? pv->pdsc$w_flags & 0xf : 0;
/* VMS procedure kind, as indicated by the procedure descriptor. We only
know how to deal with FP_STACK or FP_REGISTER here. */
ADDR new_cfa = 0;
/* CFA we will establish for the caller, computed in different ways,
e.g. depending whether we cross an exception dispatcher frame. */
CHFCTX *chfctx = 0;
/* Pointer to the VMS CHF context associated with an exception dispatcher
frame, if we happen to come across one. */
int i,j;
if (eh_debug == -1)
{
char * eh_debug_env = getenv ("EH_DEBUG");
eh_debug = eh_debug_env ? atoi (eh_debug_env) : 0;
}
if (eh_debug)
printf ("MD_FALLBACK running ...\n");
/* We only know how to deal with stack or reg frame procedures, so give
up if we're handed anything else. */
if (pkind != PDSC$K_KIND_FP_STACK && pkind != PDSC$K_KIND_FP_REGISTER)
return _URC_END_OF_STACK;
if (eh_debug)
printf ("FALLBACK: CTX FP = 0x%p, PV = 0x%p, EN = 0x%llx, RA = 0x%p\n",
ADDR_AT (context->reg[29]), pv, pv->pdsc$q_entry, context->ra);
fs->retaddr_column = RA_COLUMN;
/* If PV designates a VMS exception vector or condition handler, we need to
do as if the caller was the signaling point and estabish the state of the
intermediate VMS code (CFA, RA and saved register locations) as if it was
a single regular function. This requires special processing.
The datastructures available from an condition dispatcher frame (signal
context) do not contain the values of most callee-saved registers, so
whathever PV designates, we need to account for the registers it saves.
Besides, we need to express all the locations with respect to a
consistent CFA value, so we compute this first. */
if (DENOTES_EXC_DISPATCHER (pv))
{
/* The CFA to establish is the signaling point's stack pointer. We
compute it using the system invocation context unwinding services and
save the CHF context data pointer along the way for later uses. */
INVO_CONTEXT_BLK icb;
int status, invo_handle;
if (eh_debug)
printf ("FALLBACK: SYS$HANDLER\n");
icb.libicb$q_ireg [29] = REG_AT (context->reg[29]);
icb.libicb$q_ireg [30] = 0;
invo_handle = LIB$GET_INVO_HANDLE (&icb);
status = LIB$GET_INVO_CONTEXT (invo_handle, &icb);
GIVEUP_ON_FAILURE (status);
chfctx = (CHFCTX *) icb.libicb$ph_chfctx_addr;
status = LIB$GET_PREV_INVO_CONTEXT (&icb);
GIVEUP_ON_FAILURE (status);
if (pv && ((long) pv & 0x7) == 0) /* low bits 0 means address */
pv = *(PDSCDEF **) pv;
new_cfa = (ADDR) icb.libicb$q_ireg[30];
}
else
{
/* The CFA to establish is the SP value on entry of the procedure
designated by PV, which we compute as the corresponding frame base
register value + frame size. Note that the frame base may differ
from CONTEXT->cfa, typically if the caller has performed dynamic
stack allocations. */
int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
ADDR base_addr = ADDR_AT (context->reg[base_reg]);
new_cfa = base_addr + pv->pdsc$l_size;
}
/* State to compute the caller's CFA by adding an offset to the current
one in CONTEXT. */
fs->regs.cfa_how = CFA_REG_OFFSET;
fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
fs->regs.cfa_offset = new_cfa - context->cfa;
if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_STACK))
/* Regular unwind first, accounting for the register saves performed by
the procedure designated by PV. */
switch (pkind)
{
int i, j;
fs->regs.cfa_offset = pv->pdsc$l_size;
fs->regs.cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
fs->retaddr_column = 26;
fs->regs.cfa_how = CFA_REG_OFFSET;
fs->regs.reg[27].loc.offset = -pv->pdsc$l_size;
fs->regs.reg[27].how = REG_SAVED_OFFSET;
fs->regs.reg[26].loc.offset
= -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset);
fs->regs.reg[26].how = REG_SAVED_OFFSET;
for (i = 0, j = 0; i < 32; i++)
if (1<<i & pv->pdsc$l_ireg_mask)
{
fs->regs.reg[i].loc.offset
= -(pv->pdsc$l_size - pv->pdsc$w_rsa_offset - 8 * ++j);
fs->regs.reg[i].how = REG_SAVED_OFFSET;
}
return _URC_NO_REASON;
case PDSC$K_KIND_FP_STACK:
{
/* The saved registers are all located in the Register Save Area,
except for the procedure value register (R27) found at the frame
base address. */
int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
ADDR base_addr = ADDR_AT (context->reg[base_reg]);
ADDR rsa_addr = base_addr + pv->pdsc$w_rsa_offset;
if (eh_debug)
printf ("FALLBACK: STACK frame procedure\n");
UPDATE_FS_FOR_CFA_GR (fs, 27, base_addr, new_cfa);
/* The first RSA entry is for the return address register, R26. */
UPDATE_FS_FOR_CFA_GR (fs, 26, rsa_addr, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, rsa_addr, new_cfa);
/* The following entries are for registers marked as saved according
to ireg_mask. */
for (i = 0, j = 0; i < 32; i++)
if ((1 << i) & pv->pdsc$l_ireg_mask)
UPDATE_FS_FOR_CFA_GR (fs, i, rsa_addr + 8 * ++j, new_cfa);
/* ??? floating point registers ? */
break;
}
case PDSC$K_KIND_FP_REGISTER:
{
if (eh_debug)
printf ("FALLBACK: REGISTER frame procedure\n");
fs->regs.reg[RA_COLUMN].how = REG_SAVED_REG;
fs->regs.reg[RA_COLUMN].loc.reg = pv->pdsc$b_save_ra;
fs->regs.reg[29].how = REG_SAVED_REG;
fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp;
break;
}
default:
/* Should never reach here. */
return _URC_END_OF_STACK;
}
else if (pv && ((pv->pdsc$w_flags & 0xf) == PDSC$K_KIND_FP_REGISTER))
/* If PV designates an exception dispatcher, we have to adjust the return
address column to get at the signal occurrence point, and account for
for what the CHF context contains. */
if (DENOTES_EXC_DISPATCHER (pv))
{
fs->regs.cfa_offset = pv->pdsc$l_size;
fs->regs.cfa_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30;
fs->retaddr_column = 26;
fs->regs.cfa_how = CFA_REG_OFFSET;
fs->regs.reg[26].loc.reg = pv->pdsc$b_save_ra;
fs->regs.reg[26].how = REG_SAVED_REG;
fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp;
fs->regs.reg[29].how = REG_SAVED_REG;
return _URC_NO_REASON;
/* The PC of the instruction causing the condition is available from the
signal argument vector. Extra saved register values are available
from the mechargs array. */
CHF$SIGNAL_ARRAY *sigargs
= (CHF$SIGNAL_ARRAY *) chfctx->chfctx$q_sigarglst;
CHF$MECH_ARRAY *mechargs
= (CHF$MECH_ARRAY *) chfctx->chfctx$q_mcharglst;
ADDR condpc_addr
= &((int *)(&sigargs->chf$l_sig_name)) [sigargs->chf$is_sig_args-2];
ADDR rei_frame_addr = (void *) mechargs->chf$q_mch_esf_addr;
/* Adjust the return address location. */
UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, condpc_addr, new_cfa);
/* The frame pointer at the condition point is available from the
chf context directly. */
UPDATE_FS_FOR_CFA_GR (fs, 29, &chfctx->chfctx$q_expt_fp, new_cfa);
/* Registers available from the mechargs array. */
UPDATE_FS_FOR_CFA_GR (fs, 0, &mechargs->chf$q_mch_savr0, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 1, &mechargs->chf$q_mch_savr1, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 16, &mechargs->chf$q_mch_savr16, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 17, &mechargs->chf$q_mch_savr17, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 18, &mechargs->chf$q_mch_savr18, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 19, &mechargs->chf$q_mch_savr19, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 20, &mechargs->chf$q_mch_savr20, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 21, &mechargs->chf$q_mch_savr21, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 22, &mechargs->chf$q_mch_savr22, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 23, &mechargs->chf$q_mch_savr23, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 24, &mechargs->chf$q_mch_savr24, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 25, &mechargs->chf$q_mch_savr25, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 26, &mechargs->chf$q_mch_savr26, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 27, &mechargs->chf$q_mch_savr27, new_cfa);
UPDATE_FS_FOR_CFA_GR (fs, 28, &mechargs->chf$q_mch_savr28, new_cfa);
/* Registers R2 to R7 are available from the rei frame pointer. */
for (i = 2; i <= 7; i ++)
UPDATE_FS_FOR_CFA_GR (fs, i, rei_frame_addr+(i - 2)*8, new_cfa);
/* ??? floating point registers ? */
}
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
......@@ -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