Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

OpenVMS Calling Standard


Previous Contents Index

3.5.2 Default Procedure Signature

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:

3.6 Procedure Call Chain

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:

  1. If PDSC$V_BASE_REG_IS_FP is set to 1 in the corresponding procedure descriptor, then set INVO_HANDLE to the contents of the FP register in that invocation.
    If PDSC$V_BASE_REG_IS_FP is set to 0, set INVO_HANDLE to the contents of the SP register in that invocation. (That is, start with the base register value for the frame.)
  2. Shift the INVO_HANDLE contents left one bit. Because this value is initially known to be octaword aligned (see Section 3.7.1), the result is a value whose 5 low-order bits are 0.
  3. If PDSC$V_KIND = PDSC$K_KIND_FP_STACK, perform a logical OR on the contents of INVO_HANDLE with the value 1F16, and then set INVO_HANDLE to the value that results.
    If PDSC$V_KIND = PDSC$K_KIND_FP_REGISTER, perform a logical OR on the contents of INVO_HANDLE with the contents of PDSC$B_SAVE_RA, and then set INVO_HANDLE to the value that results.

Note that a procedure invocation handle is not defined for a null frame procedure.

Note

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.

3.6.2.2 Invocation Context Block

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


Table 3-10 Contents of the Invocation Context Block
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$V_EXCEPTION_FRAME Bit 0. If set to 1, the invocation context corresponds to an exception frame.
LIBICB$V_AST_FRAME Bit 1. If set to 1, the invocation context corresponds to an asynchronous trap.
LIBICB$V_BOTTOM_OF_STACK Bit 2. If set to 1, the invocation context corresponds to a frame that has no predecessor.
LIBICB$V_BASE_FRAME Bit 3. If set to 1, the BASE_FRAME bit is set in the FLAGS field of the associated procedure descriptor.
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.

3.6.2.3 Getting a Procedure Invocation Context with a Routine

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:

  1. Build an invocation context block when given a program state (which contains a register set).
    For the current routine, an initial invocation context block can be obtained by calling the LIB$GET_CURR_INVO_CONTEXT routine (see Section 3.6.3.2).
  2. Repeatedly call the LIB$GET_PREV_INVO_CONTEXT routine (see Section 3.6.3.3) until the end of the chain has been reached (as signified by 0 being returned).

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.

Note

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.

3.6.3.2 LIB$GET_CURR_INVO_CONTEXT

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.

3.6.3.3 LIB$GET_PREV_INVO_CONTEXT

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.

3.6.3.4 LIB$GET_INVO_HANDLE

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.

3.6.3.5 LIB$GET_PREV_INVO_HANDLE

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.

3.6.3.6 LIB$PUT_INVO_REGISTERS

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).

Caution

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

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5973PRO_005.HTML