TOC PREV NEXT INDEX DOC LIST MASTER INDEX



Ada 83 LRM Appendix F: Implementation-Dependent Characteristics

This chapter provides information as required by the Ada 83 LRM Appendix F. The implementation-dependent characteristics of Rational Apex are described in the following sections:


Pragmas

This section provides:

Error Handling for Pragmas

A pragma whose existence, placement, or arguments do not correspond to those allowed is ignored, by default, by the compiler and the runtime system. This means that a warning is generated if the compiler detects such an error, but the error does not prevent the compilation from completing successfully.

However, several Apex context switches allow you to specify whether to treat certain classes of invalid pragmas as errors that prevent successful compilation rather than as warnings. The following switches are discussed in greater detail in the Ada Runtime Guide:

If more than one of the same pragma is specified where it is not appropriate to do so (for example, two pragma Mains on the same unit), the first one is used and the others generate warnings at compile time.

References

Pragma warnings, LRM 2.8(9), 2.8(11).

Predefined Pragmas

For each pragma defined in Annex B of the Ada 83 LRM, Table 20 describes the extent to which Rational Ada supports it.

Table 20 Predefined Pragmas from the Ada 83 LRM Annex B
Predefined pragma
Level of support
Controlled
Always implicitly in effect because the implementation does not support automatic garbage collection.
Convention
Used to specify that an Ada subprogram or type should use the conventions of another language. It is useful for defining subprograms for callback operations. This pragma is actually defined in Ada 95, but it is valid in the Apex Ada implementation of Ada 83. It is described in detail in pragma Convention.
Elaborate
As described in Annex B.
Inline
The predefined pragma Inline as described in Annex B is coordinated with the implementation-defined pragmas Inline_Only and Inline_Never. All are described in Inlining Pragmas. In cases where automatic inlining is allowed, the compiler checks the switch OPTIMIZATION_OBJECTIVE. If the optimization objective is Time, the compiler inlines only those calls for which the expected result is faster execution; if the objective is Space, it inlines only those calls for which the expected result is smaller code at the call site.
Interface
As described in Annex B. Often used in conjunction with pragmas Import_Function, Import_Procedure, or Interface_Name. Language names that can be specified in the first argument of the pragma are: ASM, C, ADA, FORTRAN, PASCAL, and UNCHECKED (use C when interfacing to C++).
List
Has no effect.
Memory_Size
Has no effect.
Optimize
Has an effect only when located in the outermost scope, where it applies to the entire compilation unit. If not used, the setting of the Optimization_Objective switch is used. See "Setting the Optimization Objective.
Pack
For more information about concepts for object sizes, see the Ada Runtime Guide
Page
Has no effect.
Priority
As described in Annex B and LRM 9.8(2). The default is 0. The default priority for tasks can be altered using pragma Main.
Shared
As given in Annex B. Has an effect only for integer, enumeration, access, and fixed point types.
Storage_Unit
Has no effect.
Suppress
As described in Annex B, with the addition of the implementation-defined check name ALL_CHECKS.
System_Name
Has no effect. (There is only one enumeration literal in the type System.System_Name.)

Implementation-Defined Pragmas

Table 21 summarizes all implementation-defined pragmas in Apex. Each pragma is described in more detail in the following subsections.

Table 21 Implementation-Defined Pragmas for Ada 83
Implementation-defined pragma
Description
Api
Designates a compilation unit as belonging to the user-visible portion of an API.
Assert
Raises an exception if a specified Boolean expression evaluates to False at run time.
Calling_Convention
Provides an interface to low-level calling conventions of other languages.
Collection_Policy
Controls memory allocation for the collection designated by an access type.
Export_Elaboration_Procedure
When applied to a compilation unit that is a package specification or package body, provides an external name for the implicitly generated elaboration procedure
Export_Function
Indicates that an Ada function will be called by code written in another language; also specifies the external name for the function used at link time. This is an obsolete pragma now supplanted by pragma Export.
Export_Object
Indicates that an Ada constant or variable will be referenced by code written in another language; also specifies the external name for the object that is used at link time. This is an obsolete pragma now supplanted by pragma Export.
Export_Procedure
Indicates that an Ada procedure will be called by code written in another language; also specifies the external name for the procedure used at link time. This is an obsolete pragma now supplanted by pragma Export.
External
Indicates that an Ada subprogram will be called by code written in another language; used together with pragma External_Name. Can be used as an alternative to pragma Export_Function or pragma Export_Procedure. This is an obsolete pragma now supplanted by pragma Convention.
External_Name
Specifies the external name used at link time for a subprogram or object, so it can be referenced from other languages. This is an obsolete pragma now supplanted by pragmas Import and Export.
Implicit_Code
Used only for machine code procedures.
Import_Function
Indicates that a function is written in another language, and specifies the external name by which it is to be referenced at link time; always used in conjunction with pragma Interface. This is an obsolete pragma now supplanted by pragma Import.
Import_Object
Indicates that a constant or variable is defined by code written in another language, and specifies the external name by which it is to be referenced at link time. This is an obsolete pragma now supplanted by pragma Import.
Import_Procedure
Indicates that a procedure is written in another language, and specifies the external name by which it is to be referenced at link time. Always used in conjunction with pragma Interface. This is an obsolete pragma now supplanted by pragmas Import and Export.
Initialize
Specifies that default initialization be carried out for an imported object or an object referenced by an address clause.
Inline_Never
Specifies that a subprogram should never be inlined at any optimization level.
Inline_Only
Specifies that a subprogram should always be inlined, at any optimization level.
Interface_Name
Allows the specification of link names for subprograms and variables defined in other languages. Always used in conjunction with pragma Interface. This is an obsolete pragma now supplanted by pragma Import.
License
Used in an API specification. Allows compilation of code referencing the API to proceed only after acquiring a license to do so.
Link_With
Passes arguments to the target linker. Obsolete. Supplanted by pragma Linker_Options.
Main
Designates an Ada main unit and specifies aspects of its runtime behavior.
Must_Be_An_Entry
Specifies that the actual subprogram supplied in any instantiation for the given generic formal procedure must be a task entry.
Must_Be_Constrained
Indicates whether formal private and limited private types within a generic formal part must be constrained.
Not_Elaborated
Suppresses the generation of elaboration code and issues warnings if elaboration code is required.
Signal_Handler
Installs a procedure as a UNIX signal handler.
Suppress_All
Suppresses all permitted runtime checks.
Suppress_Elaboration_Checks
Suppresses elaboration checks for a specific compilation unit.

String-Valued Arguments to Pragmas

Many of the implementation-defined pragmas have arguments described as manifest string-valued expressions. These expressions are of type Standard.String and must be manifest to the compiler, that is, computable at compile time. For this purpose, a manifest expression is a semantically valid expression comprised only of string literals, character literals, predefined catenation operators, and references to constants of type Standard.String whose initial values are manifest.

Pragma Api

Designates a compilation unit as belonging to the user-visible portion of an API. The syntax is:

Arguments

Usage

Pragma Api must appear at the end of a compilation unit.

Pragma Assert

Raises an exception if a specified Boolean expression evaluates to False at run time. The syntax is:

Arguments

Usage

When pragma Assert is encountered at run time, the Boolean expression is evaluated. If the result is False, the exception System.Assertion_Error is raised; if the result is True, no action is taken.

This pragma can appear anywhere that a declaration or statement is allowed.

Pragma Calling_Convention

Pragma Calling_Convention is always used in conjunction with either a pragma Import or a pragma Export. The functionality described in this section applies to imported C/C++ routines and exported Ada routines.

Pragmas Import and Export tell the compiler that a certain subprogram is imported from or exported to another language. Pragma Calling_Convention gives additional instructions to the compiler about specific calling conventions to be used. This affects the code generated by the compiler for the subprogram call (if imported) or for the subprogram prologue and epilog (when exported). The syntax is:

Note that the first argument of a pragma Calling_Convention (the "Entity" argument) always names a subprogram which is also referenced by a pragma Import or Export. The other arguments of pragma Calling_Convention (which must be named) depend on whether the pragma applies to an imported or an exported subprogram.

Arguments/Attributes

Usage

Use pragma Calling_Convention to enable the running of several different IEEE floating point models within the same program. Using pragma Calling_Convention, C/C++ code using a floating point model that includes NaNs (Not-a-Number) and Infs (Infinity), can be used with Apex Ada.

To enable this facility, you must add pragma Calling_Convention after the pragma Import line where you declare the C++ procedure in Ada.

This combination tells the compiler to load the floating point status register from the C_FLOATING_POINT_CONTROL field of the user configuration table before calling the C++ routine. After the C++ code returns, the value of the FLOATING_POINT_CONTROL field of the configuration table is restored to the floating point status register.

Additional information on this pragma can be found in pragma Calling_Convention.

Examples

