Document revision date: 30 March 2001

## OpenVMS Calling Standard

Previous | Contents | Index

#### 3.10.1.3 Methods for Stack Limit Checking

Since accessible memory may be available at addresses lower than those occupied by the guard region, compilers must generate code that never extends the stack past the guard pages into accessible memory that is not allocated to the thread's stack.

A general strategy is to access each page of memory down to and possibly including the page corresponding to the intended new value for the SP. If the stack is to be extended by an amount larger than the size of a memory page, then a series of accesses is required that works from higher to lower addressed pages. If any access results in a memory access violation, then the code has made an invalid attempt to extend the stack of the current thread.

Note An access can be performed by using either a load or a store operation; however, be sure to use an instruction that is guaranteed to make an access to memory. For example, do not use an `LDQ R31,*` instruction, because the Alpha architecture does not allow any memory access, even a read access, whose result is discarded because of the R31 destination.

This standard defines two methods for stack limit checking: implicit and explicit.

Implicit Stack Limit Checking

The following are two mutually exclusive strategies for implicit stack limit checking:

- If the lowest addressed byte of the new stack region is guaranteed to be accessed prior to any further stack extension, then the stack can be extended by an increment that is equal in size to the guard region (without any further accesses).
- If some byte (not necessarily the lowest) of the new stack region is guaranteed to be accessed prior to any further stack extension, then the stack can be extended by an increment that is equal in size to one-half the guard region (without any further accesses).

The stack frame format (see Section 3.4.3) and entry code rules (see Section 3.7.5) generally do not ensure access to the lowest address of a new stack region without introducing an extra access solely for that purpose. Consequently, this standard uses the second strategy. While the amount of implicit stack extension that can be achieved is smaller, the check is achieved at no additional cost.

This standard requires that the minimum guard region size is 8192 bytes, the size of the smallest memory protection granularity allowed by the Alpha architecture.

Therefore, if the stack is being extended by an amount less than or equal to 4096 and a reserve region is not required, then explicit stack limit checking is not required.

However, because asynchronous interrupts and calls to other procedures may also cause stack extension without explicit stack limit checking, stack extension with implicit limit checking must adhere to a strict set of conventions as follows:

1. Explicit stack limit checking must be performed unless the amount by which the SP is decremented is known to be less than or equal to 4096 and a reserve region is not required.
2. Some byte in the new stack region must be accessed before the SP can be decremented for a subsequent stack extension.
   This access can be performed either before or after the SP is decremented for this stack extension, but it must be done before the SP can be decremented again.
3. No standard procedure call can be made before some byte in the new stack region is accessed.
4. The system exception dispatcher ensures that the lowest addressed byte in the new stack region is accessed if any kind of asynchronous interrupt occurs after the SP is decremented, but before the access in the new stack region occurs.

These conventions ensure that the stack pointer is not decremented so that it points to accessible storage beyond the stack limit without this error being detected (either by the guard region being accessed by the thread or by an explicit stack limit check failure).

As a matter of practice, the system can provide multiple guard pages in the guard region. When a stack overflow is detected as a result of access to the guard region, one or more guard pages can be unprotected for use by the exception-handling facility, and one or more guard pages can remain protected to provide implicit stack limit checking during exception processing. However, the size of the guard region and the number of guard pages is system defined and is not defined by this standard.

Explicit Stack Limit Checking

If the stack is being extended by an amount of unknown size or by a known size greater than the maximum implicit check size (4096), then a code sequence that follows the rules for implicit stack limit checking can be executed in a loop to access the new stack region incrementally in segments lesser than or equal to the minimum page size (8192 bytes). At least one access must occur in each such segment. The first access must occur between SP and SP - 4096 because, in the absence of more specific information, the previous guaranteed access relative to the current stack pointer may be as much as 4096 bytes greater than the current stack pointer address. The last access must be within 4096 bytes of the intended new value of the stack pointer. These accesses must occur in order, starting with the highest addressed segment and working toward the lowest addressed segment.

Note A simple algorithm that is consistent with this requirement (but achieves up to twice the minimum number of accesses) is to perform a sequence of accesses in a loop starting with the previous value of SP, decrementing by the minimum no-check extension size (4096) to, but not including, the first value that is less than the new value for the stack pointer.

The stack must not be extended incrementally in procedure prologues. A procedure prologue that needs to extend the stack by an amount of unknown size or known size greater than the minimum implicit check size must test new stack segments as just described in a loop that does not modify SP, and then update the stack with one instruction that copies the new stack pointer value into the SP.

Note An explicit stack limit check can be performed either by inline code that is part of a prologue or by a run-time support routine that is tailored to be called from a procedure prologue.

Stack Reserve Region Checking

The size of the reserve region must be included in the increment size used for stack limit checks, after which it is not included in the amount by which the stack is actually extended. (Depending on the size of the reserve region, this may partially or even completely eliminate the ability to use implicit stack limit checking.)

#### 3.10.1.4 Stack Overflow Handling

If a stack overflow is detected, one of the following results:

