HP OpenVMS Systems Documentation
HP OpenVMS Calling Standard
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.
As previously defined, the argument-passing mechanisms allowed are immediate value, reference, and descriptor. Requirements for using these mechanisms follow:
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.
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.
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.)
A standard function must return its function value by one of the following mechanisms:
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.
This standard defines the following two types of function returns 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:
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.
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.
A function value is returned by reference only if the function value satisfies both of the following criteria:
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.
For C++, when the
pointer is passed as an implicit first parameter and a pointer to a
return value buffer is also required, then the
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.
A function value is returned by descriptor only if the function value satisfies all of the following criteria:
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:
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.
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.
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.
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:
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.
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.
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.
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 126.96.36.199) 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.
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:
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.
The aligned record layout conventions ensure that:
The aligned record layout is defined by the following conventions:
188.8.131.52 OpenVMS VAX Compatible Record Layout
The OpenVMS VAX compatible record layout is defined by the following conventions:
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.
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.