The following code contains examples of pragma Calling_Convention for both imported and exported subprograms.

Pragma Collection_Policy

Controls memory allocation for the collection designated by an access type. The syntax is:

Arguments

Usage

Pragma Collection_Policy must appear in the same declarative region as the access type to which it applies, after the access type's declaration and before any forcing occurrence of the access type. If the access type is a private type, the pragma must appear in the private part after the complete access-type declaration. If the pragma appears outside the specified areas, it is ignored.

For a description and example of the pragma's application, see "Managing Storage for Access Types" in the Ada Runtime Guide.

Notes

References

Pragma Export_Elaboration_Procedure

Defines a global symbolic name for the elaboration procedure of a given compilation unit. The syntax is:

Parameters

Usage

Use this pragma to reference the elaboration procedure of an Ada module that is not otherwise elaborated. This exceptional case occurs when the module is not in the closure of the main program, or when the main program was not written in Ada.


Warning: Do not use this pragma unless you thoroughly understand the elaboration, runtime, and storage-model considerations.

Notes

References

Pragmas Export_Function, Export_Object, and Export_Procedure

Indicates that an Ada function, procedure, constant, or variable will be called or referenced by code written in another language; also specifies the external name for the exported entity used at link time. The syntax is:

Arguments

Usage

Use these export pragmas when a subprogram or object defined in Ada is to be referenced by code written in a different language (or even by Ada code that is not in the Ada closure of the main program). The code generated for an exported subprogram will compensate for differences between the calling conventions of the foreign language and Ada (if any).

An exported entity can also be referenced directly by Ada code. The pragmas also affect the global name used at link time to designate the subprogram or object. If an External_Name is specified, that name is used; otherwise, the compiler selects a name based on the language and host system, as described in the table below for a subprogram whose internal name is "Sheba".

Language
Solaris
AIX
Digital Unix
HP-UX
IRIX
ASM
SHEBA
SHEBA
SHEBA
SHEBA
SHEBA
C
sheba
.sheba
sheba
sheba
sheba
ADA
sheba
sheba
sheba
sheba
sheba
FORTRAN
sheba
.sheba.
sheba
sheba_
sheba
PASCAL
sheba
sheba
sheba
sheba
sheba
UNCHECKED
sheba
sheba
sheba
sheba
sheba

If the internal subprogram name is overloaded (and more than one of the overloaded subprograms appears in the same declarative part or package specification as the pragma), you must supply enough information for the compiler to determine unambiguously which subprogram to export. This is the purpose of the Parameter_Types argument (and for functions, the Result_Type argument).


Warning: Exporting a subprogram does not export the mechanism used by the compiler to perform elaboration checks. A call from another language to an exported subprogram with an unelaborated body can produce unpredictable results when the subprogram references an object that is itself unelaborated.


Warning: Accesses to Ada objects by non-Ada code are inherently unsafe; the compiler and runtime system cannot guarantee the integrity of such exported objects. It is the developer's responsibility to ensure that the code that accesses an exported object properly interprets and maintains the underlying structure of the object. When exporting constant objects, take special care that non-Ada code does not change the value of the constant.

Notes

References for Subprograms

References for Objects

Pragma External

Indicates that an Ada subprogram will be called by code written in another language. Together with pragma External_Name can be used as an alternative to pragma Export_Function or pragma Export_Procedure. The syntax is:

Arguments

Usage

The context, allowed languages, and types of subprograms for pragmaExternal are the same as for pragma Interface, except that a body must be supplied for the subprogram. The code generated for the subprogram will compensate for differences between the calling conventions of the foreign language and Ada (if any).

To specify the global name to use for the subprogram at link time, use pragma External_Name. If no such name is specified, the compiler will select a name in the same way as for pragmas Export_Function and Export_Procedure.

Pragma External_Name

Specifies the external name used at link time for a subprogram or object so it can be referenced from other languages. The syntax is:

Arguments

Usage

Use pragma External_Name in conjunction with pragma External on a subprogram or by itself on an object. If pragma Export_Object has previously been applied to an object, it prevails and pragma External_Name is ignored.The pragma can appear only at the place of a declarative item in a declarative part of package specification. The external entity to which it applies must have been declared by an earlier declarative item of the same declarative part or package specification.

Pragma Implicit_Code

Arguments

None.

Usage

This pragma is used only for machine code procedures. Refer to Machine Code Insertions for more information.

Pragmas Import_Function, Import_Object, and Import_Procedure

Indicates that an Ada function, procedure, or variable is defined by code written in another language, and specifies the external name by which it is to be referenced at link time. Typically, the subprogram or object is defined using a language other than Ada, although Ada can be used. The syntax is:

Arguments

Usage

Use the import pragmas to supply more information about a non-Ada subprogram specified with pragma Interface or a non-Ada object to be referenced by Ada code.

Every subprogram to which Import_Function or Import_Procedure is applied must also have an interface pragma applied, before the import pragma. The import pragma can be omitted if you want to use the compiler's defaults for the external name and parameter passing mechanisms.

If the internal Ada subprogram name is overloaded, you can supply enough information for the compiler to determine unambiguously which subprogram is being imported. Specify the Parameter_Types (and, for functions, the Result_Type) so that the compiler can construct the parameter- and/or result-type profile of the subprogram. If you omit these arguments, the import pragma (and pragma Interface) will apply to all of the overloaded subprograms of the same name in the same declarative part or package specification.


Warning: Accesses to non-Ada objects from Ada code are inherently unsafe; the compiler and runtime system cannot guarantee the integrity of such imported objects. It is the developer's responsibility to ensure that the code that accesses an imported object properly interprets and maintains the underlying structure of the object.

Notes

References for Subprograms

References for Objects

Pragma Initialize

Specifies that default initialization be carried out for an imported variable or a variable referenced by an address clause. The syntax is:

Arguments

Usage

When a program imports a variable object or declares a variable with an address clause, the compiler assumes that this variable previously existed. The compiler makes no attempt to assign a default (initial) value to this variable, because the variable might already contain a valid value or might be given an initial value by some other program. By default, the compiler does not perform any implicit initialization on:

Pragma Initialize tells the compiler to assign an appropriate default value to the variable —— for example, setting pointers and pointer fields to null, record fields to the initial values present in the record type definition, and discriminants to their proper values. Hence, the variable must not have an explicit initial value.

No additional storage space is allocated because valid variables already exist.

The referenced variable must:

Example

Pragma Initialize can be used to request that pointers be set to Null or that record fields be given some starting value.

References

Pragma Inline_Never

Completely prohibits inlining of a specified subprogram.The syntax is:

Usage

Use this pragma to specify that a subprogram should never be inlined at any optimization level.

Pragma Inline_Only

Specifies that a subprogram should always be inlined,. The syntax is:

Usage

Use this pragma to force the compiler to inline a specified subprogram, even at optimization level 0. Pragma Inline_Only (unlike pragma Inline) generates a hard error when the a call to the specified subprogram cannot be inlined. The current compiler cannot inline subprograms in the following scenarios:

Pragma Interface_Name

Allows the specification of link names for subprograms and variables defined in other languages. The syntax is:

Arguments

Usage

This pragma can be used as an alternative to pragmas Import_Function and Import_Procedure to specify the external name for an imported subprogram. If you wish to specify parameter mechanisms or distinguish between overloaded subprograms, you must use Import_Function or Import_Procedure instead. Any subprogram to which Interface_Name is applied must also have pragma Interface applied.

The places in which the pragma is legal and the restrictions that apply to it are the same as for the importing pragmas.

Pragma License

Used in an API specification, allows compilation of code referencing the API to proceed only after acquiring a license to do so.

Arguments

Usage

Pragma License must appear at the end of a compilation unit that is a package declaration, a subprogram declaration, or a generic. Pragma Api must be applied to the same compilation unit and appear before pragma License.

Whenever the compiler encounters pragma License in the closure of a unit it is compiling, it attempts to acquire a license for the feature name and version given in the pragma. If it is unable to do so, the compilation will be aborted. At most one license for the name and version is required for any Apex session.

Example

Pragma Link_With

Same functionality as pragma Linker_Options.

Pragma Linker_Options

(Supplants pragma Link_With)

Passes arguments to the target linker. The syntax is:

Usage

This pragma can appear in any package specification or declarative part. Its argument is passed as a command line argument to the target linker whenever the unit containing the pragma is in the closure of the main program being linked.

In constructing the target linker command line argument, the Linker_Options argument is first divided into tokens. Tokens are delimited by white-space.

Tokens are then passed to the linker command line. Tokens beginning with "+" and "-" tokens are interpreted as linker switches. Tokens beginning with "/" tokens are interpreted as rooted filenames. If a token begins with "-", "+", or "/", it is left untouched.

If a token begins with neither "-" nor "+" nor "/", then it is assumed to name a file and is prefixed with pathname of the directory containing the Ada unit in which the pragma appears. (This behavior is different from VADS, in which unqualified names are interpreted in the context of the main program being linked).

