Updated: 11 December 1998 |
OpenVMS Calling Standard
Previous | Contents | Index |
In certain cases, a standard default procedure signature representing a common combination of characteristics is encoded in a special manner. (For example, see the descriptions of PDSC$W_SIGNATURE_OFFSET in Sections 3.4.1 and 3.7.4.)
In the OpenVMS Alpha environment, procedure signatures are used only to effect interoperation between native OpenVMS Alpha and translated VAX VMS or OpenVMS VAX images. Default procedure signature characteristics are defined for each of the two possible call situations.
For an OpenVMS Alpha procedure that is callable from a translated VAX procedure, a default procedure signature implies the following characteristics about the expected parameters and result of a call to that procedure:
For a bound procedure used as a jacket to effect a call into a translated image, a default procedure signature implies the following characteristics about the actual parameters and the expected result from a call to that translated procedure:
Except for the first invocation in a thread, there is always an invocation that was previously considered to be the current procedure invocation. The current procedure invocation, together with the previous current procedure invocations, together with all successive previously current procedure invocations, all the way back to the first invocation in the thread, make up a logical list of procedure contexts referred to as the call chain. The current procedure invocation is always considered to be the first procedure invocation in this logical list and the first procedure invocation executed in the thread is always the last procedure invocation in the list. The register values of all nonscratch registers at the time of the currently active call in a procedure invocation can be determined by walking the call chain and retrieving the procedure invocation context for that invocation. A procedure is called an active procedure (active invocation) while it exists on the call chain.
The call chain and its supporting data are used by code that implements
various aspects of the calling standard such as call returns and
procedure unwinding.
3.6.1 Current Procedure
In this calling standard, R29 is the frame pointer (FP) register that defines the current procedure.
Therefore, the current procedure must always maintain in FP one of the following pointer values:
At any point in time, the FP value can be interpreted to find the procedure descriptor for the current procedure by examining the value at 0(FP) as follows:
By examining the first quadword of the procedure descriptor, the procedure type can be determined from the PDSC$V_KIND field.
The following code is an example of how the current procedure descriptor and procedure type can be found:
LDQ R0,0(FP) ;Fetch quadword at FP AND R0,#7,R28 ;Mask alignment bits BNEQ R28,20$ ;Is procedure descriptor pointer LDQ R0,0(R0) ;Was pointer to procedure descriptor 10$: AND R0,#7,R28 ;Do sanity check BNEQ R28,20$ ;All is well ;Error - Invalid FP 20$: AND R0,#15,R0 ;Get kind bits ;Procedure KIND is now in R0 |
IF PDSC$V_KIND is equal to PDSC$K_KIND_FP_STACK, the current procedure has a stack frame.
If PDSC$V_KIND is equal to PDSC$K_KIND_FP_REGISTER, the current procedure is a register frame procedure.
Either type of procedure can use either type of mechanism to point to
the procedure descriptor. Compilers may choose the appropriate
mechanism to use based on the needs of the procedure involved.
3.6.2 Procedure Call Tracing
Mechanisms for each of the following functions are needed to support procedure call tracing:
This section describes the data structure mechanisms. The routines that
support these functions are described in Section 3.6.3.
3.6.2.1 Referring to a Procedure Invocation from a Data Structure
When referring to a specific procedure invocation at run time, a procedure invocation handle, shown in Figure 3-9, can be used. Defined by constant LIBICB$K_INVO_HANDLE_SIZE, the structure is a single-field longword called HANDLE. HANDLE describes the invocation handle of the procedure.
Figure 3-9 Procedure Invocation Handle Format
To encode a procedure invocation handle, follow these steps:
Note that a procedure invocation handle is not defined for a null frame procedure.
So you can distinguish an invocation of a register frame procedure that calls another register frame procedure (where the called procedure uses no stack space and therefore has the same base register value as the caller), the register number that saved the return address is included in the invocation handle of a register frame procedure. Similarly, the number 3110 in the invocation handle of a stack frame procedure is included to distinguish an invocation of a stack frame procedure that calls a register frame procedure where the called procedure uses no stack space. |
The context of a specific procedure invocation is provided through the use of a data structure called an invocation context block. The minimum size of the block is 528 bytes and is system defined using the constant LIBICB$K_INVO_CONTEXT_BLK_SIZE. The size of the last field (LIBICB$Q_SYSTEM_DEFINED[n]) defined by the host system determines the total size of the block.
The fields defined in the invocation context block are illustrated in Figure 3-10 and described in Table 3-10.
Figure 3-10 Invocation Context Block Format
Field Name | Contents | ||||||||
---|---|---|---|---|---|---|---|---|---|
LIBICB$L_CONTEXT_LENGTH | Unsigned count of the total length in bytes of the context block; this represents the sum of the lengths of the standard-defined portion and the system-defined section. | ||||||||
LIBICB$R_FRAME_FLAGS |
The procedure frame flag bits <24:0> are defined as follows:
|
||||||||
LIBICB$B_BLOCK_VERSION | A byte that defines the version of the context block. Since this block is currently the first version, the value is set to 1. | ||||||||
LIBICB$PH_PROCEDURE_DESCRIPTOR | Address of the procedure descriptor for this context. | ||||||||
LIBICB$Q_PROGRAM_COUNTER | Quadword that contains the current value of the procedure's program counter. For interrupted procedures, this is the same as the continuation program counter; for active procedures, this is the return address back into that procedure. | ||||||||
LIBICB$Q_PROCESSOR_STATUS | Contains the current value of the processor status. | ||||||||
LIBICB$Q_IREG[ n] | Quadword that contains the current value of the integer register in the procedure (where n is the number of the register). | ||||||||
LIBICB$Q_FREG[ n] | Quadword that contains the current value of the floating-point register in the procedure (where n is the number of the register). | ||||||||
LIBICB$Q_SYSTEM_DEFINED[ n] | A variable-sized area with locations defined in quadword increments by the host environment that contains procedure context information. These locations are not defined by this standard. |
A thread can obtain its own context or the current context of any
procedure invocation in the current call chain (given an invocation
handle) by calling the run-time library functions defined in
Section 3.6.3.
3.6.2.4 Walking the Call Chain
During the course of program execution, it is sometimes necessary to walk the call chain. Frame-based exception handling is one case where this is done. Call chain navigation is possible only in the reverse direction (in a latest-to-earliest or top-to-bottom procedure).
To walk the call chain, perform the following steps:
Compilers are allowed to optimize high-level language procedure calls in such a way that they do not appear in the invocation chain. For example, inline procedures never appear in the invocation chain.
Make no assumptions about the relative positions of any memory used for
procedure frame information. There is no guarantee that successive
stack frames will always appear at higher addresses.
3.6.3 Invocation Context Access Routines
A thread can manipulate the invocation context of any procedure in the
thread's virtual address space by calling the following run-time
library functions.
3.6.3.1 LIB$GET_INVO_CONTEXT
A thread can obtain the invocation context of any active procedure by using the following function format:
LIB$GET_INVO_CONTEXT(invo_handle, invo_context) |
Argument | OpenVMS Usage | Type | Access | Mechanism |
---|---|---|---|---|
invo_handle | invo_handle | longword (unsigned) | read | by value |
invo_context | invo_context_blk | structure | write | by reference |
Arguments:
invo_handle
Handle for the desired invocation. |
|
invo_context
Address of an invocation context block into which the procedure context of the frame specified by invo_handle will be written. |
Function Value Returned:
status
Status value. A value of 1 indicates success; a value of 0 indicates failure. |
If the invocation handle that was passed does not represent any procedure context in the active call chain, the value of the new contents of the context block is unpredictable. |
A thread can obtain the invocation context of a current procedure by using the following function format:
LIB$GET_CURR_INVO_CONTEXT(invo_context) |
Argument | OpenVMS Usage | Type | Access | Mechanism |
---|---|---|---|---|
invo_context | invo_context_blk | structure | write | by reference |
Argument:
invo_context
Address of an invocation context block into which the procedure context of the caller will be written. |
Function Value Returned:
None. To facilitate use in the implementation of the C language unwind setjmp or longjump function (only), the routine sets R0 to 0. |
A thread can obtain the invocation context of the procedure context preceding any other procedure context by using the following function format:
LIB$GET_PREV_INVO_CONTEXT(invo_context) |
Argument | OpenVMS Usage | Type | Access | Mechanism |
---|---|---|---|---|
invo_context | invo_context_blk | structure | modify | by reference |
Argument:
invo_context
Address of an invocation context block. The given context block is updated to represent the context of the previous (calling) frame. For the purposes of this function, the minimum fields of an invocation block that must be defined are those IREG and FREG fields corresponding to registers used by a context whether the registers are preserved or not. Note that the invocation context blocks written by the routines specified in these sections define all possible fields in a context block. Such context blocks satisfy this minimum requirement. |
Function Value Returned:
status
Status value. A value of 1 indicates success. When the initial context represents the bottom of the call chain, a value of 0 is returned. If the current operation completed without error, but a stack corruption was detected at the next level down, a value of 3 is returned. |
A thread can obtain an invocation handle corresponding to any invocation context block by using the following function format:
LIB$GET_INVO_HANDLE(invo_context) |
Argument | OpenVMS Usage | Type | Access | Mechanism |
---|---|---|---|---|
invo_context | invo_context_blk | structure | read | by reference |
Argument:
invo_context
Address of an invocation context block. Here, only the frame pointer and stack pointer fields of an invocation context block must be defined. |
Function Value Returned:
invo_handle
Invocation handle of the invocation context that was passed. If the returned value is LIB$K_INVO_HANDLE_NULL, the invocation context that was passed was invalid. |
A thread can obtain an invocation handle of the procedure context preceding that of a specified procedure context by using the following function format:
LIB$GET_PREV_INVO_HANDLE(invo_handle) |
Argument | OpenVMS Usage | Type | Access | Mechanism |
---|---|---|---|---|
invo_handle | invo_handle | longword (unsigned) | read | by value |
Argument:
invo_handle
An invocation handle that represents a target invocation context. |
Function Value Returned:
invo_handle
An invocation handle for the invocation context that is previous to that which was specified as the target. |
A given procedure invocation context's fields can be updated with new register contents by calling a system library function in following format:
LIB$PUT_INVO_REGISTERS(invo_handle, invo_context, invo_mask) |
Argument | OpenVMS Usage | Type | Access | Mechanism |
---|---|---|---|---|
invo_handle | invo_handle | longword (unsigned) | read | by value |
invo_context | invo_context_blk | structure | read | by reference |
invo_mask | mask_quadword | quadword (unsigned) | read | by reference |
Arguments:
invo_handle
Handle for the invocation to be updated. |
|
invo_context
Address of an invocation context block that contains new register contents. Each register that is set in the invo_mask parameter, except SP, is updated using the value found in the corresponding IREG or FREG field. The program counter and processor status can also be updated in this way. (The SP register cannot be updated using this routine.) No other fields of the invocation context block are used. |
|
invo_mask
Address of a 64-bit bit vector, where each bit corresponds to a register field in the passed invo_context. Bits 0 through 30 correspond to IREG[0] through IREG[30], bit 31 corresponds to PROGRAM_COUNTER, bits 32 through 62 correspond to FREG[0] through FREG[30], and bit 63 corresponds to PROCESSOR_STATUS. (If bit 30, which corresponds to SP, is set, then no changes are made.) |
Function Value Returned:
status
Status value. A value of 1 indicates success. When the initial context represents the bottom of the call chain or when bit 30 of the invo_mask argument is set, a value of 0 is returned (and nothing is changed). |
While this routine can be used to update the frame pointer (FP), great care must be taken to assure that a valid stack frame and execution environment result; otherwise, execution may become unpredictable. |
Previous | Next | Contents | Index |
Copyright © Compaq Computer Corporation 1998. All rights reserved. Legal |
5973PRO_005.HTML
|