201 lines
9.1 KiB
C
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
|