[Home] [Prev] [Next] [Index]

13.7 The Package System

13.7 The Package System

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

Static Semantics

2
The following language-defined library package exists:

2.a
Implementation defined:  The contents of the visible part of package System and its language-defined children.

3
package System is
   pragma Preelaborate(System);

4
   type Name is implementation-defined-enumeration-type;
   System_Name : constant Name := implementation-defined;

5
   --System-Dependent Named Numbers:

6
   Min_Int               : constant := root_integer'First;
   Max_Int               : constant := root_integer'Last;

7
   Max_Binary_Modulus    : constant := implementation-defined;
   Max_Nonbinary_Modulus : constant := implementation-defined;

8
   Max_Base_Digits       : constant := root_real'Digits;
   Max_Digits            : constant := implementation-defined;

9
   Max_Mantissa          : constant := implementation-defined;
   Fine_Delta            : constant := implementation-defined;

10
   Tick                  : constant := implementation-defined;

11
   --Storage-related Declarations:

12
   type Address is implementation-defined;
   Null_Address : constant Address;


13
   Storage_Unit : constant := implementation-defined;
   Word_Size    : constant := implementation-defined * Storage_Unit;
   Memory_Size  : constant := implementation-defined;

14
   --Address Comparison:
   function "<" (Left, Right : Address) return Boolean;
   function "<="(Left, Right : Address) return Boolean;
   function ">" (Left, Right : Address) return Boolean;
   function ">="(Left, Right : Address) return Boolean;
   function "=" (Left, Right : Address) return Boolean;
-- function "/=" (Left, Right : Address) return Boolean;
   --"/=" is implicitly defined
   pragma Convention(Intrinsic, "<");
   ... --and so on for all language-defined subprograms in this package

15
   --Other System-Dependent Declarations:

   type Bit_Order is (High_Order_First, Low_Order_First);
   Default_Bit_Order : constant Bit_Order;

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;

17
   Default_Priority : constant Priority := (Priority'First + Priority'Last)/2;

18
private
   ... -- not specified by the language
end System;

19
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.

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

21
The meanings of the named numbers are:

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

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

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

25
Max_Nonbinary_Modulus A value such that it, and all lesser positive integers, are allowed as the modulus of a modular_type_definition.

25.a
Ramification: 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.

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

27
Max_Digits 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.

28
Max_Mantissa 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.)

29
Fine_Delta The smallest delta allowed in an ordinary_fixed_point_definition that has the real_range_specification range -1.0 .. 1.0.]

30
Tick A period in seconds approximating the real time interval during which the value of Calendar.Clock remains constant.

30.a
Ramification: There is no required relationship between System.Tick and Duration'Small, other than the one described here.

30.b
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.

30.c
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".

31
Storage_Unit The number of bits per storage element.

32
Word_Size The number of bits per word.

33
Memory_Size An implementation-defined value [that is intended to reflect the memory size of the configuration in storage elements.]

33.a
Discussion:  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.

34
Address is of a definite, nonlimited type. 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.

34.a
Ramification: 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.

34.b
Ramification: Address is the type of the result of the attribute Address.

34.c
Reason: Address is required to be nonlimited and definite because it is important to be able to assign addresses, and to declare uninitialized address variables.

35
See 13.5.3 for an explanation of Bit_Order and Default_Bit_Order.

Implementation Permissions

36
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.] Package System may be declared pure.

36.a
Ramification: 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

37
Address should be of a private type.

37.a
Reason: 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.

37.b
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.

37.c
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.

37.d
Note that the children of the Interfaces package will generally provide foreign-language-specific null values where appropriate. See UI-0065 regarding Null_Address.

NOTES

38 14
There are also some language-defined child packages of System defined elsewhere.

Wording Changes From Ada 83

38.a
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.

38.b
Some of the named numbers are defined more explicitly in terms of the standard numeric types.

38.c
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.

38.d
Priority semantics, including subtype Priority, have been moved to the Real Time Annex.

13.7.1 The Package System.Storage_Elements

Static Semantics

1
The following language-defined library package exists:

2
package System.Storage_Elements is
   pragma Preelaborate(System.Storage_Elements);

3
   type Storage_Offset is range implementation-defined;

4
   subtype Storage_Count is Storage_Offset range 0..Storage_Offset'Last;

5
   type 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:

7
   function "+"(Left : Address; Right : Storage_Offset)
     return Address;
   function "+"(Left : Storage_Offset; Right : Address)
     return Address;
   function "-"(Left : Address; Right : Storage_Offset)
     return Address;
   function "-"(Left, Right : Address)
     return Storage_Offset;

8
   function "mod"(Left : Address; Right : Storage_Offset)
     return Storage_Offset;

9
   --Conversion to/from integers:

10
   type Integer_Address is implementation-defined;
   function To_Address(Value : Integer_Address) return Address;
   function To_Integer(Value : Address) return Integer_Address;

11
   pragma Convention(Intrinsic, "+");
      -- ...and so on for all language-defined subprograms declared in this package.
end System.Storage_Elements;

11.a
Reason: The Convention pragmas imply that the attribute Access is not allowed for those operations.

11.b
The mod function is needed so that the definition of Alignment makes sense.

12
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.

12.a
Reason: 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.

12.b
Note that there are some language-defined subprograms that fill part of a Storage_Array, and return the index of the last element filled as a Storage_Offset. The Read procedures in Streams (see 13.13.1), Streams.Stream_IO (see A.12.1), and System.RPC (see E.5) behave in this manner. These will raise Constraint_Error if the resulting Last value is not in Storage_Offset. This implies that the Storage_Array passed to these subprograms should not have a lower bound of Storage_Offset'First, because then a read of 0 elements would always raise Constraint_Error. A better choice of lower bound is 1.

13
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

14
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).

Implementation Permissions

15
Package System.Storage_Elements may be declared pure.

Implementation Advice

16
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.

16.a
Discussion:  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.

16.b
Reason: 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.

16.c
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.

13.7.2 The Package System.Address_To_Access_Conversions

Static Semantics

1
The following language-defined generic library package exists:

2
generic
    type Object(<>) is limited private;
package System.Address_To_Access_Conversions is
   pragma Preelaborate(Address_To_Access_Conversions);

3
   type Object_Pointer is access all Object;
   function To_Pointer(Value : Address) return Object_Pointer;
   function To_Address(Value : Object_Pointer) return Address;

4
   pragma Convention(Intrinsic, To_Pointer);
   pragma Convention(Intrinsic, To_Address);
end System.Address_To_Access_Conversions;

5
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 (for null of the appropriate type). To_Address(Y), where Y /= null, returns Y.all'Address.

5.a
Discussion:  The programmer should ensure that the address passed to To_Pointer is either Null_Address, or the address of an object of type Object. Otherwise, the behavior of the program is unspecified; it might raise an exception or crash, for example.

5.b
Reason: 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.

5.c
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

6
An implementation may place restrictions on instantiations of Address_To_Access_Conversions.

6.a
Ramification: For example, if the hardware requires aligned loads and stores, then dereferencing an access value that is not properly aligned might raise an exception.

6.b
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.



[Home] [Prev] [Next] [Index]

documentation@rational.com
Copyright © 1993-1998, Rational Software Corporation.   All rights reserved.