If a main program's closure contains more than one pragma Linker_Options, their contents will be separated by blanks on the linker command line. The order in which the arguments appear is not defined.

If pragma Linker_Options appears in the implementation of an API, that is, in a unit that also contains pragma Api, its contents are passed to the linker when the API is used in the closure of a main program, not when the API itself is linked.

Pragma Main

Designates an Ada main unit and determines some aspects of its runtime behavior. The syntax is:

All expressions must be static; all integer expressions must be nonnegative.

Arguments

Usage

Use pragma Main after the end of the unit body of a parameterless library-unit subprogram to designate it as a main program. If the subprogram is a function, the type it returns must be Standard.Integer (the return value is passed to Unix as the exit status of the program). In Ada 95, the subprogram must not be a child unit or a rename.

Pragma Main can have two effects. It:

Example

Use pragma Main as shown:

References

Pragma Must_Be_An_Entry

Specifies that the actual subprogram supplied in any instantiation for the given generic formal procedure must be a task entry. The syntax is:

Arguments

Usage

This pragma is used when a generic depends upon one or more of its formal subprograms being implemented as a task entry.

Pragma Must_Be_Constrained

Indicates whether formal private and limited private types within a generic formal part must be constrained or have default values. The syntax is:

Arguments

Usage

Use pragma Must_Be_Constrained to specify how you intend to use the formal parameters in a generic specification.

Each condition controls the types in the following type ID list, until the next occurrence of a condition. Consider this example:

At the beginning of the list, a condition is not specified, so YES is assumed; hence, Type_1 is constrained. NO controls the following type ID list, which includes Type_2 and Type_3; hence, they are unconstrained. YES controls the remaining type ID list, so Type_4 and Type_5 are constrained.

Notes

If the condition NO is specified, any use in the body that requires a constrained type will generate a semantic error. If YES is specified, any instantiations that contain actual parameters that require constrained types will generate semantic errors if the actual parameters are not constrained and have no default discriminant values.

References

Pragma Not_Elaborated

Suppresses the generation of elaboration code and issues warnings if elaboration code is required. Also causes elaboration checks to be suppressed for all subprograms declared in the package in which it appears. The syntax is:

Arguments

None.

Usage

Use this pragma when a package will not be elaborated because it is referenced from non-Ada code and it is not referenced from within the Ada closure of the main program. If the code generator produces a warning that elaboration code was generated and the unit is not in the Ada closure of the main program, the elaboration code won't be called and the package is unlikely to work properly.

This pragma must appear immediately within a nongeneric library package specification. The pragma is implicitly applied to the package body and its package subunits.

Pragma Restrictions

Arguments

None.

Usage

Used only as a configuration pragme. Please refer to Configuration Pragmas for more information.

Pragma Signal_Handler

Installs an Ada procedure as a UNIX signal handler. The syntax is:

Arguments

Usage

Elaboration of the pragma has the effect of installing the specified procedure as a signal handler for the given signal. Subsequent occurrences of the specified signal will cause the specified procedure to be invoked.

The pragma and the procedure body must occur in the same declarative part, with the pragma following the procedure body. This prevents the installation of a procedure whose body has not yet been elaborated.

For information about Ada procedural signal handlers and details on the construction of the procedure, see the "Interrupt Handlers" chapter in the Ada Runtime Guide.

References

Pragma Suppress_All

Suppresses all permitted runtime checks. The syntax is:

Arguments

None.

Usage

Use pragma Suppress_All to create the same effect as all of the following:

Notes

References

Pragma Suppress_Elaboration_Checks

Suppresses all elaboration checks in a given compilation unit. The syntax is:

Arguments

None.

Usage

Use pragma Suppress_Elaboration_Checks at the end of any compilation unit to suppress elaboration checks for all subprograms in that unit. This is equivalent to placing a named pragma Suppress (Elaboration_Check) in each subprogram in the unit. For example;

is equivalent to

References


Attributes

Table 22 summarizes all implementation-defined attributes in Rational Ada. Each attribute is described in more detail in the following subsections.

Table 22 Implementation-Defined Attributes
Attribute
Meaning
'Compiler_Key
Identifies the compiler used to generate code for the specified object
'Compiler_Version
Yields the version of the compiler used to generate code for the specified object
'Dope_Address
Yields the address of the dope vector for an array object
'Dope_Size
Yields the size of the dope vector for an array object
'Entry_Number
Uniquely identifies an entry or generic
'Homogeneous
Specifies whether objects in a collection are of uniform size
'Type_Key
Uniquely identifies a type

Compiler_Key

For a prefix N that denotes the name of an entity, N'Compiler_Key yields the full pathname of the compiler key, which indicates the compiler that was used to generate code for the unit containing the definition of N.

The entity named by N can be a program unit (package, subprogram, task, or generic), an object (variable, constant, named number, or parameter), a type or subtype (but not an incomplete type), or an exception.

The value returned by this attribute is of type String; for example, "/apex_home/keys/ada_rational_rs6k_aix".

This attribute can be used for runtime detection of incompatibilities in data representation. It typically is used when passing messages over a network to ensure that the reader and writer agree on how to interpret the message. See also Compiler_Version.

Compiler_Version

For a prefix N that denotes the name of an entity, N'Compiler_Version yields the version of the compiler that was used to generate code for the unit containing the definition of N.

The entity named by N can be a program unit (package, subprogram, task, or generic), an object (variable, constant, named number, or parameter), a type or subtype (but not an incomplete type), or an exception.

The value returned by this attribute is of type string; for example, "1.6.1A".

This attribute can be used for run-time detection of incompatibilities in data representation. It typically is used when passing messages over a network to ensure that the reader and writer agree on how to interpret the message. See also Compiler_Key.

Dope_Address

For an object or type A, A'Dope_Address yields the address of the dope vector that describes A. The value is of type System.Address. If the object or type denoted by A has no dope vector, this value is System.Null_Address. Non-array objects and types are allowed with this attribute so that they may be applied to formal types inside a generic, where the nature of the actual type is not known statically.

This attribute can be used in conjunction with 'Dope_Size for retrieving information about the object, as when reconstructing the array when passing messages over a network. For information about dope vectors, see the Ada Runtime Guide.

Dope_Size

For an object or type A, A'Dope_Size yields the size in bits of the dope vector. The value is of type Universal_Integer. A value of zero is returned if the type to which A belongs is not an array type.

A positive value is always returned, whether or not the object denoted by A has a dope vector. Use 'Dope_Address to determine whether the dope vector actually exists.

This attribute can be used for retrieving information about the object, as when reconstructing the array when passing messages over a network. For information about dope vectors, see the Ada Runtime Guide.

Entry_Number

For a prefix E that denotes a task entry or generic formal subprogram, E'Entry_Number yields a Universal_Integer value that uniquely identifies the entity denoted by E.

Homogeneous

For a prefix T that denotes an access type, T'Homogeneous yields a Boolean value. The value returned is True if all objects in the collection will always have the same constraints. The converse, however, is not true.

Applying this attribute to a type other than an access type is a semantic error. It is most useful when applied to a generic formal access type.

Note that the attribute is a property of the type, not of the subtype. Thus, for any access type T, T'Homogeneous yields the same value as T'Base'Homogeneous.

For example:

At the implementation level, the attribute indicates whether constraint information is stored with allocated objects.

Type_Key

For a prefix T denoting a type declared in a library level package specification, T'Type_Key yields a string that uniquely identifies type T. This attribute typically is used when passing messages of a given type over a network to ensure that the reader and writer agree on the type to use when interpreting the message.

Attributes of Numeric Types

This section lists the values returned by attributes that apply to integer types, floating-point types, and the fixed-point type Duration.

Integer Types

The attributes that apply to integer types —— namely, 'First, 'Last, and 'Size —— yield the values shown in Table 23 for the predefined base types:

Table 23 Attribute Values for Integer Types
Attribute
Value
Short_Integer'First
-215
Short_Integer'Last
215-1
Short_Integer'Size
16
Integer'First
𔃀31
Integer'Last
231𔂿
Integer'Size
32
Long_Integer'First (64-bit only)
-263
Long_Integer'Last (64-bit only)
263-1
Long_Integer'Size (64-bit only)
64
Long_Integer'First (32-bit only)
-231
Long_Integer'Last (32-bit only)
231-1
Long_Integer'Size (32-bit only)
32

It is also possible to include a declaration of Tiny_Integer in package Standard. The inclusion of Tiny_Integer provides upward compatibility with the VADS compiler. This can be accomplished during the Apex installation process. If it has been included, the following line is included in the standard_1.ada file in Ada83 views of lrm.ss:

The default is that this declaration is not included in package Standard.

