![]() |
Software > OpenVMS Systems > Documentation > 82final > 5973 ![]() HP OpenVMS Systems Documentation |
![]() |
HP OpenVMS Calling Standard
3.4.3 Stack Frame FormatThe 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 FrameFigure 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.5.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.7.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 FrameFigure 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.7.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 FramesThe 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 for this purpose by the called procedure. 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 FramesThe 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:
The preserved register set must always include R29 (FP), because 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 ProcedureA 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.
3.4.5 Procedure Descriptor for Procedures with a Register FrameA 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) ![]()
3.4.6 Null Frame ProceduresA 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.
|