Contents Index Search Previous Next
13.1 Operational and Representation Items Representation Items
0.1/1
{
8652/0009}
[Representation and operational items can be used to specify aspects
of entities. Two kinds of aspects of entities can be specified: aspects
of representation and operational aspects. Representation items specify
how the types and other entities of the language are to be mapped onto
the underlying machine. Operational items specify other properties of
entities. ]
1/1
{
8652/0009}
{representation item} {representation
pragma [distributed]} {pragma,
representation [distributed]} There are
six three kinds of
representation items:
attribute_definition_clauses
for representation attributes, enumeration_representation_clauses,
record_representation_clauses, at_clauses,
representation_clauses,
component_clauses, and
representation
pragmas. [
Representation items specify how the types and other
entities of the language are to be mapped onto the underlying machine.
They can be provided to give more efficient representation or to interface
with features that are outside the domain of the language (for example,
peripheral hardware).
Representation items also specify other specifiable
properties of entities. A representation item applies to an entity identified
by a local_name, which denotes an
entity declared local to the current declarative region, or a library
unit declared immediately preceding a representation pragma in a compilation.]
1.1/1
{
8652/0009}
An {operational item} operational
item is an attribute_definition_clause
for an operational attribute.
1.2/1
{
8652/0009}
[An operational item or a representation item applies to an entity
identified by a local_name, which
denotes an entity declared local to the current declarative region, or
a library unit declared immediately preceding a representation pragma
in a compilation.]
Language Design Principles
1.a.1/1
{8652/0009}
Aspects of representation are intended to refer to properties that
need to be known before the compiler can generate code to create or access
an entity. For instance, the size of an object needs to be known before
the object can be created. Conversely, operational aspects are those
that only need to be known before they can be used. For instance, how
an object is read from a stream only needs to be known when a stream
read is executed. Thus, aspects of representation have stricter rules
as to when they can be specified.
Syntax
2/1
{
8652/0009}
aspect_clause representation_clause
::= attribute_definition_clause
|
enumeration_representation_clause
|
record_representation_clause
|
at_clause
3
local_name
::= direct_name
|
direct_name'
attribute_designator
|
library_unit_name
4/1
{
8652/0009}
A representation pragma is allowed only at places where
an aspect_clause a
representation_clause or
compilation_unit
is allowed.
{representation_clause: See aspect_clause}
Name Resolution Rules
5/1
{
8652/0009}
In
an operational item or a representation item, if the
local_name is a
direct_name,
then it shall resolve to denote a declaration (or, in the case of a
pragma,
one or more declarations) that occurs immediately within the same
declarative_region
as the
representation item. If the
local_name
has an
attribute_designator, then
it shall resolve to denote an implementation-defined component (see
13.5.1)
or a class-wide type implicitly declared immediately within the same
declarative_region as the
representation
item. A
local_name that is a
library_unit_name (only permitted
in a representation pragma) shall resolve to denote the
library_item
that immediately precedes (except for other pragmas) the representation
pragma.
5.a/1
Reason: {8652/0009}
This is a Name Resolution Rule, because we don't want an operational
or a representation item for X to be ambiguous just because
there's another X declared in an outer declarative region. It doesn't
make much difference, since most operational or representation
items are for types or subtypes, and type and subtype names can't be
overloaded.
5.b/1
Ramification: {8652/0009}
The visibility rules imply that the declaration has to occur before the
operational or representation item.
5.c/1
{8652/0009}
For objects, this implies that operational or representation
items can be applied only to stand-alone objects.
Legality Rules
6/1
{
8652/0009}
The
local_name of
an
aspect_clause a representation_clause
or representation pragma shall statically denote an entity (or, in the
case of a
pragma, one or more entities)
declared immediately preceding it in a
compilation,
or within the same
declarative_part,
package_specification,
task_definition,
protected_definition, or
record_definition
as the representation
or operational item. If a
local_name
denotes a [local] callable entity, it may do so through a [local]
subprogram_renaming_declaration
[(as a way to resolve ambiguity in the presence of overloading)]; otherwise,
the
local_name shall not denote
a
renaming_declaration.
6.a
Ramification: The ``statically
denote'' part implies that it is impossible to specify the representation
of an object that is not a stand-alone object, except in the case of
a representation item like pragma Atomic that is allowed inside a component_list
(in which case the representation item specifies the representation of
components of all objects of the type). It also prevents the problem
of renamings of things like ``P.all'' (where P is an access-to-subprogram
value) or ``E(I)'' (where E is an entry family).
6.b
The part about where the denoted
entity has to have been declared appears twice -- once as a Name Resolution
Rule, and once as a Legality Rule. Suppose P renames Q, and we have a
representation item in a declarative_part
whose local_name is P. The fact
that the representation item has to appear in the same declarative_part
as P is a Name Resolution Rule, whereas the fact that the representation
item has to appear in the same declarative_part
as Q is a Legality Rule. This is subtle, but it seems like the least
confusing set of rules.
6.c
7
{representation of an object}
{size (of an object)}
The
representation of an object consists of
a certain number of bits (the
size of the object). These are the
bits that are normally read or updated by the machine code when loading,
storing, or operating-on the value of the object. This includes some
padding bits, when the size of the object is greater than the size of
its subtype.
{gaps} {padding
bits} Such padding bits are considered
to be part of the representation of the object, rather than being gaps
between objects, if these bits are normally read and updated.
7.a
To be honest: {contiguous
representation [partial]} {discontiguous representation
[partial]} Discontiguous representations are allowed,
but the ones we're interested in here are generally contiguous sequences
of bits.
7.b
Ramification:
Two objects with the same value do not necessarily have the same
representation. For example, an implementation might represent False
as zero and True as any odd value. Similarly, two objects (of the same
type) with the same sequence of bits do not necessarily have the same
value. For example, an implementation might use a biased representation
in some cases but not others:
7.c
subtype S is Integer range 1..256;
type A is array(Natural range 1..4) of S;
pragma Pack(A);
X : S := 3;
Y : A := (1, 2, 3, 4);
7.d
The implementation might use
a biased-by-1 representation for the array elements, but not for X. X
and Y(3) have the same value, but different representation: the representation
of X is a sequence of (say) 32 bits: 0...011, whereas the representation
of Y(3) is a sequence of 8 bits: 00000010 (assuming a two's complement
representation).
7.e
Such tricks are not required,
but are allowed.
7.f
Discussion: The value
of any padding bits is not specified by the language, though for a numeric
type, it will be much harder to properly implement the predefined operations
if the padding bits are not either all zero, or a sign extension.
7.g
Ramification: For example,
suppose S'Size = 2, and an object X is of subtype S. If the machine code
typically uses a 32-bit load instruction to load the value of X, then
X'Size should be 32, even though 30 bits of the value are just zeros
or sign-extension bits. On the other hand, if the machine code typically
masks out those 30 bits, then X'Size should be 2. Usually, such masking
only happens for components of a composite type for which packing, Component_Size,
or record layout is specified.
7.h
Note, however, that the formal
parameter of an instance of Unchecked_Conversion is a special case. Its
Size is required to be the same as that of its subtype.
7.i
Note that we don't generally
talk about the representation of a value. A value is considered to be
an amorphous blob without any particular representation. An object is
considered to be more concrete.
8
{aspect of representation
[distributed]} {representation
aspect} {directly specified
(of an aspect of representation of an entity)} A
representation item
directly specifies an
aspect of representation
of the entity denoted by the
local_name,
except in the case of a type-related representation item, whose
local_name
shall denote a first subtype, and which directly specifies an aspect
of the subtype's type.
{type-related (representation
item) [distributed]} {subtype-specific
(of a representation item) [distributed]} {type-related
(aspect) [distributed]} {subtype-specific
(of an aspect) [distributed]} A representation
item that names a subtype is either
subtype-specific (Size and
Alignment clauses) or
type-related (all others). [Subtype-specific
aspects may differ for different subtypes of the same type.]
8.a
To be honest: Type-related
and subtype-specific are defined likewise for the corresponding
aspects of representation.
8.b
To be honest: Some representation
items directly specify more than one aspect.
8.c
Discussion: For example,
a pragma Export specifies the convention
of an entity, and also specifies that it is exported.
8.d
Ramification: Each specifiable
attribute constitutes a separate aspect. An enumeration_representation_clause
specifies the coding aspect. A record_representation_clause
(without the mod_clause) specifies
the record layout aspect. Each representation pragma specifies a separate
aspect.
8.e
Reason: We don't need
to say that an at_clause or a mod_clause
specify separate aspects, because these are equivalent to attribute_definition_clauses.
See J.7, ``At Clauses'',
and J.8, ``Mod Clauses''.
8.f
Ramification:
The following representation items are type-related:
8.g
- enumeration_representation_clause
8.h
- record_representation_clause
8.i
8.j/1
- This
paragraph was deleted.{8652/0009}
External_Tag clause
8.k
8.l
8.m
8.n
8.o/1
- This
paragraph was deleted.{8652/0009}
Read clause
8.p/1
- This
paragraph was deleted.{8652/0009}
Write clause
8.q/1
- This
paragraph was deleted.{8652/0009}
Input clause
8.r/1
- This
paragraph was deleted.{8652/0009}
Output clause
8.s
8.t
8.u
- pragmas Import,
Export, and Convention (when applied to a type)
8.v
- pragmas Atomic
and Volatile (when applied to a type)
8.w
- pragmas Atomic_Components
and Volatile_Components (when applied to an array type)
8.x
- pragma Discard_Names
(when applied to an enumeration or tagged type)
8.y
The
following representation items are subtype-specific:
8.z
- Alignment clause
(when applied to a first subtype)
8.aa
- Size clause (when
applied to a first subtype)
8.bb
The
following representation items do not apply to subtypes, so they are
neither type-related nor subtype-specific:
8.cc
- Address clause
(applies to objects and program units)
8.dd
- Alignment clause
(when applied to an object)
8.ee
- Size clause (when
applied to an object)
8.ff
- pragmas Import,
Export, and Convention (when applied to anything other than a type)
8.gg
- pragmas Atomic
and Volatile (when applied to an object or a component)
8.hh
- pragmas Atomic_Components
and Volatile_Components (when applied to an array object)
8.ii
- pragma Discard_Names
(when applied to an exception)
8.jj
- pragma Asynchronous
(applies to procedures)
8.1/1
{
8652/0009}
An operational item directly specifies an operational aspect
of the type of the subtype denoted by the local_name.
The local_name of an operational
item shall denote a first subtype. An operational item that names a subtype
is type-related. {operational aspect [distributed]}
{directly specified (of an operational
aspect of an entity)} {type-related
(operational item) [distributed]} {type-related
(aspect) [partial]}
8.jj.1/1
Ramification: {8652/0009}
The following operational items are type-related:
8.jj.2/1
8.jj.3/1
8.jj.4/1
8.jj.5/1
8.jj.6/1
9
A representation item that directly specifies
an aspect of a subtype or type shall appear after the type is completely
defined (see
3.11.1), and before the subtype
or type is frozen (see
13.14). If a representation
item is given that directly specifies an aspect of an entity, then it
is illegal to give another representation item that directly specifies
the same aspect of the entity.
9.a/1
Ramification: {8652/0009}
The fact that a representation item (or operational item, see next
paragraph) that directly specifies an aspect of an entity is required
to appear before the entity is frozen prevents changing the representation
of an entity after using the entity in ways that require the representation
to be known.
9.1/1
{
8652/0009}
An operational item that directly specifies an aspect of a type shall
appear before the type is frozen (see 13.14).
If an operational item is given that directly specifies an aspect of
a type, then it is illegal to give another operational item that directly
specifies the same aspect of the type.
9.a.1/1
Ramification: Unlike
representation items, operational items can be specified on partial types.
Since they don't affect the representation, the full declaration need
not be known to determine their legality.
10
For an untagged derived type, no type-related
representation items are allowed if the parent type is a by-reference
type, or has any user-defined primitive subprograms.
10.a/1
Ramification: {8652/0009}
On the other hand, subtype-specific representation items may be given
for the first subtype of such a type, as can operational items .
10.b
Reason: The reason for
forbidding type-related representation items on untagged by-reference
types is because a change of representation is impossible when passing
by reference (to an inherited subprogram). The reason for forbidding
type-related representation items on untagged types with user-defined
primitive subprograms was to prevent implicit change of representation
for type-related aspects of representation upon calling inherited subprograms,
because such changes of representation are likely to be expensive at
run time. Changes of subtype-specific representation attributes, however,
are likely to be cheap. This rule is not needed for tagged types, because
other rules prevent a type-related representation item from changing
the representation of the parent part; we want to allow a type-related
representation item on a type extension to specify aspects of the extension
part. For example, a pragma Pack
will cause packing of the extension part, but not of the parent part.
11/1
{
8652/0009}
{
8652/0011}
Operational
and r Representation aspects of a generic formal parameter
are the same as those of the actual.
Operational and representation
aspects of a partial view are the same as those of the full view.
A type-related representation item is not allowed for a descendant of
a generic formal untagged type.
11.a/1
Ramification: {8652/0009}
Representation items are allowed for types whose subcomponent types or
index subtypes are generic formal types. Operational items and subtype-related
representation items are allowed on descendants of generic formal types.
11.b
Reason: Since it is not
known whether a formal type has user-defined primitive subprograms, specifying
type-related representation items for them is not allowed, unless they
are tagged (in which case only the extension part is affected in any
case).
12
A representation item that specifies the Size
for a given subtype, or the size or storage place for an object (including
a component) of a given subtype, shall allow for enough storage space
to accommodate any value of the subtype.
13/1
{
8652/0009}
A representation
or operational item that is not supported by
the implementation is illegal, or raises an exception at run time.
Static Semantics
14
If two subtypes statically match, then their
subtype-specific aspects (Size and Alignment) are the same.
{statically
matching (effect on subtype-specific aspects) [partial]}
14.a
Reason: This is necessary
because we allow (for example) conversion between access types whose
designated subtypes statically match. Note that it is illegal to specify
an aspect (including a subtype-specific one) for a nonfirst subtype.
14.b
Consider,
for example:
14.c/1
package P1 is
subtype S1 is Integer range 0..2**16-1;
for S1'Size use 16; -- Illegal!
-- S1'Size would be 16 by default.
type A1 is access all S1;
X1: A1;
end P1;
14.d/1
package P2 is
subtype S2 is Integer range 0..2**16-1;
for S2'Size use 32; -- Illegal!
type A2 is access all S2;
X2: A2;
end P2;
14.e/1
procedure Q is
use P1, P2;
type Array1 is array(Integer range <>) of aliased S1;
pragma Pack(Array1);
Obj1: Array1(1..100);
type Array2 is array(Integer range <>) of aliased S2;
pragma Pack(Array2);
Obj2: Array2(1..100);
begin
X1 := Obj2(17)'Unchecked_ Access;
X2 := Obj1(17)'Unchecked_ Access;
end Q;
14.f
Loads and stores through X1
would read and write 16 bits, but X1 points to a 32-bit location. Depending
on the endianness of the machine, loads might load the wrong 16 bits.
Stores would fail to zero the other half in any case.
14.g
Loads and stores through X2
would read and write 32 bits, but X2 points to a 16-bit location. Thus,
adjacent memory locations would be trashed.
14.h
Hence, the above is illegal.
Furthermore, the compiler is forbidden from choosing different Sizes
by default, for the same reason.
14.i
The same issues apply to Alignment.
15/1
{
8652/0040}
A derived type inherits each type-related aspect
of representation
of its parent type that was directly specified before the declaration
of the derived type, or (in the case where the parent is derived) that
was inherited by the parent type from the grandparent type. A derived
subtype inherits each subtype-specific aspect
of representation of
its parent subtype that was directly specified before the declaration
of the derived type, or (in the case where the parent is derived) that
was inherited by the parent subtype from the grandparent subtype, but
only if the parent subtype statically matches the first subtype of the
parent type. An inherited aspect of representation is overridden by a
subsequent representation item that specifies the same aspect of the
type or subtype.
15.a
To be honest: A record_representation_clause
for a record extension does not override the layout of the parent part;
if the layout was specified for the parent type, it is inherited by the
record extension.
15.b
Ramification: If a representation
item for the parent appears after the derived_type_declaration,
then inheritance does not happen for that representation item.
15.1/1
{
8652/0040}
In contrast, whether operational aspects are inherited by a derived
type depends on each specific aspect. When operational aspects are inherited
by a derived type, aspects that were directly specified before the declaration
of the derived type, or (in the case where the parent is derived) that
were inherited by the parent type from the grandparent type are inherited.
An inherited operational aspect is overridden by a subsequent operational
item that specifies the same aspect of the type.
15.b.1/1
Ramification: As with
representation items, if an operational item for the parent appears after
the derived_type_declaration, then
inheritance does not happen for that operational item.
15.b.2/1
Discussion: Currently,
only untagged types inherit operational aspects. We considered writing
this rule that way, but rejected it as that could be too specific for
future operational aspects. (After all, that is precisely the problem
that caused us to introduce ``operational aspects'' in the first place.)
16
Each aspect of
representation of an entity is as follows:
17
- {specified (of
an aspect of representation of an entity)} If
the aspect is specified for the entity, meaning that it is either
directly specified or inherited, then that aspect of the entity is as
specified, except in the case of Storage_Size, which specifies a minimum.
17.a
Ramification: This rule
implies that queries of the aspect return the specified value. For example,
if the user writes ``for X'Size use 32;'', then a query
of X'Size will return 32.
18
- {unspecified
[partial]} If an aspect of representation
of an entity is not specified, it is chosen by default in an unspecified
manner.
18.a/1
Ramification: {8652/0009}
Note that representation items representation_clauses
can affect the semantics of the entity.
18.b
The rules forbid things like
``for S'Base'Alignment use ...'' and ``for S'Base
use record ...''.
18.c
Discussion: The intent
is that implementations will represent the components of a composite
value in the same way for all subtypes of a given composite type. Hence,
Component_Size and record layout are type-related aspects.
18.1/1
{
8652/0040}
{specified (of an operational aspect of an entity)}
If an operational aspect is specified for
an entity (meaning that it is either directly specified or inherited),
then that aspect of the entity is as specified. Otherwise, the aspect
of the entity has the default value for that aspect.
Dynamic Semantics
19/1
{
8652/0009}
{elaboration (aspect_clause) [partial]}
{elaboration (representation_clause)
[partial]} For the elaboration of a
aspect_clause representation_clause,
any evaluable constructs within it are evaluated.
19.a
Ramification: Elaboration
of representation pragmas is covered by the general rules for pragmas
in Section 2.
Implementation Permissions
20
An implementation may interpret aspects of representation
in an implementation-defined manner. An implementation may place implementation-defined
restrictions on representation items.
{recommended
level of support [distributed]} A
recommended
level of support is specified for representation items and related
features in each subclause. These recommendations are changed to requirements
for implementations that support the Systems Programming Annex (see
C.2,
``
Required Representation Support'').
20.a
Implementation defined: The
interpretation of each aspect of representation.
20.b
Implementation defined: Any
restrictions placed upon representation items.
20.c
Ramification: Implementation-defined
restrictions may be enforced either at compile time or at run time. There
is no requirement that an implementation justify any such restrictions.
They can be based on avoiding implementation complexity, or on avoiding
excessive inefficiency, for example.
20.c.1/1
{8652/0009}
There is no such permission for operational aspects.
Implementation Advice
21
{recommended
level of support (with respect to nonstatic expressions) [partial]}
The recommended level of support for all representation
items is qualified as follows:
22
- An implementation need not support
representation items containing nonstatic expressions, except that an
implementation should support a representation item for a given entity
if each nonstatic expression in the representation item is a name that
statically denotes a constant declared before the entity.
22.a
Reason:
This is to avoid the following sort of thing:
22.b
X : Integer := F(...);
Y : Address := G(...);
for X'Address use Y;
22.c
In the above, we have to evaluate
the initialization expression for X before we know where to put the result.
This seems like an unreasonable implementation burden.
22.d
The
above code should instead be written like this:
22.e
Y : constant Address := G(...);
X : Integer := F(...);
for X'Address use Y;
22.f
This allows the expression ``Y''
to be safely evaluated before X is created.
22.g
The constant could be a formal
parameter of mode in.
22.h
An implementation can support
other nonstatic expressions if it wants to. Expressions of type Address
are hardly ever static, but their value might be known at compile time
anyway in many cases.
23
- An implementation need not support
a specification for the Size for a given composite subtype, nor the size
or storage place for an object (including a component) of a given composite
subtype, unless the constraints on the subtype and its composite subcomponents
(if any) are all static constraints.
24
- An aliased component, or a component
whose type is by-reference, should always be allocated at an addressable
location.
24.a/1
Reason: The intent is
that access types, type System.Address, and the pointer used for a by-reference
parameter should be implementable as a single machine address -- bit-field
pointers should not be required. (There is no requirement that this implementation
be used -- we just want to make sure it' s feasible.)
24.b
Implementation Note: Note
that the above rule does not apply to types that merely allow by-reference
parameter passing; for such types, a copy typically needs to be made
at the call site when a bit-aligned component is passed as a parameter.
24.c/1
Ramification: A pragma
Pack will typically not pack so tightly as to disobey the above rule.
A Component_Size clause or record_representation_clause
will typically be y illegal if it disobeys the above rule.
Atomic components have similar restrictions (see C.6,
``Shared Variable Control'').
Incompatibilities With Ada 83
24.d
{incompatibilities with Ada
83} It is now illegal for a representation item
to cause a derived by-reference type to have a different record layout
from its parent. This is necessary for by-reference parameter passing
to be feasible. This only affects programs that specify the representation
of types derived from types containing tasks; most by-reference types
are new to Ada 95. For example, if A1 is an array of tasks, and A2 is
derived from A1, it is illegal to apply a pragma
Pack to A2.
Extensions to Ada 83
24.e/1
{8652/0009}
{extensions to Ada 83} Ada 95 allows additional
aspect_clauses representation_clauses
for objects.
Wording Changes from Ada 83
24.f/1
{8652/0009}
The syntax rule for type_representation_clause
is removed; the right-hand side of that rule is moved up to where it
was used, in aspect_clause representation_clause.
There are two references to ``type representation clause'' in RM83, both
in Section 13; these have been reworded. Also, the representation_clause
has been renamed the aspect_clause
to reflect that it can be used to control more than just representation
aspects.
24.g/1
{8652/0009}
We have defined a new term ``representation item,'' which includes all
representation clauses representation_clauses
and representation pragmas, as well as component_clauses.
This is convenient because the rules are almost identical for all of
them three. We have also defined the new terms ``operational
item'' and ``operational aspects'' in order to conveniently handle new
types of specifable entities.
24.h
All of the forcing occurrence
stuff has been moved into its own subclause (see 13.14),
and rewritten to use the term ``freezing''.
24.i
RM83-13.1(10) requires implementation-defined
restrictions on representation items to be enforced at compile time.
However, that is impossible in some cases. If the user specifies a junk
(nonstatic) address in an address clause, and the implementation chooses
to detect the error (for example, using hardware memory management with
protected pages), then it's clearly going to be a run-time error. It
seems silly to call that ``semantics'' rather than ``a restriction.''
24.j
RM83-13.1(10) tries to pretend
that representation_clauses don't
affect the semantics of the program. One counter-example is the Small
clause. Ada 95 has more counter-examples. We have noted the opposite
above.
24.k
Contents Index Search Previous Next Legal