If you want Tiny_Integer and it wasn't included during installation, then create a new view of lrm.ss. After deleting all Diana trees from the view (typically by cleaning down to archived), compile the view using the following command:

Floating-Point Types

The attributes that apply to floating-point types yield the following values for the predefined base type Float:

Table 24 Floating-Point Type Attributes
Name of Attribute
Attribute Value of LONG_FLOAT
Attribute Value of FLOAT and SHORT_FLOAT
SIZE
64
32
FIRST
-1.79769313486232E+308
-3.40282E+38
LAST
1.79769313486232E+308
3.40282E+38
DIGITS
15
6
MANTISSA
51
21
EPSILON
8.88178419700125E-16
9.53674316406250E-07
EMAX
204
84
SMALL
1.94469227433161E-62
2.58493941422821E-26
LARGE
2.57110087081438E+61
1.93428038904620E+25
SAFE_EMAX
1021
125
SAFE_SMALL
2.2250738585072E-308
1.17549435082229E-38
SAFE_LARGE
2.24711641867789E+307
4.25352755827077E+37
MACHINE_RADIX
2
2
MACHINE_MANTISSA
53
24
MACHINE_EMAX
1024
128
MACHINE_EMIN
-1021
-125
MACHINE_ROUNDS
TRUE
TRUE
MACHINE_OVERFLOWS
TRUE
TRUE

Type Duration

The attributes that apply to fixed-point types yield the following values for the predefined type Duration:

Table 25 Fixed Point Type Attribute Values - 32 bit systems
Name of Attribute
Attribute Value for DURATION
SIZE
32
FIRST
-214748.3648
LAST
214748.3647
DELTA
1.00000000000000E-04
MANTISSA
31
SMALL
1.00000000000000E-04
LARGE
2.14748364700000E+05
FORE
7
AFT
4
SAFE_SMALL
1.00000000000000E-04
SAFE_LARGE
2.14748364700000E+05
MACHINE_ROUNDS
TRUE
MACHINE_OVERFLOWS
TRUE

Table 26 Fixed Point Type Attribute Values - 64 bit systems
Name of Attribute
Attribute Value for DURATION
SIZE
64
FIRST
-9223372036.854775808
LAST
9223372036.854775807
DELTA
1.00000000000000E-09
MANTISSA
63
SMALL
1.00000000000000E-09
LARGE
9.22337203685478E+09
FORE
11
AFT
9
SAFE_SMALL
1.00000000000000E-09
SAFE_LARGE
9.22337203685478E+09
MACHINE_ROUNDS
TRUE
MACHINE_OVERFLOWS
TRUE


Packages Standard and System

This section contains the specifications for packages Standard and System.

Package System (LRM 13.7)

Full listings of package System and its language-defined children can be found in the following location.

Native Apex Releases:

These meta names are set when Apex is invoked. Their values can be displayed using Tools > Session > Environment command.

Cross/Embedded Apex Releases:

The location of these packages for the Apex cross products is dependent on the target processor and runtime variant. Use Table 27 to locate the desired Apex cross location. APEX_BASE and APEX_PROD_VERSION are set when Apex is invoked. Their values can be displayed using Tools > Session > Environment command.

Table 27 Location of Package System for Apex Cross (Ada 83)
Target
Location
Apex for Rational Exec
I386:
$APEX_BASE/ada/lrm.ss/i386.rx_i386.ada83.${APEX_PROD_VERSION}.rel
M68k:
$APEX_BASE/ada/lrm.ss/m68k.rx_mc68040.ada83.${APEX_PROD_VERSION}.rel
M68060:
$APEX_BASE/ada/lrm.ss/m68k.rx_mc68060.ada83.${APEX_PROD_VERSION}.rel
Mips1 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.rx_mips1b.ada83.${APEX_PROD_VERSION}.rel
Mips2 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.rx_mips2b.ada83.${APEX_PROD_VERSION}.rel
PowerPC:
$APEX_BASE/ada/lrm.ss/power.rx_ppc.ada83.${APEX_PROD_VERSION}.rel
RH32:
$APEX_BASE/ada/lrm.ss/rh32.rx_p3.ada83.2.4.2.rel

Apex for Tornado
M68060:
$APEX_BASE/ada/lrm.ss/m68k.vw_mc68060.ada83.${APEX_PROD_VERSION}.rel
Mips1 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.vw_mips1b.ada83.${APEX_PROD_VERSION}.rel
Mips2 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.vw_mips2b.ada83.${APEX_PROD_VERSION}.rel
PowerPC:
$APEX_BASE/ada/lrm.ss/power.vw_ppc.ada83.${APEX_PROD_VERSION}.rel

Apex for LynxOS
PowerPC:
$APEX_BASE/ada/lrm.ss/power.lx_ppc.ada83.${APEX_PROD_VERSION}.rel

Package Standard (LRM Annex C)

A listing of package Standard is provided for each of the Apex platforms and can be found in the following location.

Native Apex Releases:

These meta names are set when Apex is invoked. Their values can be displayed using Tools > Session > Environment command.

Cross/Embedded Apex Releases:

The location of this package for the Apex cross products is dependent on the target processor and runtime variant. Use Table 28 to locate the desired Apex cross location. APEX_BASE and APEX_PROD_VERSION are set when Apex is invoked. Their values can be displayed using Tools > Session > Environment command.

Table 28 Location of Package Standard for Apex Cross (Ada 83)
Target
Location
Apex for Rational Exec
I386:
$APEX_BASE/ada/lrm.ss/i386.rx_i386.ada83.${APEX_PROD_VERSION}.rel
M68k:
$APEX_BASE/ada/lrm.ss/m68k.rx_mc68040.ada83.${APEX_PROD_VERSION}.rel
M68060:
$APEX_BASE/ada/lrm.ss/m68k.rx_mc68060.ada83.${APEX_PROD_VERSION}.rel
Mips1 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.rx_mips1b.ada83.${APEX_PROD_VERSION}.rel
Mips2 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.rx_mips2b.ada83.${APEX_PROD_VERSION}.rel
PowerPC:
$APEX_BASE/ada/lrm.ss/power.rx_ppc.ada83.${APEX_PROD_VERSION}.rel
RH32:
$APEX_BASE/ada/lrm.ss/rh32.rx_p3.ada83.2.4.2.rel

Apex for Tornado
M68060:
$APEX_BASE/ada/lrm.ss/m68k.vw_mc68060.ada83.${APEX_PROD_VERSION}.rel
Mips1 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.vw_mips1b.ada83.${APEX_PROD_VERSION}.rel
Mips2 (Big Endian):
$APEX_BASE/ada/lrm.ss/mips.vw_mips2b.ada83.${APEX_PROD_VERSION}.rel
PowerPC:
$APEX_BASE/ada/lrm.ss/power.vw_ppc.ada83.${APEX_PROD_VERSION}.rel

Apex for LynxOS
PowerPC:
$APEX_BASE/ada/lrm.ss/power.lx_ppc.ada83.${APEX_PROD_VERSION}.rel

Table 29 shows the sizes of predefined integer and floating-point types:

Table 29 Sizes of Predefined Numeric Types
Ada type name
Size
Short_Integer
16 bits
Integer
32 bits
Long_Integer
64 bits
Float
32 bits
Long_Float
64 bits

Fixed-point types are implemented using 32 bits.

Floating-point types are implemented according to the IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std. 754-1985).

Standard.Duration is a 32-bit fixed-point type with a delta of 2 -4.


Representation Clauses

This section discusses limitations on representation clauses in the following categories:

Note that in general, a compiler must either accept a representation clause and comply with it, or reject it if it finds that it cannot implement it. When we say that a representation clause is "allowed" or "supported", we mean that it is accepted by the compiler, and therefore, that the generated code complies with that clause.

For related information, about sizes of objects, see the Ada Runtime Guide.

Alignment of Types and Objects

Note: In this discussion, the alignment is expressed in bytes.

In Ada 83, the only mechanism for controlling alignment is the alignment_clause of a record_representation_clause (RM83 13.4(2-4)). For instance:

Note that while an alignment_clause is part of a record_representation_clause, which may include component_clauses, the presence of component_clauses is not mandatory. In the above example, the alignment for the type is specified to be 8, but the internal layout of the record is left unspecified (and will be chosen by the compiler).

The semantics of alignment_clauses are defined by RM83 13.4(4):

An alignment clause forces each record of the given type to be allocated at a starting address that is a multiple of the value of the given expression (that is, the address modulo of the expression must be zero.) An implementation may place restrictions on the allowable alignments.

Note the phrase "each record of the given type." This phrase implies that each and every object of the type has to comply with the given alignment. This includes objects allocated on the stack (for example, objects declared within subprograms) or allocated on the heap (for example, by means of an allocator).

