[OpenVMS documentation]
[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
Updated: 11 December 1998

OpenVMS Calling Standard


Previous Contents Index

3.4.3 Stack Frame Format

The stack of a stack frame procedure consists of a fixed part (the size of which is known at compile time) and an optional variable part. There are two basic types of stack frames:

Even though the exact contents of a stack frame are determined by the compiler, all stack frames have common characteristics.

Various combinations of PDSC$V_BASE_REG_IS_FP and PDSC$L_SIZE can be used as follows:

3.4.3.1 Fixed-Size Stack Frame

Figure 3-2 illustrates the format of the stack frame for a procedure with a fixed amount of stack that uses the SP register as the stack base pointer (when PDSC$V_BASE_REG_IS_FP is 0). In this case, R29 (FP) typically contains the address of the procedure descriptor for the current procedure (see Section 3.6.1).

Some parts of the stack frame are optional and occur only as required by the particular procedure. As shown in the figure, the field names within brackets are optional fields. Use of the arguments passed in memory field appending the end of the descriptor is described in Sections 3.4.3.3 and 3.8.2.

For information describing the fixed temporary locations and register save area, see Sections 3.4.3.3 and 3.4.3.4.

Figure 3-2 Fixed-Size Stack Frame Format


3.4.3.2 Variable-Size Stack Frame

Figure 3-3 illustrates the format of the stack frame for procedures with a varying amount of stack when PDSC$V_BASE_REG_IS_FP is 1. In this case, R29 (FP) contains the address that points to the base of the stack frame on the stack. This frame-base quadword location contains the address of the current procedure's descriptor.

Figure 3-3 Variable-Size Stack Frame Format


Some parts of the stack frame are optional and occur only as required by the particular procedure. In Figure 3-3, field names within brackets are optional fields. Use of the arguments passed in memory field appending the end of the descriptor is described in Sections 3.4.3.3 and 3.8.2.

For more information describing the fixed temporary locations and register save area, see Sections 3.4.3.3 and 3.4.3.4.

A compiler can use the stack temporary area pointed to by the SP base register for fixed local variables, such as constant-sized data items and program state, as well as for dynamically sized local variables. The stack temporary area may also be used for dynamically sized items with a limited lifetime, for example, a dynamically sized function result or string concatenation that cannot be stored directly in a target variable. When a procedure uses this area, the compiler must keep track of its base and reset SP to the base to reclaim storage used by temporaries.

3.4.3.3 Fixed Temporary Locations for All Stack Frames

The fixed temporary locations are optional sections of any stack frame that contain language-specific locations required by the procedure context of some high-level languages. This may include, for example, register spill area, language-specific exception-handling context (such as language-dynamic exception-handling information), fixed temporaries, and so on.

The argument home area (if allocated by the compiler) can be found with the PDSC$L_SIZE offset in the last fixed temporary locations at the end of the stack frame. It is adjacent to the arguments passed in memory area to expedite the use of arguments passed (without copying). The argument home area is a region of memory used by the called procedure for the purpose of assembling in contiguous memory the arguments passed in registers, adjacent to the arguments passed in memory, so all arguments can be addressed as a contiguous array. This area can also be used to store arguments passed in registers if an address for such an argument must be generated. Generally, 6 * 8 bytes of stack storage is allocated by the called procedure for this purpose.

If a procedure needs to reference its arguments as a longword array or construct a structure that looks like an in-memory longword argument list, then it might allocate enough longwords in this area to hold all of the argument list and, optionally, an argument count. In that case, argument items passed in memory must be copied to this longword array.

The high-address end of the stack frame is defined by the value stored in PDSC$L_SIZE plus the contents of SP or FP, as indicated by PDSC$V_BASE_REG_IS_FP. The high-address end is used to determine the value of SP for the predecessor procedure in the calling chain.

3.4.3.4 Register Save Area for All Stack Frames

The register save area is a set of consecutive quadwords in which registers saved and restored by the current procedure are stored (see Figure 3-4). The register save area begins at the location pointed to by the offset PDSC$W_RSA_OFFSET from the frame base register (SP or FP as indicated by PDSC$V_BASE_REG_IS_FP), which must yield a quadword-aligned address. The set of registers saved in this area contain the return address followed by the registers specified in the procedure descriptor by PDSC$L_IREG_MASK and PDSC$L_FREG_MASK.

All registers saved in the register save area (other than the saved return address) must have the corresponding bit set in the appropriate procedure descriptor register save mask even if the register is not a member of the set of registers required to be saved across a standard call. Failure to do so will prevent the correct calculation of offsets within the save area.

Figure 3-4 illustrates the fields in the register save area (field names within brackets are optional fields). Quadword RSA$Q_SAVED_RETURN is the first field in the save area and it contains the contents of the return address register. The optional fields vary in size (8-byte increments) to preserve, as required, the contents of the integer and floating-point hardware registers used in the procedure.

Figure 3-4 Register Save Area (RSA) Layout


The algorithm for packing saved registers in the quadword-aligned register save area is:

  1. The return address is saved at the lowest address of the register save area (offset 0).
  2. All saved integer registers (as indicated by the corresponding bit in PDSC$L_IREG_MASK being set to 1) are stored, in register-number order, in consecutive quadwords, beginning at offset 8 of the register save area.
  3. All saved floating-point registers (as indicated by the corresponding bit in PDSC$L_FREG_MASK being set to 1) are stored, in register-number order, in consecutive quadwords following the saved integer registers.

    Note

    Floating-point registers saved in the register save area are stored as a 64-bit exact image of the register (for example, no reordering of bits is done on the way to or from memory). Compilers must use an STT instruction to store the register regardless of floating-point type.

The preserved register set must always include R29 (FP), since it will always be used.

If the return address register is not to be preserved (as is the case for a standard call), then it must be stored at offset 0 in the register save area and the corresponding bit in the register save mask must not be set.

However, if a nonstandard call is made that requires the return address register to be saved and restored, then it must be stored in both the location at offset 0 in the register save area and at the appropriate location within the variable part of the save area. In addition, the appropriate bit of PDSC$L_IREG_MASK must be set to 1.

The example register save area shown in Figure 3-5 illustrates the register packing when registers R10, R11, R15, FP, F2, and F3 are being saved for a procedure called with a standard call.

Figure 3-5 Register Save Area (RSA) Example


3.4.4 Register Frame Procedure

A register frame procedure does not maintain a call frame on the stack and must, therefore, save its caller's context in registers. This type of procedure is sometimes referred to as a lightweight procedure, referring to the expedient way of saving the call context.

Such a procedure cannot save and restore nonscratch registers. Because a procedure without a stack frame must use scratch registers to maintain the caller's context, such a procedure cannot make a standard call to any other procedure.

A procedure with a register frame can have an exception handler and can handle exceptions in the normal way. Such a procedure can also allocate local stack storage in the normal way, although it might not necessarily do so.

Note

Lightweight procedures have more freedom than might be apparent. By using appropriate agreements with callers of the lightweight procedure, with procedures that the lightweight procedure calls, and by the use of unwind handlers, a lightweight procedure can modify nonscratch registers and can call other procedures.

Such agreements may be by convention (as in the case of language-support routines in the RTL) or by interprocedural analysis. However, calls employing such agreements are not standard calls and might not be fully supported by a debugger; for example, the debugger might not be able to find the contents of the preserved registers.

Since such agreements must be permanent (for upwards compatibility of object code), lightweight procedures should in general follow the normal restrictions.

3.4.5 Procedure Descriptor for Procedures with a Register Frame

A register frame procedure descriptor built by a compiler provides information about a procedure with a register frame. The minimum size of the descriptor is 24 bytes (defined by PDSC$K_MIN_REGISTER_SIZE). An optional PDSC extension in 8-byte increments supports exception-handling requirements.

The fields defined in the register frame procedure descriptor are illustrated in Figure 3-6 and described in Table 3-4.

Figure 3-6 Register Frame Procedure Descriptor (PDSC)


Table 3-4 Contents of Register Frame Procedure Descriptor (PDSC)
Field Name Contents
PDSC$W_FLAGS The PDSC descriptor flag bits <15:0> are defined as follows:
PDSC$V_KIND A 4-bit field <3:0> that identifies the type of procedure descriptor. For a procedure with a register frame, this field must specify a value 10 (defined by constant PDSC$K_KIND_FP_REGISTER).
PDSC$V_HANDLER_VALID If set to 1, this descriptor has an extension for the stack handler (PDSC$Q_REG_HANDLER) information.
PDSC$V_HANDLER_REINVOKABLE If set to 1, the handler can be reinvoked, allowing an occurrence of another exception while the handler is already active. If this bit is set to 0, the exception handler cannot be reinvoked. This bit must be 0 when PDSC$V_HANDLER_VALID is 0.
PDSC$V_HANDLER_DATA_VALID If set to 1, the HANDLER_VALID bit must be 1 and the PDSC extension STACK_HANDLER_DATA field contains valid data for the exception handler, and the address of PDSC$Q_STACK_HANDLER_DATA will be passed to the exception handler as defined in Section 6.2.
PDSC$V_BASE_REG_IS_FP If this bit is set to 0, the SP is the base register to which PDSC$L_SIZE is added during an unwind. A fixed amount of storage is allocated in the procedure entry sequence, and SP is modified by this procedure only in the entry and exit code sequence. In this case, FP typically contains the address of the procedure descriptor for the procedure. Note that a procedure that sets this bit to 0 cannot make standard calls.

If this bit is set to 1, FP is the base address and the procedure has a fixed amount of stack storage specified by PDSC$L_SIZE. A variable amount of stack storage can be allocated by modifying SP in the entry and exit code of this procedure.

PDSC$V_REI_RETURN If set to 1, the procedure expects the stack at entry to be set, so an REI instruction correctly returns from the procedure. Also, if set, the contents of the PDSC$B_SAVE_RA field are unpredictable and the return address is found on the stack.
Bit 9 Must be 0 (reserved).
PDSC$V_BASE_FRAME For compiled code, this bit must be 0. If set to 1, indicates the logical base frame of a stack that precedes all frames corresponding to user code. The interpretation and use of this frame and whether there are any predecessor frames is system software defined (and subject to change).
PDSC$V_TARGET_INVO If set to 1, the exception handler for this procedure is invoked when this procedure is the target invocation of an unwind. Note that a procedure is the target invocation of an unwind if it is the procedure in which execution resumes following completion of the unwind. For more information, see Chapter 6.

If set to 0, the exception handler for this procedure is not invoked. Note that when PDSC$V_HANDLER_VALID is 0, this bit must be 0.

PDSC$V_NATIVE For compiled code, this bit must be set to 1.
PDSC$V_NO_JACKET For compiled code, this bit must be set to 1.
PDSC$V_TIE_FRAME For compiled code, this bit must be 0. Reserved for use by system software.
Bit 15 Must be 0 (reserved).
PDSC$B_SAVE_FP Specifies the number of the register that contains the saved value of the frame pointer (FP) register.

In a standard procedure, this field must specify a scratch register so as not to violate the rules for procedure entry code as specified in Section 3.7.5.

PDSC$B_SAVE_RA Specifies the number of the register that contains the return address. If this procedure uses standard call conventions and does not modify R26, then this field can specify R26.

In a standard procedure, this field must specify a scratch register so as not to violate the rules for procedure entry code as specified in Section 3.7.5.

PDSC$V_FUNC_RETURN A 4-bit field <11:8> that describes which registers are used for the function value return (if there is one) and what format is used for those registers.

Table 3-7 lists and describes the possible encoded values of PDSC$V_FUNC_RETURN.

PDSC$V_EXCEPTION_MODE A 3-bit field <14:12> that encodes the caller's desired exception-reporting behavior when calling certain mathematically oriented library routines. The possible values for this field are defined as follows:
Value Name Meaning
0 PDSC$K_EXCEPTION_MODE_SIGNAL Raise exceptions for all error conditions except for underflows producing a 0 result. This is the default mode.
1 PDSC$K_EXCEPTION_MODE_SIGNAL_ALL Raise exceptions for all error conditions (including underflows).
2 PDSC$K_EXCEPTION_MODE_SIGNAL_SILENT Raise no exceptions. Create only finite values (no infinities, denormals, or NaNs). In this mode, either the function result or the C language errno variable must be examined for any error indication.
3 PDSC$K_EXCEPTION_MODE_FULL_IEEE Raise no exceptions except as controlled by separate IEEE exception enable bits. Create infinities, denormals, or NaN values according to the IEEE floating-point standard.
4 PDSC$K_EXCEPTION_MODE_CALLER Perform the exception-mode behavior specified by this procedure's caller.
PDSC$W_SIGNATURE_OFFSET A 16-bit signed byte offset from the start of the procedure descriptor. This offset designates the start of the procedure signature block (if any). A 0 in this field indicates no signature information is present. Note that in a bound procedure descriptor (as described in Section 3.7.4), signature information might be present in the related procedure descriptor. A 1 in this field indicates a standard default signature. An offset value of 1 is not otherwise a valid offset because both procedure descriptors and signature blocks must be quadword aligned.
PDSC$Q_ENTRY Absolute address of the first instruction of the entry code sequence for the procedure.
PDSC$L_SIZE Unsigned size in bytes of the fixed portion of the stack frame for this procedure. The size must be a multiple of 16 bytes to maintain the minimum stack alignment required by the Alpha hardware architecture and stack alignment during a call (defined in Section 3.7.1).
PDSC$W_ENTRY_LENGTH Unsigned offset in bytes from the entry point to the first instruction in the procedure code segment following the procedure prologue (that is, following the instruction that updates FP to establish this procedure as the current procedure).
PDSC$Q_REG_HANDLER Absolute address to the procedure descriptor for a run-time static exception-handling procedure. This part of the procedure descriptor is optional. It must be supplied if either PDSC$V_HANDLER_VALID is 1 or PDSC$V_HANDLER_DATA_VALID is 1 (which requires that PDSC$V_HANDLER_VALID be 1).

If PDSC$V_HANDLER_VALID is 0, then the contents or existence of PDSC$Q_REG_HANDLER is unpredictable.

PDSC$Q_REG_HANDLER_DATA Data (quadword) for the exception handler. This is an optional quadword and needs to be supplied only if PDSC$V_HANDLER_DATA_VALID is 1.

If PDSC$V_HANDLER_DATA_VALID is 0, then the contents or existence of PDSC$Q_REG_HANDLER_DATA is unpredictable.

3.4.6 Null Frame Procedures

A procedure may conform to this standard even if it does not establish its own context if, in all circumstances, invocations of that procedure do not need to be visible or debuggable. This is termed executing in the context of the caller and is similar in concept to a conventional VAX JSB procedure. For the purposes of stack tracing or unwinding, such a procedure is never considered to be current.

For example, if a procedure does not establish an exception handler or does not save and restore registers, and does not extend the stack, then that procedure might not need to establish a context. Likewise, if that procedure does extend the stack, it still might not need to establish a context if the immediate caller either cannot be the target of an unwind or is prepared to reset the stack if it is the target of an unwind.

The circumstances under which procedures can run in the context of the caller are complex and are not fully specified by this standard.

As with the other procedure types previously described, the choice of whether to establish a context belongs to the called procedure. By defining a null procedure descriptor format, the same invocation code sequence can be used by the caller for all procedure types.


Previous Next Contents Index

[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
[OpenVMS documentation]

Copyright © Compaq Computer Corporation 1998. All rights reserved.

Legal
5973PRO_003.HTML