[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Calling Standard


Previous Contents Index

3.7.5 Sending Data

This section defines the OpenVMS Alpha calling standard requirements for mechanisms to send data and the order of argument evaluation.

3.7.5.1 Sending Mechanism

As previously defined, the argument-passing mechanisms allowed are immediate value, reference, and descriptor. Requirements for using these mechanisms follow:

  • By immediate value. An argument may be passed by immediate value only if the argument is one of the following:
    • One of the noncomplex scalar data types with a size known (at compile time) to be <= 64 bits
    • Either single or double precision complex
    • A record with a known size (at compile time)
    • A set, implemented as a bit vector, with a size known (at compile time) to be <= 64 bits

    No form of string or array data type may be passed by immediate value in a standard call.
    Unused high-order bits must be zero or sign extended, as appropriate depending on the date type, to fill all bits of each argument list item (as specified in Table 3-11).
    A single- or double- precision complex value is passed as two single or double precision floating-point values, respectively. Note that the argument count reflects that two argument positions are used rather than just one actual argument.
    A record value, which may be larger than 64 bits, is passed by immediate value as follows:
    • Allocate as many fully occupied argument item positions to the argument value as are needed to represent the argument.
    • The value of the unoccupied bits is undefined in a final, partially occupied argument item position, if any.
    • If an argument position is passed in one of the registers, it can only be passed in an integer register (never in a floating-point register).

    Other argument values that are larger than 64 bits can be passed by immediate value using nonstandard conventions, typically using a method similar to those for passing records. Thus, for example, a 26-byte string can be passed by value in four integer registers.
  • By reference. Nonparametric arguments (arguments for which associated information such as string size and array bounds are not required) can be passed by reference in a standard call. This includes extended precision floating and extended precision complex values.
  • By descriptor. Parametric arguments (arguments for which associated information such as string size and array bounds must be passed to the caller) are passed by a single descriptor in a standard call.

Note that extended floating values are not passed using the immediate value mechanism; rather, they are passed using the by reference mechanism. (However, when by value semantics is required, it may be necessary to make a copy of the actual parameter and pass a reference to that copy in order to avoid improper alias effects.)

Also note that when a record is passed by immediate value, the component types are not material to how the argument is aligned; the record will always be quadword aligned.

3.7.5.2 Order of Argument Evaluation

Because most high-level languages do not specify the order of evaluation (with respect to side effects) of arguments, those language processors can evaluate arguments in any convenient order. The choice of argument evaluation order and code generation strategy is constrained only by the definition of the particular language. Programs should not depend on the order of evaluation of arguments.

3.7.6 Receiving Data

When it cannot be determined at compile time whether a given in-register argument item is passed in a floating-point register or an integer register, the argument information register can be interpreted at run time to establish where the argument was passed. (See Section 3.6.1 for details.)

3.7.7 Returning Data

A standard function must return its function value by one of the following mechanisms:

  • Immediate value
  • Reference
  • Descriptor

These mechanisms are the only standard means available for returning function values, and they support the important language-independent data types. Functions that return values by any mechanism other than those specified here are nonstandard, language-specific functions.

3.7.7.1 Function Value Return by Immediate Value

This standard defines the following two types of function returns by immediate value:

  • Nonfloating function value return
  • Floating function value return

Nonfloating Function Value Return by Immediate Value

A function value is returned by immediate value in register R0 only if the type of function value is one of the following:

  • Nonfloating-point scalar data type with size known to be <= 64 bits
  • Record with size known to be <= 64 bits
  • Set, implemented as a bit vector, with size known to be <= 64 bits

No form of string or array can be returned by immediate value, and two separate 32-bit entities cannot be combined and returned in R0.

A function value of less than 64 bits returned in R0 must be zero extended or sign extended as appropriate, depending on the data type (see Table 3-11), to a full quadword.

Floating Function Value Return by Immediate Value

A function value is returned by immediate value in register F0 only if it is a noncomplex single- or double-precision floating-point value (F, D, G, S, or T).

A function value is returned by immediate value in registers F0 and F1 only if it is a complex single or double-precision floating-point value (complex F, D, G, S, or T).

Note that extended floating point and extended complex values are returned by reference as described next.

3.7.7.2 Function Value Return by Reference

A function value is returned by reference only if the function value satisfies both of the following criteria:

  • Its size is known to both the calling procedure and the called procedure, but the value cannot be returned by immediate value. (Because the function value requires more than 64 bits, the data type is a string or an array type.)
  • It can be returned in a contiguous region of storage.

The actual-argument list and the formal-argument list are shifted to the right by one argument item. The new, first argument item is reserved for the function value. This hidden first argument is included in the count and register usage information that is passed in the argument information register (see Section 3.6.1 for details).

The calling procedure must provide the required contiguous storage and pass the address of the storage as the first argument. This address must specify storage naturally aligned according to the data type of the function value.

The called function must write the function value to the storage described by the first argument.

The this Pointer

For C++, when the this pointer is passed as an implicit first parameter and a pointer to a return value buffer is also required, then the this pointer becomes the first parameter, the buffer pointer becomes the second parameter, and the remaining normal parameters are shifted two slots to make this possible.

3.7.7.3 Function Value Return by Descriptor

A function value is returned by descriptor only if the function value satisfies all of the following criteria:

  • It cannot be returned by immediate value. (Because the function value requires more than 64 bits, the data type is a string or an array type, and so on.)
  • Its size is not known to either the calling procedure or the called procedure.
  • It can be returned in a contiguous region of storage.

Noncontiguous function values are language specific and cannot be returned as a standard-conforming return value.

Records, noncontiguous arrays, and arrays with more than one dimension cannot be returned by descriptor in a standard call.

Both 32-bit and 64-bit descriptor forms can be used for function values returned by descriptor. See Chapter 7 for details of the descriptor forms.

The use of descriptors for function value return divides into three major cases with return values involving:

  • Dynamic text---Heap-managed strings of arbitrary and dynamically changeable length
  • Return objects created by the calling routine---Function values that are to be returned in an object allocated by and having attributes (bounds, lengths, and so on) specified by the calling routine
  • Return objects created by the called routine---Function values that are returned in an object allocated by and having attributes (bounds, lengths, and so on) specified by the called routine

For correct results to be obtained from this type of function return, the calling and called routines must agree by prior arrangement which of these three major cases applies, and whether 64-bit descriptor forms may be used.

The following paragraphs describe the specialized requirements for each major case:

Dynamic Text

For dynamic text return by descriptor, the calling routine passes a valid (completely initialized) dynamic string descriptor (DSC$B_CLASS = DSC$K_CLASS_D). The called routine must assign a value to the variable represented by this descriptor using the same rules that apply to a dynamic text descriptor used as an ordinary parameter.

Return Object Created by Calling Routine

For a return object created by the calling routine, the calling routine passes a descriptor in which all fields are completely loaded.

The called routine must supply a return value that satisfies that description. In particular, the called routine must truncate or pad the returned value to satisfy the requirements of the descriptor according to the semantics of the language in which the called routine is written.

The calling and called routines must agree by prior arrangement on the DSC$B_CLASS and DSC$B_DTYPE of descriptor to be used.

Return Object Created by Called Routine

For a return object created by the called routine, the calling and called routines must agree by prior arrangement on the DSC$B_CLASS and DSC$B_DTYPE of descriptor to be used. The calling routine passes a descriptor in which:

  • DSC$A_POINTER field is set to 0.
  • DSC$B_CLASS field is loaded.
  • DSC$B_DTYPE field is loaded.
  • DSC$B_DIMCT field is loaded and the DSC$B_AFLAGS field is set to 0 if the descriptor is an array descriptor.
  • All other fields are unpredictable.

If the passed descriptor is an array descriptor, it must contain space for bounds information to be returned even though the DSC$B_AFLAGS field is set to 0.

The called routine must return the function value using stack return conventions and load the DSC$A_POINTER field to point to the returned data. Other descriptor information, such as origin, bounds (if supplied), and DSC$B_AFLAGS fields must be filled in appropriately to correspond to the returned data.

An important implication of a call that uses this kind of value return is that the stack pointer normally is not restored to its value prior to the call as part of the return from the called procedure. The returned value typically (but not necessarily) is left by the called routine somewhere on the stack. For that reason, this mechanism is sometimes known as the stack return mechanism.

However, this type of return does not imply that the actual storage used by the called routine to hold the returned value must be at the address pointed to by the stack pointer; it need not even be on the stack. It could be in some read-only, static memory. (This latter case might arise when the returned value is constant or is obtained from some constant structure.) For this reason, the calling routine must not assume that the data described by the return descriptor is writable.

3.8 Data Allocation

This section describes the standard static data requirements that define the Alpha alignment of data structures, record formats, and record layout. These conventions help to ensure proper data compatibility with all OpenVMS Alpha and VAX languages.

3.8.1 Alignment

In the Alpha environment, memory references to data that is not naturally aligned can result in alignment faults, which can severely degrade the performance of all procedures that reference the unaligned data.

To avoid such performance degradation, all data values on Alpha systems should be naturally aligned. Table 3-12 contains information on data alignment.

Table 3-12 Natural Alignment Requirements
Data Type Alignment Starting Position
8-bit character string Byte boundary
16-bit integer Address that is a multiple of 2 (word alignment)
32-bit integer Address that is a multiple of 4 (longword alignment)
64-bit integer Address that is a multiple of 8 (quadword alignment)
F_floating
F_floating complex
Address that is a multiple of 4 (longword)
D_floating
D_floating complex
Address that is a multiple of 8 (quadword)
G_floating
G_floating complex
Address that is a multiple of 8 (quadword)
S_floating
S_floating complex
Address that is a multiple of 4 (longword alignment)
T_floating
T_floating complex
Address that is a multiple of 8 (quadword)
X_floating
X_floating complex
Address that is a multiple of 16 (octaword)

For aggregates such as strings, arrays, and records, the data type to be considered for purposes of alignment is not the aggregate itself, but rather the elements of which the aggregate is composed. The alignment requirement of an aggregate is that all elements of the aggregate be naturally aligned. For example, varying 8-bit character strings must start at addresses that are a multiple of at least 2 (word alignment) because of the 16-bit count at the beginning of the string; 32-bit integer arrays start at a longword boundary, irrespective of the extent of the array.

The rules for passing a record in an argument that is passed by immediate value (see Section 3.7.5.1) always provide quadword alignment of the record value independent of the normal alignment requirement of the record. If deemed appropriate by an implementation, normal alignment can be established within the called procedure by making a copy of the record argument at a suitably aligned location.

3.8.2 Record Layout Conventions

The OpenVMS Alpha calling standard rules for record layout are designed to provide good run-time performance on all implementations of the Alpha architecture and to provide the required level of compatibility with conventional VAX operating environments.

Therefore, this standard defines two record layout conventions:

  • Those optimized for optimal access characteristics (referred to as aligned record layouts)
  • Those compatible with conventions that are traditionally used by VAX languages (referred to as VAX compatible record layouts)

Note

Although compiler implementers must make appropriate business decisions, Hewlett-Packard strongly recommends that all Alpha high-level language compilers should support both record layouts.

Only these two record layouts may be used across standard interfaces or between languages. Languages can support other language-specific record layout conventions, but such layouts are nonstandard.

The aligned record layout conventions should be used unless interchange is required with conventional VAX applications that use the OpenVMS VAX compatible record layouts.

3.8.2.1 Aligned Record Layout

The aligned record layout conventions ensure that:

  • All components of a record or subrecord are naturally aligned.
  • Layout and alignment of record elements and subrecords are independent of any record or subrecord in which they are embedded.
  • Layout and alignment of a subrecord is the same as if it were a top-level record.
  • Declaration in high-level languages of standard records for interlanguage use is straightforward and obvious, and meets the requirements for source-level compatibility between Alpha and VAX languages.

The aligned record layout is defined by the following conventions:

  • The components of a record must be laid out in memory corresponding to the lexical order of their appearance in the high-level language declaration of the record.
  • The first bit of a record or subrecord must be directly addressable (byte aligned).
  • Records and subrecords must be aligned according to the largest natural alignment requirements of the contained elements and subrecords.
  • Bit fields (packed subranges of integers) are characterized by an underlying integer type that is a byte, word, longword, or quadword in size together with an allocation size in bits. A bit field is allocated at the next available bit boundary, provided that the resulting allocation does not cross an alignment boundary of the underlying type. Otherwise, the field is allocated at the next byte boundary that is aligned as required for the underlying type. (In the later case, the space skipped over is left permanently not allocated.) In addition, if necessary, the alignment of the record as a whole is increased to that of the underlying integer type.
  • Unaligned bit strings, unaligned bit arrays, and elements of unaligned bit arrays must start at the next available bit in the record. No fill is ever supplied preceding an unaligned bit string, unaligned bit array, or unaligned bit array element.
  • All other components of a record must start at the next available naturally aligned address for the data type.
  • The length of a record must be a multiple of its alignment. (This includes the case when a record is a component of another record.)
  • Strings and arrays must be aligned according to the natural alignment requirements of the data type of which the string or array is composed.
  • The length of an array element is a multiple of its alignment, even if this leaves unused space at its end. The length of the whole array is the sum of the lengths of its elements.

3.8.2.2 OpenVMS VAX Compatible Record Layout

The OpenVMS VAX compatible record layout is defined by the following conventions:

  • The components of a record must be laid out in memory corresponding to the lexical order of their appearance in the high-level language declaration of the record.
  • Unaligned bit strings, unaligned bit arrays, and elements of unaligned bit arrays must start at the next available bit in the record. No fill is ever supplied preceding an unaligned bit string, unaligned bit array, or unaligned bit array element.
  • All other components of a record must start at the next available byte in the record. Any unused bits following the last-used bit in the last-used byte of each component must be filled out to the next byte boundary so that any following data starts on a byte boundary.
  • Subrecords must be aligned according to the largest alignment of the contained elements and subrecords. A subrecord always starts at the next available byte unless it consists entirely of unaligned bit data and it immediately follows an unaligned bit string, unaligned bit array, or a subrecord consisting entirely of unaligned bit data.
  • Records must be aligned on byte boundaries.

3.9 Multithreaded Execution Environments

This section defines the conventions to support the execution of multiple threads in a multilanguage Alpha environment. Specifically defined is how compiled code must perform stack limit checking. While this standard is compatible with a multithreaded execution environment, the detailed mechanisms, data structures, and procedures that support this capability are not specified in this manual.

For a multithread environment, the following characteristics are assumed:

  • There can be one or more threads executing within a single process.
  • The state of a thread is represented in a thread environment block (TEB).
  • The TEB of a thread contains information that determines a stack limit below which the stack pointer must not be decremented by the executing code (except for code that implements the multithread mechanism itself).
  • Exception handling is fully reentrant and multithreaded.

3.9.1 Stack Limit Checking

A program that is otherwise correct can fail because of stack overflow. Stack overflow occurs when extension of the stack (by decrementing the stack pointer, SP) allocates addresses not currently reserved for the current thread's stack.

Detection of a stack overflow situation is necessary because a thread, attempting to write into stack storage, could modify data allocated in that memory for some other purpose. This would most likely produce unpredictable and undesirable results or irreproducible application failures.

The requirements for procedures that can execute in a multithread environment include checking for stack overflow. This section defines the conventions for stack limit checking in a multithreaded program environment.

In the following sections, the term new stack region refers to the region of the stack from one less than the old value of SP to the new value of the SP.

3.9.1.1 Stack Guard Region

In a multithread environment, the memory beyond the limit of each thread's stack is protected by contiguous guard pages, which form the stack's guard region.


Previous Next Contents Index