Because of this rule, the allowable alignments are generally small,that is, limited to those that can be naturally supported by the machine instructions (for instance, 4- or 8-byte alignment on the stack). This means that in Ada 83, it is generally not possible to specify "large" alignments (for instance, page alignment). Some compilers (for example,VADS) have taken liberties with the language rules, and support larger alignments, but only enforce them on some objects (for example, statically allocated objects). While this approach was certainly pragmatic and useful given the limitations imposed by Ada 83, it made programs less portable. Moreover, the introduction of the Alignment attribute in Ada 95 provides much better support for controlling alignments. For this reason, Apex adheres to the strict rules of Ada 83, and only supports "small" alignments for types in Ada 83 (see below for the actual limits).

The actual limits for Apex are as follows:

Table 30 Type and Object Alignment Limits - Ada 83

4

8

8

8

8

8

4

8

Representation-Clause Error Handling

Normally, an invalid representation clause causes an error at compile time and prevents successful compilation.

Several Apex context switches, however, allow you to specify whether to treat certain classes of invalid representation clauses as nonfatal errors that allow successful compilation rather than as errors. The following switches are described in the online documentation:

Length Clauses

Length clauses are supported by Rational Apex as follows:

Enumeration Representation Clauses (LRM 13.3)

Enumeration representation clauses are supported with the following restriction:

Record Representation Clauses (LRM 13.4)

Both full and partial representation clauses are supported for both discriminated and undiscriminated records. Record component clauses are not allowed on:

The static simple expression in the alignment clause part of a record representation clause —— see the Ada LRM 13.4 (4) —— must be a power of 2 with the following limits:

The size specified for a discrete field in a component clause must not exceed 32 bits.

Bit numbering in record representation clauses is machine dependent. On big-endian machines, bit 0 maps to the most significant bit. On little-endian machines, bit 0 maps to the least significant bit. Figures illustrating the bit numbering and addressing schemes for each of the Apex platforms are provided on the following pages. Select your platform from the following list:

Representation clauses are not supported for derived discriminated record types.

Figure 4 Digital UNIX and Intel Architecture Little Endian

Figure 5 HP PA Addressing and Bit Numbering

Figure 6 MIPS Little Endian

Figure 7 MIPS Big Endian

Figure 8 PowerPC Addressing and Bit Numbering

Figure 9 RS/6000 Addressing and Bit Numbering

Figure 10 SPARC Addressing and Bit Numbering

Change of Representation (LRM 13.6)

Change of representation is supported wherever it is implied by support for representation specifications. In particular, type conversions between array types might cause packing or unpacking to occur. Conversions between related enumeration types with different representations can result in table-lookup operations.


Implementation-Generated Names

The Ada LRM allows for the generation of names denoting implementation-dependent components in records. No such names are visible to the user for Apex.


Address Clauses (LRM
13.5)

Address clauses cannot be applied to task types. No other restrictions are placed on address clauses.

An address clause can be attached to a task entry only when the task entry is used for signal (interrupt) catching; however, in this case, the task entry must be available at the time of the signal. For more information see Pragma Signal_Handler. For more information on interrupt-entry signal handling, see the Ada Runtime Guide.

Values of address clauses are not checked for validity. No check is made to determine whether an address clause causes the overlay of objects or of program units.


Unchecked Programming

Unchecked Storage Deallocation (LRM 13.10.1)

Unchecked storage deallocation is implemented by the Ada LRM-defined generic function Unchecked_Deallocation. This procedure can be instantiated with an object type and its access type, resulting in a procedure that deallocates the object's storage. Objects of any type can be deallocated.

The storage reserved for the entire collection associated with an access type is reclaimed when the program exits the scope in which the access type is declared. Placing an access-type declaration within a block can be a useful implementation strategy when conservation of memory is necessary within a collection. Space on the free list is coalesced when objects are deallocated.

Erroneous use of dangling references can be detected in certain cases. When detected, the Storage_Error exception is raised. Deallocation of objects that were not created through allocation (that is, through Unchecked_Conversion) can also be detected in certain cases, also raising Storage_Error.

Unchecked Type Conversion (LRM 13.10.2)

Unchecked type conversion is implemented by the generic function Unchecked_Conversion defined by the Ada LRM. This function can be instantiated with source and target types, resulting in a function that converts source data values into target data values.

Operation of Unchecked Type Conversion

In general, unchecked conversion produces reasonable results only if the source and the target type have the same size. The compiler generates a warning message if it detects that source and target types of an unchecked conversion have different sizes:

Unchecked conversion to and from scalar types that include redundant high order bits is also considered unsafe. For example, the 28 most significant bits of new Integer range 0..15 are redundant because they are always equal to zero. If the compiler detects unchecked conversion to or from such types it generates the warning messages:

The compiler generates similar warning messages for unchecked conversion to or from packed structured types, if the packed size is smaller than the default size of the type. Finally, if the source or the target type of an unchecked conversion has a dynamic size, the compiler generates the warning message:

The user can ignore these messages, but the implementation as described here cannot guarantee that something sensible is returned in these cases. However, considerable effort is made to ensure that the result is well-defined.

Special care must be taken for unchecked conversion to record or array types. The layout of a record or array can contain unused bits that are normally initialized to zero by the compiler. If a value is assigned to such a record or array through Unchecked_Conversion, the unused bits can assume any value. This might result in the predefined equality operator returning False even if all visible fields of the two operands are equal.

Task types are treated as pointers (access values) to a task control block. Converting a task type thus converts is address into the target type, not the contents of the task control block.

Converting from Discrete, Fixed, Access, or Task Types to Discrete, Fixed, or Access Types

If Source'Size >= Target'Size, the least significant Target'Size, bits of the source operand are returned. If Source'Size < Target'Size, the source operand is extended to (at least) Target'Size bits —— sign-extended if Source is a signed type and zero-extended otherwise.

Converting from Discrete, Fixed, Access, or Task Types to Float Types

If the source type has fewer bits than the target type, the algorithm is intended to maximize the probability of producing a NaN (Not a Number).

If Source'Size >= Target'Size, the least significant Target'Size bits of the source operand are returned. If Source'Size < Target'Size, the source operand is extended with ones, which usually results in a NaN value.

Converting from Float Types to Discrete, Fixed, or Access Types

If Source'Size >= Target'Size, the low order bits of the source operand are returned. If Source'Size < Target'Size, the source operand is returned in the least significant bits of the result and zero-extended.

Converting from Float Types to Float Types

If Source'Size = Target'Size, the source operand is returned as a value of the target type. This is equivalent to a numerical conversion without range checks. If Source'Size /= Target'Size, the result of the operation is undefined.

Converting from Record or Array Types to Record or Array Types

If Source'Size >= Target'Size, the first Target'Size bits at the address of the source operand are returned. If Source'Size < Target'Size, the source operand is returned in the first.

Source'Size bits of the result, the remaining bits of the result being undefined. On current Apex (big-endian) architectures, the "first bits" means the bits #31, 30, 29, and so on.

Converting from Record or Array Types to Discrete, Fixed, or Access Types

If Source'Size >= Target'Size, the first Target'Size bits at the address of the source operand are returned. If Source'Size < Target'Size, the source operand is returned in the least significant bits of the result, which is otherwise filled with zeros.

Converting from Record or Array Types to Float Types

If Source'Size >= Target'Size, the first Target'Size bits at the address of the source operand are returned. If Source'Size < Target'Size, the source operand is returned in the least significant bits of the result, which is otherwise filled with ones (this should produce a NaN).

Converting from Scalar, Access, or Task Types to Record or Array Types

If Source'Size >= Target'Size, the least significant Target'Size bits of the source operand are returned. If Source'Size < Target'Size, the source operand is returned in the first Source'Size bits of the result, the remaining bits of the result being undefined.

Restrictions on Unchecked Type Conversion

The following restrictions apply to unchecked type conversion:


Input/Output Packages

The Ada language defines specifications for four I/O packages: Sequential_Io, Direct_Io, Low_Level_Io, and Text_Io. The following subsections explain the implementation-dependent characteristics of those four packages provided with Apex.

Sequential_Io (LRM 14.2.2 and 14.2.3)

For the Read procedure of Sequential_Io, the Data_Error exception is raised only when the size of the data read from the file is greater than the size of the out parameter Item.

POSIX Compliance

The Form parameter on subprograms in Sequential_Io is compliant with the POSIX.5 standard. The Form parameter is discussed in detail in "Files and I/O" in the Ada Runtime Guide.

Direct_Io (LRM 14.2.4)

Package Direct_Io may not be instantiated with any type that is either an unconstrained array type or a discriminated record type without default discriminants. A semantic error is reported when an attempt is made to install any unit that contains an instantiation in which the actual type is such a forbidden type.

For the Read procedure of Direct_Io, no check is performed to ensure that the data read from the file can be interpreted as a value of the Element_Type.

Specification of Package Direct_Io (LRM 14.2.5)

The declaration of the type Count in package Direct_Io is:

