Ada '83 Quality and Style:
Guidelines for Professional Programmers
CHAPTER 7: Portability
Ada provides many implementation-dependent features that permit greater
control over and interaction with the underlying hardware architecture than is
normally provided by a high-order language. These mechanisms are intended to
assist in systems programming and real-time programming to obtain greater
efficiency (e.g., specific size layout of variables through representation
clauses) and direct hardware interaction (e.g., interrupt entries) without
having to resort to assembly level programming.
Given the objectives for these features, it is not surprising that you must
usually pay a significant price in portability to use them. In general, where
portability is the main objective, do not use these features. When you must
use these features, encapsulate them in packages well-commented as interfacing
to the particular target environment. This section identifies the various
features and their recommended use with respect to portability.
Language Ref Manual references:
13 Representation Clauses and Implementation-Dependent Features
guideline
- Use algorithms that do not depend on the representation of the data
and therefore do not need representation clauses.
- Use representation clauses when accessing interface data or when a
specific representation is needed to implement a design.
rationale
In many cases, it is easy to use representation clauses to implement an
algorithm, even when it is not necessary. There is also a tendency to
document the original programmer's assumptions about the representation for
future reference. But there is no guarantee that another implementation will
support the representation chosen. Unnecessary representation clauses also
confuse porting or maintenance efforts which must assume that the programmer
depends on the documented representation.
Interfaces to non-Ada systems and external devices are the most common
situations where a representation clause is needed. Uses of pragma Interface
and address clauses should be evaluated during design and porting to determine
whether a representation clause is needed.
note
During a porting effort, all representation clauses can be evaluated as either
design artifacts or specifications for accessing interface data that might
change with a new implementation.
Language Ref Manual references:
13.1 Unchecked Programming,
13.2 Length Clauses,
13.3 Enumeration Representation Clauses,
13.4 Record Representation Clauses,
13.6 Change of Representation
guideline
- Avoid using package System constants except in attempting to
generalize other machine dependent constructs.
rationale
Since the values in this package are implementation-provided, unexpected
effects can result from their use.
exceptions
Do use package System constants to parameterize other implementation-dependent
features (see Pappas [1985] section 13.7.1).
Language Ref Manual references:
13.7 The Package System,
F Implementation-Dependent Characteristics
guideline
- Avoid machine code inserts.
rationale
Appendix C (of Department of Defense 1983)
suggests that the package
implementing machine code inserts is optional. Additionally, it is not
standardized so that machine code inserts are most likely not portable. In
fact, it is possible that two different vendors' syntax will differ for an
identical target and differences in lower-level details such as register
conventions will hinder portability.
exceptions
If machine code inserts must be used to meet another project requirement,
recognize the portability decreasing effects.
In the declarative region of the body of the routine where the machine code
insert is being used, insert comments explaining what function the insert
provides, and (especially) why the insert is necessary. Comment the necessity
of using machine code inserts by delineating what went wrong with attempts to
use other higher-level constructs.
Language Ref Manual references:
13.8 Machine Code Insertions,
C Predefined Language Environment,
F Implementation-Dependent Characteristics
guideline
- Avoid interfacing Ada with other languages.
- Isolate all subprograms employing pragma
Interface
to
implementation-dependent (interface) package bodies.
rationale
The problems with employing pragma Interface
are complex. These problems
include pragma syntax differences, conventions for linking/binding Ada to
other languages, and mapping Ada variables to foreign language variables. By
hiding these dependencies within interface packages, the amount of code
modification can be reduced.
exceptions
It is often necessary to interact with other languages, if only an assembly
language to reach certain hardware features. In these cases, clearly comment
the requirements and limitations of the interface and pragma Interface
usage.
Language Ref Manual references:
13.9 Interface to Other Languages,
B Predefined Language Pragmas
guideline
- Avoid pragmas and attributes added by the compiler implementor.
rationale
The Ada Language Reference Manual (Department of Defense 1983)
permits an
implementor to add pragmas and attributes to exploit a particular hardware
architecture or software environment. These are obviously even more
implementation-specific and therefore less portable than an implementor's
interpretations of the predefined pragmas and attributes.
exceptions
Some implementation-dependent features are gaining wide acceptance in the Ada
community to help alleviate inherent inefficiencies in some Ada features. A
good example of this is the "fast interrupt" mechanism that provides a minimal
interrupt latency time in exchange for a restrictive tasking environment. Ada
community groups (e.g., SIGAda's
ARTEWG)
are attempting to standardize a
common mechanism and syntax to provide this capability. By being aware of
industry trends when specialized features must be used, you can take a more
general approach that will help minimize the porting job.
Language Ref Manual references:
F Implementation-Dependent Characteristics
guideline
rationale
The unchecked storage deallocation mechanism is one method for overriding the
default time at which allocated storage is reclaimed. The earliest default
time is when an object is no longer accessible, e.g., when control leaves the
scope where an access type was declared (the exact point after this time is
implementation- dependent). Any unchecked deallocation of storage performed
prior to this may result in an erroneous Ada program if an attempt is made to
access the object.
This guideline is stronger than Guideline 5.9.2
because of the extreme dependence on
the implementation of Unchecked_Deallocation
. Using it could cause
considerable difficulty with portability.
exceptions
Using unchecked deallocation of storage can be beneficial in local control of
highly iterative or recursive algorithms where available storage may be
exceeded.
Language Ref Manual references:
3.8 Access Types,
4.8 Allocators,
8.2 Scope of Declarations,
13.10.1 Unchecked Storage Deallocation
guideline
rationale
The unchecked type conversion mechanism is, in effect, a means of bypassing
the strong typing facilities in Ada. An implementation is free to limit the
types that may be matched and the results that occur when object sizes differ.
exceptions
Unchecked type conversion is useful in implementation dependent parts of Ada
programs (where lack of portability is isolated) where low-level programming
and foreign language interfacing is the objective.
Language Ref Manual references:
13.9 Interface to Other Languages,
13.10.2 Unchecked Type Conversions
guideline
- Avoid the direct invocation of or implicit dependence upon an
underlying host operating system or Ada run time support system.
rationale
Features of an implementation not specified in the
Ada Language Reference Manual (Department of Defense 1983)
will usually differ between
implementations. Specific implementation-dependent features are not likely to
be provided in other implementations. Even if a majority of vendors eventually
provide similar features, they are unlikely to have identical formulations.
Indeed, different vendors may use the same formulation for (semantically)
entirely different features.
Try to avoid these when coding. Consider the consequences of including system
calls in a program on a host development system. If these calls are not
flagged for removal and replacement, the program could go through development
and testing only to be unusable when moved to a target environment which lacks
the facilities provided by those system calls on the host.
exceptions
In real-time embedded systems, making calls to low-level support system
facilities may often be unavoidable. Isolate the uses of these facilities may
be too difficult. Comment them as you would machine code inserts (see
Guideline 7.6.3); they are, in a sense, instructions for the virtual machine
provided by the support system. When isolating the uses of these features,
provide an interface for the rest of your program to use which can be ported
through replacement of the interface's implementation.
Language Ref Manual references:
F Implementation-Dependent Characteristics
Back to document index