Skip to main content

13.7 The Package System


This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue


[For each implementation there is a library package called System which includes the definitions of certain configuration-dependent characteristics.]

Static Semantics


The following language-defined library package exists:

implementation defined
The contents of the visible part of package System.
package System 
   with  Pure is 
4type Name is implementation-defined-enumeration-type;
   System_Name : constant Name := implementation-defined;
5-- System-Dependent Named Numbers:
6Min_Int               : constant := root_integer'First;
   Max_Int               : constant := root_integer'Last;
7Max_Binary_Modulus    : constant := implementation-defined;
   Max_Nonbinary_Modulus : constant := implementation-defined;
8Max_Base_Digits       : constant := root_real'Digits;
   Max_Digits            : constant := implementation-defined;
9Max_Mantissa          : constant := implementation-defined;
   Fine_Delta            : constant := implementation-defined;
10Tick                  : constant := implementation-defined;
11-- Storage-related Declarations:
12type Address is implementation-defined;
   Null_Address : constant Address;
13Storage_Unit : constant := implementation-defined;
   Word_Size    : constant := implementation-defined * Storage_Unit;
   Memory_Size  : constant := implementation-defined;
-- Address Comparison: function "<" (Left, Right : Address) return Boolean with Convention => Intrinsic; function "<="(Left, Right : Address) return Boolean with Convention => Intrinsic; function ">" (Left, Right : Address) return Boolean with Convention => Intrinsic; function ">="(Left, Right : Address) return Boolean with Convention => Intrinsic; function "=" (Left, Right : Address) return Boolean with Convention => Intrinsic; -- function "/=" (Left, Right : Address) return Boolean; -- "/=" is implicitly defined 15/2
-- Other System-Dependent Declarations: type Bit_Order is (High_Order_First, Low_Order_First); Default_Bit_Order : constant Bit_Order := implementation-defined; 16-- Priority-related declarations (see D.1): subtype Any_Priority is Integer range implementation-defined; subtype Priority is Any_Priority range Any_Priority'First .. implementation-defined; subtype Interrupt_Priority is Any_Priority range Priority'Last+1 .. Any_Priority'Last; 17Default_Priority : constant Priority := (Priority'First + Priority'Last)/2; 18private ... -- not specified by the language end System;

Name is an enumeration subtype. Values of type Name are the names of alternative machine configurations handled by the implementation. System_Name represents the current machine configuration.


The named numbers Fine_Delta and Tick are of the type universal_real; the others are of the type universal_integer.


The meanings of the named numbers are:


[ Min_Int
The smallest (most negative) value allowed for the expressions of a signed_integer_type_definition.

The largest (most positive) value allowed for the expressions of a signed_integer_type_definition.

A power of two such that it, and all lesser positive powers of two, are allowed as the modulus of a modular_type_definition.

A value such that it, and all lesser positive integers, are allowed as the modulus of a modular_type_definition.
There is no requirement that Max_Nonbinary_Modulus be less than or equal to Max_Binary_Modulus, although that's what makes most sense. On a typical 32-bit machine, for example, Max_Binary_Modulus will be 2**32 and Max_Nonbinary_Modulus will be 2**31, because supporting nonbinary moduli in above 2**31 causes implementation difficulties.

The largest value allowed for the requested decimal precision in a floating_point_definition.

The largest value allowed for the requested decimal precision in a floating_point_definition that has no real_range_specification. Max_Digits is less than or equal to Max_Base_Digits.

The largest possible number of binary digits in the mantissa of machine numbers of a user-defined ordinary fixed point type. (The mantissa is defined in Annex G.)

The smallest delta allowed in an ordinary_fixed_point_definition that has the real_range_specification range –1.0 .. 1.0. ]

A period in seconds approximating the real time interval during which the value of Calendar.Clock remains constant.
There is no required relationship between System.Tick and Duration'Small, other than the one described here.
The inaccuracy of the delay_statement has no relation to Tick. In particular, it is possible that the clock used for the delay_statement is less accurate than Calendar.Clock.
We considered making Tick a run-time-determined quantity, to allow for easier configurability. However, this would not be upward compatible, and the desired configurability can be achieved using functionality defined in Annex D, “Real-Time Systems”.

The number of bits per storage element.

The number of bits per word.

An implementation-defined value [that is intended to reflect the memory size of the configuration in storage elements.]
It is unspecified whether this refers to the size of the address space, the amount of physical memory on the machine, or perhaps some other interpretation of “memory size”. In any case, the value has to be given by a static expression, even though the amount of memory on many modern machines is a dynamic quantity in several ways. Thus, Memory_Size is not very useful.

Address is a definite, nonlimited type with preelaborable initialization (see 10.2.1). Address represents machine addresses capable of addressing individual storage elements. Null_Address is an address that is distinct from the address of any object or program unit.