- Exception SS$_ACCVIO may be raised.
- The system may transparently extend the thread's stack, reset the TEB stack limit value appropriately, and continue execution of the thread.

Note that if a transparent stack extension is performed, a stack overflow that occurs in a called procedure might cause the stack to be extended. Therefore, the TEB stack limit value must be considered volatile and potentially modified by external procedure calls and by handling of exceptions.

## Chapter 4
OpenVMS Argument Data Types

This chapter defines the argument-passing data types that are used to call a procedure for both VAX and Alpha environments. All features defined here apply to both OpenVMS VAX and OpenVMS Alpha systems unless otherwise noted.

Each data type implemented for a high-level language uses one of the following classes of VAX data types for procedure parameters and elements of file records:

- Atomic
- String
- Miscellaneous

When existing data types fail to satisfy the semantics of a language, new data types, including certain language-specific ones, are added to this standard. These data types can generally be passed by immediate value (if 32 bits or less), by reference, or by descriptor.

Each data type code presented in this chapter indicates a unique data format. Use these encodings whenever you need to identify data types to achieve greater commonality across user software.

The encoding given in Sections 4.1 and 4.2 can help you to identify data types, such as in a descriptor. However, in addition to their use in descriptors, these data type codes are also useful for identifying VAX and Alpha data types in areas outside the scope of the calling standard. Therefore, each data-type code indicates a unique data format independent of its use in descriptors.

Some data types are composed of a recordlike structure consisting of two or more elementary data types. For example, the F_floating complex (FC) data type is made up of two F_floating data types, and the varying character string (VT) data type is made up of a word (unsigned, WU) data type followed by a character string (T) data type.

Unless stated otherwise, all data types in this standard represent signed quantities. The unsigned quantities do not allocate space for the sign; all bit or character positions are used for significant data.

## 4.1 Atomic Data Types

Table 4-1 shows how atomic data types are defined and encoded for VAX and Alpha environments.

Table 4-1 Atomic Data Types
Symbol | Code | Name/Description
--- | --- | ---
DSC$K_DTYPE_Z | 0 | Unspecified The calling program has specified no data type. The default argument for the called procedure should be the correct type.
DSC$K_DTYPE_BU | 2 | Byte (unsigned) 8-bit unsigned quantity.
DSC$K_DTYPE_WU | 3 | Word (unsigned) 16-bit unsigned quantity.
DSC$K_DTYPE_LU | 4 | Longword (unsigned) 32-bit unsigned quantity.
DSC$K_DTYPE_QU | 5 | Quadword (unsigned) 64-bit unsigned quantity.
DSC$K_DTYPE_OU | 25 | Octaword (unsigned) 128-bit unsigned quantity.
DSC$K_DTYPE_B | 6 | Byte integer (signed) 8-bit signed two's complement integer.
DSC$K_DTYPE_W | 7 | Word integer (signed) 16-bit signed two's complement integer.
DSC$K_DTYPE_L | 8 | Longword integer (signed) 32-bit signed two's complement integer.
DSC$K_DTYPE_Q | 9 | Quadword integer (signed) 64-bit signed two's complement integer.
DSC$K_DTYPE_O | 26 | Octaword integer (signed) 128-bit signed two's complement integer.
DSC$K_DTYPE_F | 10 | F_floating 32-bit F_floating quantity representing a single-precision number.
DSC$K_DTYPE_D 1 | 11 | D_floating 64-bit D_floating quantity representing a double-precision number.
DSC$K_DTYPE_G | 27 | G_floating 64-bit G_floating quantity representing a double-precision number.
+DSC$K_DTYPE_H 2 | 28 | H_floating 128-bit H_floating quantity representing a quadruple-precision number.
DSC$K_DTYPE_FC | 12 | F_floating complex Ordered pair of F_floating quantities representing a single-precision complex number. The lower addressed quantity is the real part; the higher addressed quantity is the imaginary part.
DSC$K_DTYPE_DC | 13 | D_floating complex Ordered pair of D_floating quantities representing a double-precision complex number. The lower addressed quantity is the real part; the higher addressed quantity is the imaginary part.
DSC$K_DTYPE_GC | 29 | G_floating complex Ordered pair of G_floating quantities representing a double-precision complex number. The lower addressed quantity is the real part; the higher addressed quantity is the imaginary part.
+DSC$K_DTYPE_HC 2 | 30 | H_floating complex Ordered pair of H_floating quantities representing a quadruple-precision complex number. The lower addressed quantity is the real part; the higher addressed quantity is the imaginary part.
++DSC$K_DTYPE_FS | 52 | S_floating 32-bit IEEE S_floating quantity representing a single-precision number.
++DSC$K_DTYPE_FT | 53 | T_floating 64-bit IEEE T_floating quantity representing a double-precision number.
++DSC$K_DTYPE_FSC | 54 | S_floating complex Ordered pair of S_floating quantities representing a single-precision complex number. The lower addressed quantity is the real part; the higher addressed quantity is the imaginary part.
++DSC$K_DTYPE_FTC | 55 | T_floating complex Ordered pair of T_floating quantities representing a single-precision complex number. The lower addressed quantity is the real part; the higher addressed quantity is the imaginary part.
++DSC$K_DTYPE_FX | 57 | X_floating 128-bit IEEE X_floating quantity representing an extended-precision number.
++DSC$K_DTYPE_FXC | 58 | X_floating complex Ordered pair of X_floating quantities representing an extended-precision complex number. The lower addressed quantity is the real part; the higher addressed quantity is the imaginary part.