where Element_Type is the generic formal type parameter.

POSIX Compliance

The Form parameter on subprograms in Direct_Io is compliant with the POSIX.5 standard.The Form parameter is discussed in detail in "Files and I/O" in the Ada Runtime Guide.

Low_Level_Io (LRM 14.6)

Package Low_Level_Io is not provided with Apex.

Text_Io (LRM 14.3)

The Text_Io default input and output files are associated
with the UNIX standard input and standard output paths, respectively.

Specification of Package Text_Io (LRM 14.3.10)

The declaration of the type Count in Text_Io is:

The declaration of the subtype Field in Text_Io is:

Note that not all values of Text_Io.Field can be used in operations of package Text_io. The use of very large values for Field may cause problems on your system.

File-Management Operations

The operations of Get and Put are as described in the Ada LRM.

Data written using Put and Put_Line is not interpreted unless the data being written by Put is Ascii.Ff (a form feed). In this case, an Ascii.Lf (a line feed) is inserted. Data written using Put_Line is followed by the line terminator Ascii.Lf.

Data read using Get and Get_Line is not interpreted except that the line terminator, Ascii.Lf, and the page terminator, Ascii.Ff, are removed from the input stream.

POSIX Compliance

The Form parameter on subprograms in Text_Io is compliant with the POSIX.5 standard. The Form parameter is discussed in detail in "Files and I/O" in the Ada Runtime Guide.


Parameter Passing

Parameters are passed in registers or by pushing values (or addresses) on the stack, or by using a combination of registers and stack locations.