The implementation has to ensure that there is at least one address that nothing will be allocated to; Null_Address will be one such address.
Address is the type of the result of the attribute Address.
Address is required to be nonlimited and definite because it is important to be able to assign addresses, and to declare uninitialized address variables.
If System.Address is defined as a private type (as suggested below), it might be necessary to add the Preelaborable_Initialization aspect to the declaration of Address in order that it have preelaborable initialization as required.

Default_Bit_Order shall be a static constant. See 13.5.3 for an explanation of Bit_Order and Default_Bit_Order.

Implementation Permissions


An implementation may add additional implementation-defined declarations to package System and its children. [However, it is usually better for the implementation to provide additional functionality via implementation-defined children of System.]

The declarations in package System and its children can be implicit. For example, since Address is not limited, the predefined "=" and "/=" operations are probably sufficient. However, the implementation is not required to use the predefined "=".

Implementation Advice


Address should be a private type.

This promotes uniformity by avoiding having implementation-defined predefined operations for the type. We don't require it, because implementations may want to stick with what they have.
implementation advice
Type System.Address should be a private type.
implementation note
It is not necessary for Address to be able to point at individual bits within a storage element. Nor is it necessary for it to be able to point at machine registers. It is intended as a memory address that matches the hardware's notion of an address.
The representation of the null value of a general access type should be the same as that of Null_Address; instantiations of Unchecked_Conversion should work accordingly. If the implementation supports interfaces to other languages, the representation of the null value of a general access type should be the same as in those other languages, if appropriate.
Note that the children of the Interfaces package will generally provide foreign-language-specific null values where appropriate. See UI-0065 regarding Null_Address.
NOTE There are also some language-defined child packages of System defined elsewhere.

Extensions to Ada 83

The declarations Max_Binary_Modulus, Max_Nonbinary_Modulus, Max_Base_Digits, Null_Address, Word_Size, Bit_Order, Default_Bit_Order, Any_Priority, Interrupt_Priority, and Default_Priority are added to System in Ada 95. The presence of ordering operators for type Address is also guaranteed (the existence of these depends on the definition of Address in an Ada 83 implementation). We do not list these as incompatibilities, as the contents of System can vary between implementations anyway; thus a program that depends on the contents of System (by using use System; for example) is already at risk of being incompatible when moved between Ada implementations.

Wording Changes from Ada 83

Much of the content of System is standardized, to provide more uniformity across implementations. Implementations can still add their own declarations to System, but are encouraged to do so via children of System.
Some of the named numbers are defined more explicitly in terms of the standard numeric types.
The pragmas System_Name, Storage_Unit, and Memory_Size are no longer defined by the language. However, the corresponding declarations in package System still exist. Existing implementations may continue to support the three pragmas as implementation-defined pragmas, if they so desire.
Priority semantics, including subtype Priority, have been moved to the Real Time Annex.

Extensions to Ada 95

implementation advice
Amendment Type Address is defined to have preelaborable initialization, so that it can be used without restriction in preelaborated units. (If Address is defined to be a private type, as suggested by the , in Ada 95 it cannot be used in some contexts in a preelaborated units. This is an unnecessary portability issue.)
Amendment Default_Bit_Order is now a static constant.
Package System is now Pure, so it can be portably used in more places. (Ada 95 allowed it to be Pure, but did not require that.)

13.7.1 The Package System.Storage_Elements

Static Semantics


The following language-defined library package exists:

package System.Storage_Elements 
   with Pure is 
3type Storage_Offset is range implementation-defined;
4subtype Storage_Count is Storage_Offset range 0..Storage_Offset'Last;
5type Storage_Element is mod implementation-defined;
   for Storage_Element'Size use Storage_Unit;
   type Storage_Array is array
     (Storage_Offset range <>) of aliased Storage_Element;
   for Storage_Array'Component_Size use Storage_Unit;
6-- Address Arithmetic:
function "+"(Left : Address; Right : Storage_Offset) return Address with Convention => Intrinsic; function "+"(Left : Storage_Offset; Right : Address) return Address with Convention => Intrinsic; function "-"(Left : Address; Right : Storage_Offset) return Address with Convention => Intrinsic; function "-"(Left, Right : Address) return Storage_Offset with Convention => Intrinsic; 8/3
function "mod"(Left : Address; Right : Storage_Offset) return Storage_Offset with Convention => Intrinsic; 9-- Conversion to/from integers: 10/3
type Integer_Address is implementation-defined; function To_Address(Value : Integer_Address) return Address with Convention => Intrinsic; function To_Integer(Value : Address) return Integer_Address with Convention => Intrinsic; 11/3
end System.Storage_Elements;
The Convention aspects imply that the attribute Access is not allowed for those operations.
The mod function is needed so that the definition of Alignment makes sense.
implementation defined
The range of Storage_Elements.Storage_Offset, the modulus of Storage_Elements.Storage_Element, and the declaration of Storage_Elements.Integer_Address.

