fis-gtm/sr_port/stack_frame.h

201 lines
9.1 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#ifndef __STACK_FRAME_H__
#define __STACK_FRAME_H__
/* stack_frame.h - GT.M MUMPS stack frame */
/* There are several references to this structure from assembly language; these include:
*
* From VMS: G_MSF.MAX
* From Unix: g_msf.si
* From z/OS: 'gtc.xxxxxxxx.maclib(GTMSFRME)'
* 'gtc.xxxxxxxx.maclib(G$MSF)'
*
* Any changes to the stack frame must be reflected in those files as well.
*
* Warning: the lists above may not be complete.
*/
#include "hashtab_mname.h"
typedef struct saved_for_indx_array_struct
{
mval *saved_for_indx[1];
} saved_for_indx;
typedef struct stack_frame_struct /* contents of the GT.M MUMPS stack frame */
{
struct rhead_struct *rvector; /* routine header */
#if defined(__MVS__)
unsigned char *mumsf_r5; /* register 5 */
unsigned char *mumsf_r6; /* register 6 */
unsigned char *mpc; /* mumps program counter */
unsigned char *mumsf_r8; /* register 8 */
unsigned char *mumsf_r9; /* register 9 */
ht_ent_mname **l_symtab; /* local symbol table */
unsigned char *temps_ptr; /* pointer to base of temps */
unsigned char *ctxt; /* context pointer (base register for use when there's no PC-relative address mode) */
int4 *literal_ptr; /* pointer to base of literals */
unsigned char *mumsf_r14; /* register 14 */
unsigned char *mumsf_r15; /* register 15 */
unsigned char *mumsf_r0; /* register 0 */
unsigned char *mumsf_r1; /* register 1 */
unsigned char *calldm_base; /* register 2 */
unsigned char *mumsf_r3; /* register 3 */
#else
ht_ent_mname **l_symtab; /* local symbol table */
unsigned char *mpc; /* mumps program counter */
unsigned char *ctxt; /* context pointer (base register for use when there's no PC-relative address mode) */
#ifdef HAS_LITERAL_SECT
int4 *literal_ptr; /* pointer to base of literals */
#endif
unsigned char *temps_ptr; /* pointer to base of temps */
#endif
char *vartab_ptr; /* variable table may be in rvector or on stack */
GTM64_ONLY(struct stack_frame_struct *old_frame_pointer;) /* Moved old_frame_pointer near all pointers
* for alignment and smaller stackframe size
*/
short vartab_len; /* variable table length */
short temp_mvals; /* temp mval count if this frame for an indirect rtn (ihdtyp) */
NON_GTM64_ONLY(struct stack_frame_struct *old_frame_pointer;) /* old_frame_pointer remains at the same
* place for 32-bit platforms
*/
/* note the alignment of these next two fields is critical to correct operation of
* opp_ret on the VMS platforms. Any changes here need to be reflected there.
*/
unsigned short type;
unsigned char flags;
bool dollar_test;
saved_for_indx *for_ctrl_stack; /* anchor for array of FOR control variable indices */
mval *ret_value;
} stack_frame;
/* Stack frame types */
#define SFT_COUNT (1 << 0) /* 0x0001 frame counts (real code) or doesn't (transcendental code) */
#define SFT_DM (1 << 1) /* 0x0002 direct mode */
#define SFT_REP_OP (1 << 2) /* 0x0004 frame to replace opcode (zbreak has already occured) */
#define SFT_ZBRK_ACT (1 << 3) /* 0x0008 action frame for zbreak */
#define SFT_DEV_ACT (1 << 4) /* 0x0010 action frame for device error handler */
#define SFT_ZTRAP (1 << 5) /* 0x0020 error handler frame ($ZTRAP or $ETRAP) */
/* 0x0040 VACANT!!!: extfun frame is no longer used */
#define SFT_ZSTEP_ACT (1 << 7) /* 0x0080 action frame for a zstep */
#define SFT_ZINTR (1 << 8) /* 0x0100 $zinterrupt frame */
#define SFT_TRIGR (1 << 9) /* 0x0200 Trigger base frame */
/* The following definition identifies a frame that is running a line of code - either in a routine or what amounts to an XECUTE
* it excludes frames dealing with @ indirection and frames generated for various nefarious internal purposes.
* As of this writing, it's used in op_unwind to identify a frame that should receive a relocated for_ctrl_stack created by an @
* frame - see op_unwind for the code and additional comments
*/
#define SFT_LINE_OF_CODE_FRAME (SFT_COUNT | SFT_ZBRK_ACT | SFT_DEV_ACT | SFT_ZTRAP | SFT_ZSTEP_ACT | SFT_ZINTR)
/* Flags for flag byte */
#define SFF_INDCE (1 << 0) /* 0x01 This frame is executing an indirect cache entry */
#define SFF_ZTRAP_ERR (1 << 1) /* 0x02 error occured during $ZTRAP compilation */
#define SFF_DEV_ACT_ERR (1 << 2) /* 0x04 compilation error occured in device exception handler */
#define SFF_CI (1 << 3) /* 0x08 call-in base frame */
#define SFF_ETRAP_ERR (1 << 4) /* 0x10 An $ETRAP style error occurred while in this frame. A return to this frame will
* cause the getframe macro to invoke error_return() for further error processing.
*/
#define SFF_UNW_SYMVAL (1 << 5) /* 0x20 Unwound a symval in this stackframe (relevant to tp_restart) */
#define SFF_IMPLTSTART_CALLD (1 << 6) /* 0x40 This frame initiated a trigger call or spanning node transaction
* - checked by MUM_TSTART to prevent error returns to the frame
* which would cause a restart of error handling.
*/
#define SFF_INDCE_OFF ~(SFF_INDCE) /* Mask to turn off SFF_INDCE */
#define SFF_ZTRAP_ERR_OFF ~(SFF_ZTRAP_ERR) /* Mask to turn off SFF_ZTRAP_ERR */
#define SFF_DEV_ACT_ERR_OFF ~(SFF_DEV_ACT_ERR) /* Mask to turn off SFF_DEV_ACT_ERR */
#define SFF_CI_OFF ~(SFF_CI) /* Mask to turn off SFF_CI */
#define SFF_ETRAP_ERR_OFF ~(SFF_ETRAP_ERR) /* Mask to turn off SFF_ETRAP_ERR */
#define SFF_UNW_SYMVAL_OFF ~(SFF_UNW_SYMVAL) /* Mask to turn off SFF_UNW_SYMVAL */
#define SFF_IMPLTSTART_CALLD_OFF ~(SFF_IMPLTSTART_CALLD) /* Mask to turn off SFF_IMPLTSTART_CALLD */
#define ADJUST_FRAME_POINTER(fptr, shift) \
{ \
GBLREF stack_frame *error_frame; \
stack_frame *oldfp; \
\
oldfp = fptr; \
fptr = (stack_frame *)((char *)oldfp - shift); \
if (error_frame == oldfp) \
{ /* Adjust "error_frame" as well */ \
assert(error_frame >= frame_pointer); \
error_frame = fptr; \
} \
}
/* the following macro ensures there's an array of FOR pointers and frees any old entry that's about to get overlaid */
#define MANAGE_FOR_INDX(FPTR, LEVEL, NEW_INDX) \
{ \
assert(NULL != NEW_INDX); \
if (NULL == FPTR->for_ctrl_stack) \
{ \
FPTR->for_ctrl_stack = (saved_for_indx *)malloc(SIZEOF(mval *) * MAX_FOR_STACK); \
memset(FPTR->for_ctrl_stack, 0, SIZEOF(mval *) * MAX_FOR_STACK); \
} else \
FREE_INDX_AND_CLR_SIBS(FPTR, LEVEL, NEW_INDX); \
assert(NULL == FPTR->for_ctrl_stack->saved_for_indx[LEVEL]); \
FPTR->for_ctrl_stack->saved_for_indx[LEVEL] = NEW_INDX; \
}
/* the following macro runs the FOR pointer array, freeing anything it finds before freeing the array
* in theory it could work down the array, but since the above macro needs FREE_INDX_AND_CLR_SIBS to work up, this does too
*/
#define FREE_SAVED_FOR_INDX(FPTR) \
{ \
uint4 Level; \
\
assert(NULL != FPTR->for_ctrl_stack); \
for (Level = 1; Level < MAX_FOR_STACK; Level++) /* level 0 never holds a pointer */ \
FREE_INDX_AND_CLR_SIBS(FPTR, Level, NULL); \
free((char *)FPTR->for_ctrl_stack); \
}
/* the following macro, currentl only used by the above 2 macros,
* deals with the possibility of the same control variable at multiple nesting levels and clears higher nesting levels
*/
#define FREE_INDX_AND_CLR_SIBS(FPTR, LEVEL, NEW_INDX) \
{ \
uint4 Lvl; \
mval *Ptr; \
\
if (NULL != (Ptr = FPTR->for_ctrl_stack->saved_for_indx[LEVEL])) /* NOTE assignment */ \
{ \
free((char *)Ptr); \
for (Lvl = 1; Lvl < MAX_FOR_STACK; Lvl++) /* level 0 never holds a pointer */ \
if (Ptr == FPTR->for_ctrl_stack->saved_for_indx[Lvl]) \
FPTR->for_ctrl_stack->saved_for_indx[Lvl] = (mval *)(Lvl < LEVEL ? NEW_INDX : NULL); \
} \
}
void new_stack_frame(rhdtyp *rtn_base, unsigned char *context, unsigned char *transfer_addr);
void new_stack_frame_sp(rhdtyp *rtn_base, unsigned char *context, unsigned char *transfer_addr);
int4 symbinit(void);
unsigned char *get_symb_line(unsigned char *out, unsigned char **b_line, unsigned char **ctxt);
unsigned char *symb_line(unsigned char *in_addr, unsigned char *out, unsigned char **b_line, rhdtyp *routine);
void copy_stack_frame(void);
void copy_stack_frame_sp(void);
void exfun_frame(void);
void exfun_frame_sp(void);
void exfun_frame_push_dummy_frame(void);
void base_frame(rhdtyp *base_address);
void pseudo_ret(void);
void call_dm(void);
int dm_start(void);
stack_frame *op_get_msf (void);
int op_zbreak(stack_frame *fp);
void adjust_frames(unsigned char *old_ptext_beg, unsigned char *old_ptext_end, unsigned char *new_ptext_beg);
#endif