For calls to Ada procedures extra information (hidden parameters) may be passed for arrays (dope vector address), or for records ('CONSTRAINED), or for up-level references in nested procedures (static link). Dope vector addresses are passed immediately following the parameter with which they are associated. A static link, if required, is passed as the final parameter to a procedure.

In general, small results are returned in registers; large results with known targets are passed by reference. Large results of anonymous target and known size are passed by reference to a temporary created on the caller's stack. Large results of anonymous target and unknown size are returned by copying the value down from a temporary in the callee so the space used by the temporary can be reclaimed.

When only Ada programs and subprograms are being called, Apex may sometimes follow calling conventions different from those used by compilers for other languages. However, when interface calls are made using pragma Export or pragma import, Apex will generate code sequence that conforms to a standard.

Additional information on interface programming is available in Interfacing with Other Languages.

Machine Code Insertions may be used to explicitly build a call interface when compiler conventions are not compatible or when interfacing to assembly language.

The exact details of parameter passing are highly dependent on the target architecture. Additional information is available for each target processor. Select the desired section from the following list:

Parameter Passing - Sun SPARC (32-bit)

For a detailed description on SPARC 32-bit calling conventions, please refer to the 32-bit Application Binary Interface (ABI) manual available for purchase or free download from Sparc International at http://www.sparc.org/.

What follows is a brief description on the roles of various registers in standard function calling sequence, based on the 32-bit ABI from Sparc International.

SPARC has 32 integer registers and 32 floating-point registers, that are accessible to any program, at any time. Of these, 8 integer registers and 32 floating-point registers are global to the program. All remaining 24 integer registers are windowed by way of save and restore instructions (in the prologue and epilogue, respectively, of the routine). Sets of 24 overlap each other by 8 registers each there by making caller's out registers coincide with callee's in registers.

The integer registers are named, global (%g0 to %g7), out (%o0 to %o7), local (%l0 to %l7), in (%i0 to %i7). The floating point registers are represented as %f0, %f1, ..., %f31. These are single precision floating-point registers. These registers are used in pairs for storing double precision values and are accessible as %d0, %d2, ..., %d30 (%d0 is %f0%f1, and so on).

Register Usage in Standard Calls

The following discussion assumes that register window is enabled by way of save and restore instructions. The compiler will not generate these instructions in a Machine_Code routine in the presence of "pragma Implicit_Code(Off);" statement, in which case, the current routine's register window is same as the caller's register window. In the presence of a register window, caller's %l0 through %l7 and %i0 through %i7 registers are not accessible from within the callee.

All the 32 floating-point registers are volatile across function calls.

Parameter Passing - Sun SPARC V9 (64-bit)

For a detailed description on SPARC V9 64-bit calling conventions, please refer to the 64-bit Application Binary Interface (ABI) manual available for purchase or free download from Sparc International at http://www.sparc.org/. What follows is a brief description on the roles of various registers in standard function calling sequence, based on the 64-bit ABI from Sparc International.

SPARC V9 has 32 integer registers, 32 single precision (32-bit) floating-point registers, and 16 double precision (64-bit) floating-point registers (these are present in SPARC V9 only), that are accessible to any program, at any time. Of these, 8 integer registers and all floating-point registers are global to the program. All remaining 24 integer registers are windowed by way of save and restore instructions (in the prologue and epilogue, respectively, of the routine). Sets of 24 overlap each other by 8 registers each there by making caller's out registers coincide with callee's in registers.

The integer registers are named, global (%g0 to %g7), out (%o0 to %o7), local (%l0 to %l7), in (%i0 to %i7). The single precision floating point registers are represented as %f0, %f1, ..., %f31. These registers are used in pairs for storing double precision values and they are accessible as %d0, %d2, ..., %d30 (%d0 is %f0%f1, and so on). The SPARC V9 specific double precision floating-point registers are accessible as %d32, %d34, ..., %d62 (%d32 is not equivalent to %f32%f33 register pair since, %d32 through %d62 are pure double precision float registers). SPARC V9 also supports quad precision (128-bit) floating-point registers and they overlap the 32-bit float registers and 64-bit float registers, and are accessible as %q0, %q4, ... %q28, %q32, ..., %q60, where %q0 is same as the quadruple %f0%f1%f2%f3 or pair %d0%d2, and so on till %q28. From %q32 onwards, there are no single precision float registers. So %q32 is equivalent to the register pair %d32%d33, so on. Apex Ada compiler does not support quad precision float types yet.

Register Usage in Standard Calls

The following discussion assumes that register window is enabled by way of save and restore instructions. The compiler will not generate these instructions in a Machine_Code routine in the presence of "pragma Implicit_Code(Off);" statement, in which case, the current routine's register window is same as the caller's register window. In the presence of a register window, caller's %l0 through %l7 and %i0 through %i7 registers are not accessible from within the callee.

Parameter Passing - Alpha Architecture

For a detailed description of Alpha calling conventions, please refer to the following document:

Digital Unix - Calling standard for Alpha Systems
Part Number: AA-PYBAC-TE

Available on-line in HTML or PDF format from Compaq Computer Corporation.

Additional Alpha documentation is available at http://tru64unix.compaq.com/faqs/publications/pub_page/doc_list.html

What follows here is a brief description of the register conventions use in a typical Ada calling sequence.

Table 32 General Registers
Register
Synonym
Description
R0
V0
Integer result register.
R1-R8
T0-T7
Scratch registers; not preserved across calls.
R9-R15
S0-S6
Saved registers; must be preserved across calls.0
R13
S4
Argument-Pointer (Apex Ada).
R14
S5
Stack-Limit register (Apex Ada).
R15
S6,FP
Frame-pointer or saved register.
R16-21
A0-A5
Integer argument registers; not preserved across calls.
R27
PV,T12
Procedure value register.
R28
At
Assembler temporary; reserved for compiler use in address calculations.
R29
GP
Global pointer.
R30
SP
Stack pointer.
R31
zero
Zero register; reads as zero when used as a source operand. Has no effect when used as a result operand.

Table 33 Floating-Point Registers
Register
Description
F0
Floating-point result register.
F1
Scratch register. Also used to return the imaginary part of a complex number in a standard C call.
F2-F9
Saved registers; must be preserved across calls.
F10-F15
Scratch registers; not preserved across calls.
F16-21
Argument registers; not preserved across calls.
F22-F30
Scratch registers; not preserved across calls.
F31
FZERO register; reads as zero when used as a source operand. Has no effect when used as a result operand.

Typical Ada Calling Sequence

1 . The caller passes up to six arguments in registers. The first argument is passed in R16 (scalar) or F16 (float). The second argument is passed in R17 or F17, and so on, up to R21/F21. The remaining arguments are passed on the stack.

2 . Caller loads PV (R27) with the procedure value (address) of the routine to be called, and transfers control to called routine. The return address is in RA (R26).

3 . The called routine loads its GP value relative to the PV.

4 . The called routine checks if there is sufficient space available on the stack for its local storage. If not, a Storage_Error exception is raised.

5 . The called routine modifies the SP to allocate space for local storage.

6 . The called routine saves the return address (RA), and any registers in the set S0-S6 and F2-F9 that are modified by the routine.

7 . A trap barrier marks the end of the standard prologue. At this point none of the saved registers (S0-S6, F2-F9) have been modified, so the context of the calling routine is still intact.

8 . The called routine sets up a frame-pointer (S6 or FP) and an argument pointer (s4 or AP), if needed.

9 . The body of the called routine executes.

10 . The called routine puts the function result in V0 or F0.

11 . The return address (RA) and saved registers are restored.

12 . The stack pointer is restored, reclaiming local storage.

13 . The called routine returns to the caller.

14 . The caller re-loads its GP value relative to the return address.

15 . The caller assigns any result or out parameters to its local storage or static locations, if needed.

Parameter Passing - HP-PA

For a detailed description on PA-RISC calling conventions, please refer to the following documents:

32-Bit PA-RISC Run-Time Architecture (HP-UX 10.20)
32-Bit PA-RISC Run-Time Architecture (HP-UX 11.00)
64-Bit Run-Time Architecture for PA-RISC 2.0

Additional PA-RISC documentation can be found at http://devresource.hp.com/STK/toc_ref.html#PA-RISC and http://docs.hp.com

What follows here is a brief description of the register conventions use in a typical Ada calling sequence.

Table 34 General Registers
Register
Synonyms
Description
GR0

Zero value register
GR1

Scratch register
GR2
RP
Return pointer and scratch register
GR3-GR18

Callee-saves registers
GR18

Stack limit register (Apex Ada)
GR19

Linkage Table Pointer register (LTP)
GR19-GR22

Caller-saves registers
GR23
arg3
Argument word 3
GR24
arg2
Argument word 2
GR25
arg1
Argument word 1
GR26
arg0
Argument word 0
GR27
DP
Data pointer
GR28-GR29

Return value registers
GR31

Millicode return pointer or scratch register (caller-saves)
GR30
SP
Stack pointer

Table 35 Space Register
Register
Synonyms
Description
SR0

Caller-saves space register or millicode return space register
SR1
sarg sret
Space argument and return register or caller-saves space register
SR2

Caller-saves space register
SR3

Callee-saves space register
SR4

Code space register
SR5

Data space register (privileged)
SR6-SR7

System space registers (privileged)

Table 36 Floating-Point Registers
Register
Synonyms
Description
FR0-FR3

Floating-point status and exception
FR4
farg0 fret
Floating-point argument, return value
FR5
farg1
Second floating-point argument
FR6
farg2
Third floating-point argument
FR7
farg3
Fourth floating-point argument
FR8-FR11

Caller-saves register
FR12-FR21

Callee-saves register
FR22-FR31

Caller-saves register

Parameter Passing - IBM RS/6000

For a detailed description on IBM RS/6000 calling conventions, please refer to the following document:

SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement, Sun Microsystems and IBM, September 1995. Part Number: 802-3334-10.

Also available from ESOFTA at http://www.esofta.com/pdfs/SVR4abippc.pdf

What follows is a brief description of the register conventions followed in a typical Ada calling sequence.

Table 37 General Registers
Register
Preserved Across Calls
Description
r0
No
Volatile register which may be modified during function linkage (prolog/epilog)
r1
Usually
Stack pointer, always valid.
r2
Yes
TOC pointer. Calling routine needs to do explicit reload of TOC pointer following any call.
r3-r4
No
Volatile registers used for parameter passing. and return values.
r5-r10
No
Volatile registers used for parameter passing.
r11-r12
No
Volatile registers which may be modified during function linkage.
r13
Yes
SDA base.
r14
Yes
Stack limit register (Apex Ada).
r15-r30
Yes
Non-volatile registers.
r31
Yes
Frame pointer.

Table 38 Float-Point Registers
Register
Preserved Across Calls
Description
f0
No
Scratch register.
f1
No
Volatile registers used for parameter passing and return values.
f2-f13
No
Volatile registers used for parameter passing.
f14-f31
Yes
Non-volatile registers.

Table 39 Special Purpose Registers
Register
Preserved Across Calls
Description
CR0
No
Implicitly used by integer instructions with record bit set.
CR1
No
Implicitly used by floating-point instructions with record bit set.
CR2-4
Yes
General use.
CR5-7
No
General use.
LR
No
Link register.
CTR
No
Count register.
XER
No
Fixed-point exception register.
FPSCR
No
Floating-point status and control register.
MQ
No
Obsolete. Exists only on RS6000 and PPC601.

Typical Ada Calling Sequence

1 . The caller passes scalar arguments in r3-r10; floating-point arguments in fr1-fr13; other arguments are passed on the stack. Mixing integer and floating-point parameters causes integer parameter registers to be skipped. For example, if (integer, float, integer) are passed then (r3, f1, r5) are used, not (r3, f1, r4). If the called routine is a foreign (non-Ada) routine (i.e. Pragma Import(C...)), then the caller saves the FPSCR prior to the call.

2 . Control is transferred to the called routine.

3 . The called routine allocates space for the frame and locals, and performs a stack overflow check (if not suppressed).

4 . Called routine saves floating-point registers in fr14-fr31, general registers in r13-r31, and condition register fields in cr2-cr4 that will be modified. (Sufficient space is allocated to save all these registers, but only the registers that are modified are saved and restored).

5 . Body of the called routine executes.

6 . Any function result is left in r3 or f1.

7 . Saved registers are restored.

8 . The space for the frame and locals is deallocated.

9 . The called routine returns to the caller.

10 . If the called routine was a foreign routine, the caller clears bits 0-3 of XER and restores the FPSCR.

11 . The caller assigns any result or out parameters to its local storage or static locations, if necessary.

Parameter Passing - M68k Family

When only Ada programs and subprograms are being called, Apex passes parameters using registers. The following conventions for passing parameters in registers is used:

1 . For scalar and access parameters (integers, enumerations, addresses and fixed point numbers), the first two parameters are passed (or returned) in D2 and D3. Subsequent parameters are passed on the stack.

2 . For floating point parameters (with hardware floating point), the first four parameters are passed (or returned) in fp0, fp1, fp2 and fp3. Subsequent parameters are passed on the stack.

3 . Registers d2 and d3 are scratch registers, i.e., they are no longer saved across calls. In this respect, they are like a0, a1, d0 and d1.

Note: Register parameters are incompatible with the standard MC68020 calling conventions. However, calls to subprograms with pragma Interface are called using the standard calling conventions.

Small results are returned in registers; large results with known targets are passed by reference. Large results of anonymous target and known size are passed by reference to a temporary created on the caller's stack. Large results of anonymous target and unknown size are returned by copying the value down from a temporary in the callee so the space used by the temporary can be reclaimed.

The compiler assumes the following calling conventions:

1 . caller copies register parameters into d2-d3 and fp0-fp3 as described above.

2 . caller pushes remaining arguments on stack in reverse order from their declaration.

3 . caller calls callee.

4 . callee builds display and allocates space for local variables with the LINK instruction.

5 . callee pushes any registers it uses in the sets d4-d7 and a2-a5 and fp4-fp7 if the M68881 is being used.

6 . callee executes.

7 . callee pops registers pushed in Step 5.

8 . callee leaves result in d0 or fp0 if callee is a function.

9 . callee deallocates local variables with the unlk instruction.

10 . callee returns to caller.

11 . caller copies back any out parameters or function values.

12 . caller deallocates the space used for arguments on the stack.

Note: Compilers for other languages follow calling conventions different from those used by Apex. When calling foreign language subprograms (with pragma Interface) or in routines callable from foreign languages (with pragma External), the caller allocates stack space for each parameter passed in a register plus an additional word in accordance with C compiler conventions. Also, floating point parameters are passed in the integer registers.

Machine code insertions can be used to explicitly build a call interface when compiler conventions are not compatible or when interfacing to assembly language.

For example, suppose an interface to a C function Pass_Int is desired, where the C compiler generated code such that the callee deallocates space for the parameters.

The following Ada code provides a wrapper to call this function, while allowing the C function to handle the deallocation.

Parameter Passing - PowerPC Family

For a detailed description of PowerPC calling conventions, please refer to the following document:

PowerPC Embedded Application Binary Interface, Version 1.0,
IBM and Motorola, January 10, 1995.

Available in PDF format from ESOFTA

What follows here is a brief description of the register conventions used in a typical Ada calling sequence.

Table 40 General Registers
Register
Preserved Across Calls
Description
r0
No
Volatile register which may be modifed during function linkage (prolog/epilog).
r1
Usually
Stack pointer, always valid.
r2
Yes
SDA2 base.
r3-r4
No
Volatile registers used for parameter passing. and return values.
r5-r10
No
Volatile registers used for parameter passing.
r11-r12
No
Volatile registers which may be modified during function linkage.
r13
Yes
SDA base.
r14
Yes
Stack limit register (Apex Ada).
r15-r29
Yes
Non-volatile registers.
r30
Yes
Argument pointer (if needed).
r31
Yes
Frame pointer.

Table 41 Float-Point Registers
Register
Preserved Across Calls
Description
f0
No
Scratch register
f1
No
Volatile registers used for parameter passing and return values.
f2-f8
No
Volatile registers used for parameter passing.
f9-f13
No
Volatile registers.
f14-f31
Yes
Non-volatile registers.

Table 42 Special Purpose Registers
Register
Preserved Across Calls
Description
CR0
No
Implicitly used by integer instructions with record bit set.
CR1
No
Implicitly used by floating-point instructions with record bit set.
CR2-4
Yes
General use.
CR5-7
No
General use.
LR
No
Link register.
CTR
No
Count register.
XER
No
Fixed-point exception register.
FPSCR
No
Floating-point status and control register.
MQ
No
Obsolete. Exists only on PPC601.

Typical Ada Calling Sequence

1 . The caller passes scalar arguments in r3-r10; floating-point arguments in fr1-fr8; other arguments are passed on the stack. Mixing integer and floating-point parameters does not cause integer parameter registers to be skipped. For example, if (integer, float, integer) are passed then (r3, f1, r4) are used, not (r3, f1, r5). If the called routine is a foreign (non-Ada) routine (i.e. Pragma Import(C...)), then the caller saves the FPSCR prior to the call.

2 . Control is transferred to the called routine.

3 . The called routine assigns stack pointer r1 to frame pointer r31 (if necessary), allocates space for frame and locals and performs a stack overflow check (if not suppressed).

4 . The called routine saves floating-point registers in fr14-fr31, general registers in r13-r31, and condition register fields in cr2-cr4, that will be modified.

5 . If needed, the called routine sets up an argument pointer in r30.

6 . Body of the called routine executes.

7 . Any function result is left in r3 or f1.

8 . Saved registers are restored.

9 . The space for the frame and locals is deallocated.

10 . The called routine returns to the caller.

11 . If the called routine was a foreign routine, the caller clears bits 0-3 of XER and restores the FPSCR.

12 . The caller assigns any result or out parameters to its local storage or static locations, if necessary.

Parameter Passing - MIPS Family

For a detailed description of MIPS calling conventions, please refer to the following documents:

MIPSpro N32 ABI Handbook
IRIX 6.3
- Books (document number: 007-2816-004)

MIPSpro 64-Bit Porting and Transition Guide
IRIX 6.3
- Books (document number: 007-2391-006)

These documents can be located on-line from the SGI TechPubs Library.

What follows is a brief overview on the roles of various registers in a typical Ada calling sequence.

Table 43 General Registers
Register
Synonym
Description
R0

Always zero.
R1
at
Assembler temporary. Reserved for compiler.
R2-R3
v0-v1
Integer result registers.
R4-R7
a0-a3
Integer argument registers.
R8-R11
t0-t4,a4-a7
Temporary registers, or additional integer argument registers (N32/N64 standard only).
R12-R15
t0-t7
Temporary registers.
R16-R22
s0-s6
Saved registers; must be preserved across calls.
R23
s7
Stack-Limit (Apex Ada). Must be preserved across calls.
R24-R25
t8-t9
Temporary registers.
R26-R27
k0-k1
Kernel registers. Reserved for OS.
R28
gp
Global pointer.
R29
sp
Stack pointer.
R30
s8, fp
Saved register, or frame pointer. Must be preserved across calls.
R31
ra
Return address register.

Table 44 Floating-Point Registers
Register
Description
F0-F2
Floating-point result registers.
F4-F10
Temporary registers.
F12-F14
Floating-point argument registers.
F16..F18
Temporary registers.
F20-F30
Saved registers; must be preserved across calls.

Typical Ada Calling Sequence

1 . The Caller passes scalar arguments in a0, a1, a2 and a3 and floating pointer arguments in f12 and f14. Other arguments are passed on the stack.

2 . Caller transfer control to the called routine.

3 . The called routine calculates space for local storage and performs a stack overflow check (unless suppressed). If there is sufficient space on the stack, SP is adjusted to create the space for local storage, otherwise a Storage_Error exception is raised.

4 . The called routine preserves registers in the set s0-s7, sp, s8 and ra if they are used. Registers f20 through f30 are also saved if used.

5 . The Called routine sets up a frame pointer (r30, aka fp) if the sp is modified in the body of the routine, otherwise a virtual frame pointer is used.

6 . The body of the called routine executes.

7 . If the called routine is a function, scalar results are returned in v0-v1 and floating-point results are returned in F0-F2.

8 . Saved registers are restored.

9 . The stack pointer is restored, reclaiming local storage.

10 . The called routine returns to the caller.

Parameter Passing - RH-32

When calling other languages, parameters are passed in registers and by pushing values (or addresses) on the stack. Extra information is passed for records ('CONSTRAINED) and for arrays (dope vector address).

Small results are returned in registers; large results with known targets are passed by reference. Large results of anonymous target and known size are passed by reference to a temporary created on the caller's stack. Large results of anonymous target and unknown size are returned by copying the value down from a temporary in the callee so the space used by the temporary can be reclaimed.

1 . caller passes scalar arguments in a0, a1, a2 and a3 and floating pointer arguments in f6 and f7. Other arguments are passed on the stack. Inter-language calls (for example, from a C routine to an Ada routine or from an Ada routine to a C routine) use the standard RH32 calling convention. To call a C procedure, declare the Ada interface using pragma Interface (language, subprogram). To declare an Ada procedure that is called from C or FORTRAN, use pragma External (language, subprogram).

2 . caller calls callee.

3 . callee allocates space for locals, if needed, by subtracting from the stack pointer. If the stack pointer is changed, a stack overflow check is executed.

4 . callee preserves registers in the set s0-s7, sp, s8 and ra if they are used. Also, registers f10 through f15 are saved if used.

5 . callee copies the display, if needed.

6 . callee sets up a frame pointer (r30, aka fp) if the sp is modified by code during the call. Otherwise, a virtual frame pointer is used.

7 . callee executes.

8 . callee puts return result in v0 or f0.

9 . saved registers are restored.

10 . the stack pointer is restored, reclaiming local storage.

11 . the callee returns to the caller.

Machine code insertions can be used to explicitly build a call interface when compiler conventions are not compatible or when interfacing to assembly language.

It is important to understand the referencing of parameters when using machine code insertions. Parameters cannot be treated like memory locations since in may cases, they are being held in registers. Attempting to treat a parameter held in a register like a memory location causes a compiler error.

Apex passes one or more parameters in registers. The Machine_Code package expects references to parameters (via the 'REF attribute) to be consistent with what Apex expects. For example, on RH32-based systems, the compiler passes the first 4 scalar parameters in registers a0-a3 and the first 2 floating parameters in f6 and f7. On the RH32, the ld_w instruction is used to move a value from a memory location into a register, while the Apex move mnemonic is the equivalent of moving a value from one register to another. Given the following example:

Since the first 4 scalar parameters are passed in registers, p1 is in a register, while p5 is on the stack. Therefore (B) and (C) are legal, while (A) and (D) flag p1/p5 as being illegal operands.

Parameter Passing - Intel Architecture

Apex Ada uses the following calling conventions:

1 . The caller pushes arguments on stack in reverse order from their declaration

2 . The caller transfers control to the called routine

3 . The called routine pushes EBP on stack, and sets EBP to the new ESP (i.e. EBP points at the location of the old EBP).

4 . The called routine computes space for local variables and reforms a storage check (unless suppressed). If there is sufficient space on the stack, ESP is adjusted to create the space for local variables, otherwise a storage_error exception is raised. Except for the storage check, steps 3 and 4 are equivalent to the ENTER instruction.

5 . If the called routine has an external C interface (i.e. Pragma Export(C...)), then ESI, EDI, and EBX are saved on the stack.

6 . The body of the called routine executes.

7 . If the called routine is a function, scalar results are returned in EAX, and floating-point results are returned in ST(0).

8 . Registers saved in step 5 are restored.

9 . The called routine deallocates space for local variables, and restores EBP. This is done using the LEAVE instruction.

10 . The called routine returns to the caller.

11 . The caller copies back any out parameters or function value.

12 . The caller deallocates space used for arguments on the stack

Machine code insertions can be used to explicitly build a call interface when compiler conventions are not compatible or when interfacing to assembly language.

For example, suppose an interface to a C function Pass_Int is desired, where the C compiler generated code such that the callee deallocates space for the parameters:

The following Ada code provides a wrapper to call this function, while allowing the C function to handle the deallocation:


Other Implementation-Dependent Features

Machine Code (LRM 13.8)

Machine-code insertions are supported at this time for all platforms. Machine-code insertions are described in detail in Machine Code Insertions.


Rational Software Corporation 
http://www.rational.com
support@rational.com
techpubs@rational.com
Copyright © 1993-2004, Rational Software Corporation. All rights reserved.
TOC PREV NEXT INDEX DOC LIST MASTER INDEX TECHNOTES APEX TIPS