1While the calling standard supports the manipulation of D_floating and D_floating complex data, compiled code support will invoke conversion from D_floating to G_floating as needed for Alpha arithmetic operations, and conversion of G_floating intermediate results back to D_floating when needed for stores to memory or parameter passing. This allows D_floating data to be used in Alpha arithmetic operations without required source changes but with results limited to G_floating precision.
2H_floating data is not supported for general use on OpenVMS Alpha systems. However, conversion routines are supplied to allow users to convert existing H_floating data to other storage representations.
+VAX specific.
++Alpha specific.

## 4.2 String Data Types

String data types are ordinarily described by a string descriptor. Table 4-2 shows how the string data types are defined and encoded for OpenVMS VAX and OpenVMS Alpha environments.

Table 4-2 String Data Types
Symbol | Code | Name/Description
--- | --- | ---
DSC$K_DTYPE_T | 14 | Character string A single 8-bit character (atomic data type) or a sequence of 0 to 2 16 - 1 8-bit characters (string data type).
DSC$K_DTYPE_VT | 37 | Varying character string A 16-bit unsigned count of the current number of 8-bit characters in the following string, followed by a string of 0 to 2 16 - 1 8-bit characters (see Section 4.5 for details). When this data type is used with descriptors, it can only be used with the varying string and varying string array descriptors, because the length field is interpreted differently from the other 8-bit string data types. (See Sections 4.5, 5.8, and 5.9 for further discussion.)
DSC$K_DTYPE_NU | 15 | Numeric string, unsigned
DSC$K_DTYPE_NL | 16 | Numeric string, left separate sign
DSC$K_DTYPE_NLO | 17 | Numeric string, left overpunched sign
DSC$K_DTYPE_NR | 18 | Numeric string, right separate sign
DSC$K_DTYPE_NRO | 19 | Numeric string, right overpunched sign
DSC$K_DTYPE_NZ | 20 | Numeric string, zoned sign
DSC$K_DTYPE_P | 21 | Packed-decimal string
DSC$K_DTYPE_V | 1 | Aligned bit string A string of 0 to 2 16 - 1 contiguous bits. The first bit is bit <0> of the first byte, and the last bit is any bit in the last byte. Remaining bits in the last byte must be 0 on read and are cleared on write. Unlike the unaligned bit string (VU) data type, when the aligned bit string (V) data type is used in array descriptors, the ARSIZE field is in units of bytes, not bits, because allocation is a multiple of 8 bits.
DSC$K_DTYPE_VU | 34 | Unaligned bit string The data is 0 to 2 16 - 1 contiguous bits located arbitrarily with respect to byte boundaries. See also aligned bit string (V) data type. Because additional information is required to specify the bit position of the first bit, this data type can be used only with the unaligned bit string and unaligned bit array descriptors (see Sections 5.10 and 5.11).

## 4.3 Miscellaneous Data Types

Table 4-3 shows how miscellaneous data types are defined and encoded for the OpenVMS VAX and OpenVMS Alpha environments.

Table 4-3 Miscellaneous Data Types
Symbol | Code | Name/Description
--- | --- | ---
+DSC$K_DTYPE_ZI | 22 | Sequence of instructions
+DSC$K_DTYPE_ZEM | 23 | Procedure entry mask
DSC$K_DTYPE_DSC | 24 | Descriptor This data type allows a descriptor to be a data type; thus, levels of descriptors are allowed.
+DSC$K_DTYPE_BPV | 32 | Bound procedure value (for VAX environment only) A two-longword entity in which the first longword contains the address of a procedure entry mask and the second longword is the environment value. The environment value is determined in a language-specific manner when the original bound procedure value is generated. When the bound procedure is called, the calling program loads the second longword into R1. When the environment value is not needed, this data type can be passed using the immediate value mechanism. In this case, the argument list entry contains the address of the procedure entry mask and the second longword is omitted.
DSC$K_DTYPE_BLV | 33 | Bound label value A two-longword entity in which the first longword contains the address of an instruction and the second longword is the language-specific environment value. The environment value is determined in a language-specific manner when the original bound label value is generated.
DSC$K_DTYPE_ADT | 35 | Absolute date and time A 64-bit unsigned, scaled, binary integer representing a date and time in 100-nanosecond units offset from the OpenVMS operating system base date and time, which is 00:00 o'clock, November 17, 1858 (the Smithsonian base date and time for astronomical calendars). The value 0 indicates that the date and time have not been specified, so a default value or distinctive print format can be used. Note that the ADT data type is the same as the OpenVMS date format for positive values only.

+VAX specific.

Previous | Next | Contents | Index

| privacy and legal statement |
5973PRO_009.HTML