Storage_Element represents a storage element. Storage_Offset represents an offset in storage elements. Storage_Count represents a number of storage elements. Storage_Array represents a contiguous sequence of storage elements.

The index subtype of Storage_Array is Storage_Offset because we wish to allow maximum flexibility. Most Storage_Arrays will probably have a lower bound of 0 or 1, but other lower bounds, including negative ones, make sense in some situations.
This paragraph was deleted.

Integer_Address is a [(signed or modular)] integer subtype. To_Address and To_Integer convert back and forth between this type and Address.

Implementation Requirements


Storage_Offset'Last shall be greater than or equal to Integer'Last or the largest possible storage offset, whichever is smaller. Storage_Offset'First shall be <= (–Storage_Offset'Last).

Paragraph 15 was deleted.

Implementation Advice


Operations in System and its children should reflect the target environment semantics as closely as is reasonable. For example, on most machines, it makes sense for address arithmetic to “wrap around”. Operations that do not make sense should raise Program_Error.

implementation advice
Operations in System and its children should reflect the target environment; operations that do not make sense should raise Program_Error.
For example, on a segmented architecture, X < Y might raise Program_Error if X and Y do not point at the same segment (assuming segments are unordered). Similarly, on a segmented architecture, the conversions between Integer_Address and Address might not make sense for some values, and so might raise Program_Error.
We considered making Storage_Element a private type. However, it is better to declare it as a modular type in the visible part, since code that uses it is already low level, and might as well have access to the underlying representation. We also considered allowing Storage_Element to be any integer type, signed integer or modular, but it is better to have uniformity across implementations in this regard, and viewing storage elements as unsigned seemed to make the most sense.
implementation note
To_Address is intended for use in Address clauses. Implementations should overload To_Address if appropriate. For example, on a segmented architecture, it might make sense to have a record type representing a segment/offset pair, and have a To_Address conversion that converts from that record type to type Address.

Extensions to Ada 95

Package System.Storage_Elements is now Pure, so it can be portably used in more places. (Ada 95 allowed it to be Pure, but did not require that.)

13.7.2 The Package System.Address_To_Access_Conversions

Static Semantics


The following language-defined generic library package exists:

   type Object(<>) is limited private;
package System.Address_To_Access_Conversions  
   with  Preelaborate, Nonblocking, Global => in out synchronized is 
type Object_Pointer is access all Object; function To_Pointer(Value : Address) return Object_Pointer with Convention => Intrinsic; function To_Address(Value : Object_Pointer) return Address with Convention => Intrinsic; 4/3
end System.Address_To_Access_Conversions;

The To_Pointer and To_Address subprograms convert back and forth between values of types Object_Pointer and Address. To_Pointer(X'Address) is equal to X'Unchecked_Access for any X that allows Unchecked_Access. To_Pointer(Null_Address) returns null. For other addresses, the behavior is unspecified. To_Address(null) returns Null_Address. To_Address(Y), where Y /= null, returns Y.all'Address.

The programmer should ensure that the address passed to To_Pointer is either Null_Address, or the address of an object of type Object. (If Object is not a by-reference type, the object ought to be aliased; recall that the Address attribute is not required to provide a useful result for other objects.) Otherwise, the behavior of the program is unspecified; it might raise an exception or crash, for example.
Unspecified is almost the same thing as erroneous; they both allow arbitrarily bad behavior. We don't say erroneous here, because the implementation might allow the address passed to To_Pointer to point at some memory that just happens to “look like” an object of type Object. That's not necessarily an error; it's just not portable. However, if the actual type passed to Object is (for example) an array type, the programmer would need to be aware of any dope that the implementation expects to exist, when passing an address that did not come from the Address attribute of an object of type Object.
One might wonder why To_Pointer and To_Address are any better than unchecked conversions. The answer is that Address does not necessarily have the same representation as an access type. For example, an access value might point at the bounds of an array when an address would point at the first element. Or an access value might be an offset in words from someplace, whereas an address might be an offset in bytes from the beginning of memory.

Implementation Permissions


An implementation may place restrictions on instantiations of Address_To_Access_Conversions.

For example, if the hardware requires aligned loads and stores, then dereferencing an access value that is not properly aligned might raise an exception.
For another example, if the implementation has chosen to use negative component offsets (from an access value), it might not be possible to preserve the semantics, since negative offsets from the Address are not allowed. (The Address attribute always points at “the first of the storage elements...”.) Note that while the implementation knows how to convert an access value into an address, it might not be able to do the reverse. To avoid generic contract model violations, the restriction might have to be detected at run time in some cases.