DDC-I Logo

Sitemap  

DDC-I Ada Compiler System  
Ada83 to Ada95 Migration Risk Assessment

Product Family: DACS, SCORE, TADS
Target CPU:
PC/Windows, PC/LynxOS, SPARC/Solaris, HP/UX, VAX/VMS, 1750A, 68xxx, 80x86, i960, PowerPC
Language:
Ada
Host:
PC/Windows, PC/LynxOS, Sparc/Solaris, Sparc/SunOS, VAX/VMS, HP/UX

The following discusses transitioning from Ada 83 to Ada 95 with focus on risk assessment, management and mitigation. Special attention is given to the areas most likely to affect embedded applications.

General issues
During the development of Ada 95 several texts came out discussing the compatibility issues of Ada 95 versus Ada83. These include the Ada 95 Rationale, Annex X and the Ada Compatibility Guide. The latter provides a very detailed survey of the standard language compatibility issues and also a set of guidelines for modifying Ada 83 source code to avoid most of the upward incompatibilities.

Adapting the existing source code to these guidelines requires in some cases abstaining from using certain Ada 83 features and may possibly lead to less elegant code (in which case the reasons should be documented with appropriate comments). There are, however, several benefits to this approach and - very important in this context - the benefits reduce the risks associated with a subsequent transition to Ada 95.

  1. Applying the guidelines yields source code which is free from most of the standard language incompatibilities (in the words of the Ada Compatibility Guide "all but the obscure incompatibilities").
  2. The resulting source code remains valid Ada 83 and may consequently be fully tested in the existing Ada 83 environment.
  3. The resulting source code becomes syntatically valid Ada 95 (with exception of unconstrained generic formal parameters).
  4. Many of the potential semantic errors an Ada 95 compiler may flag on the Ada 83 source code will now be easily pin-pointed.

Even when applied to the fullest, these guidelines cannot ensure that the result is a valid Ada 95 program. The most important reason for this is the implicit dependence on implementation defined behaviour which almost any real life application exhibits. A simple example could be Ada 95's recommandation of making type Address in package System a private type; if the Ada 83 sources are compiled with an Ada 95 compiler where this is the case, any existing and legal literal value of type Address will be flagged as illegal.

Given these guidelines, the maintainers of an Ada 83 program will typically be able to determine which guidelines will require source changes (a program which does not use floating point types will never need to look for uses of their model oriented attributes), estimate the amount of work involved in making the necessary changes and finally judge the risk (application size growth, platform dependencies, compiler problems etc.) resulting from making these changes.

We will not discuss the areas covered by these general guidelines further here but assume in the following that the issues covered by them have been addressed.

Implementation-specific issues
The next step in the risk assessment for a transitioning from Ada 83 to Ada 95 is to repeat the process but this time look for the non-standard language incompatibilities, i.e. those that result from legal but different implementation defined behaviour. It is unfortunately the very nature of non-standard issues that they cannot be enumerated.

Still, in the following, we will try to point out a number of areas with implementation defined behaviour. Instead of attempting to address Ada application programs in general, we will focus on the areas most likely to affect embedded applications. In doing so, we make certain assumptions.

  1. We assume that the application rely very little or not at all on exceptions at run-time. Ada 95 does not require all exceptions to be raised in exactly the same situations or places as Ada 83. An application which relies on the precise effect in Ada 83 may require a very complicated analysis to determine whether the transition will introduce problems. We disregard such effects here.
  2. We assume that the embedded application has been developed for a particular platform using one Ada compiler. It may therefore depend on features exclusive to that Ada compiler (a risk which is greatly reduced if the application has been used on several platforms or been built using several different Ada compilers).
  3. The interaction with an underlying operating system is assumed to be minimal. We will therefore in general not discuss the possible incompatibilities relating to changes in packages Direct_Io, Sequential_Io and Text_Io.

The Ada 83 Language Reference Manual did not identify precisely where implementation-specific characteristics may exist. The Ada 95 Reference Manual on the other hand provides such a list in Annex M. This list may be used as a starting point for identifying the Ada 83 implementation-specific characteristics the application to be transitioned may depend on. It is, however, important to understand that not only does the list contain many items which are either specific to Ada 95 or irrelavant once the source code is syntactically correct Ada 95, it also may leave out important Ada 83 implementation-specific characteristics where they are language specified in Ada 95 (e.g. rounding to integer of a floating point value exactly halfway between two integers).

Areas affecting embedded applications
Let us now turn discuss some of the implementation-specific characteristics which typically will affect an Ada 83 program.

The effect of pragma Pack is very much left up to the compiler system by both language standards. The standards place no hard requirements on packed records. Packed arrays of type Boolean always have an element size of one bit; compilers targeting the same machine may be assumed to represent constrained values of the packed type String identically and to avoid gaps in packed arrays when the component's type has a size which is a power of 2 times the storage unit. In connection with a transition, it is important to categorize the uses of pragma Pack: Those covered above where the same representation can be expected, those which sole purpose is saving data space and those where the pragma helps obtain a specific representation required e.g. in communication with external devices. The desired effect of the pragma must be verified for any instances of the last category. Where the pragma is found not to result in the desired layout, other representation specifications must be used to ensure the layout in connection with a transition.

Package System is a source of various transition problems. The minimum contents of Ada 95's package System is not a superset of Ada 83's. Additionally, package System is one place which reflects a number of implementation choices; this may be in definitions of standardized entities or it may be in implementation specific extensions. It is recommened that use clauses on package System be avoided in order to reduce the risk of legality issues in the transition and to allow easier identification of which of System's entities the application depends on. It should be pointed out that the Ada 95 standard recommends that the type System.Address be implemented as a private type; even if your Ada 95 compiler system does not follow the advice, the definition of System.Address and the operations provided for it may change (in Ada 83, System.Address was often declared as a signed integer type due to the lack of fundamental unsigned types, in Ada 95, the natural choice is often a modular type which affects any literal values and the results of comparisons).

The attribute Address used on global constants of elementary types with static values may produce different results in Ada 83 and Ada 95. Ada 83 provided no means for specifying in the declaration of such constants that they needed to be allocated in memory rather than always be expanded in the code and so compilers may either produce the expected address value or a nil value. Ada 95 provides ways of ensuring memory allocation (the keyword aliased) and compilers will therefore typically not allocate such constants in memory and generate a nil value if used in an Address attribute.

Package Generic_Elementary_Functions is provided by both Ada 83 (through the later standard ISO/IEC DIS 11430) and Ada 95. However, the interface is not exactly the same. The most relevant differences from a transition perspective are that the Ada 95 version is defined as a child unit (but this difference is easily overcome by introducing a renaming if one is not already provided by the Ada 95 compiler system, likewise for the non-generic equivalents) and that the exception Argument_Error is now found in another unit. The results of using the provided operations may vary where Ada 95 takes the possibility of signed zeroes into account.

The freezing rules (which determine when in a source all properties of an entity must have been specified) have been tightened in Ada 95 over Ada 83. This tend to cause problems in package specifications where representation items have been moved away from a declaration, for instance into a private part to signal that the precise representation is not part of package's interface. Such representation items are often required by Ada 95 to appear closer to the declaration. Moving the representation items to just after the declaration makes the source legal Ada 83 and Ada 95 at the same time.

Interfacing pragmas is a area where the Ada 83 and Ada 95 standards differ a good deal. Ada 83 only provided the pragma Interface to import entities to Ada and placed no particular requirements on naming of interface languages, external naming or calling conventions. This meant that most Ada 83 compiler vendors introduced implementation specific pragmas to cover export of Ada entities and external naming. Ada 95, on the other hand, standardizes importing from and exporting to Ada, Assembler, C (and to some extent C++), COBOL and Fortran. It is recommended to isolate the parts of the application which explicitly interfaces with non-Ada entities and to document any assumptions made about external naming and calling conventions in particular. All interfacing pragmas should be expected to require some rework in a transition unless the Ada 83 and Ada 95 compiler systems are documented to be compatible.

Machine code insertions will tend to differ considerably between two different compiler system including between an Ada 83 compiler system and an Ada 95 compiler system. Again, isolation of the use of machine code insertions and of use clauses on package Machine_Code is recommended. A complete rewrite of the existing machine code insertions should be expected in connection with a transition. In this connection it is worth investigating if some of the existing machine code insertions can be replaced by new Ada 95 features (e.g. access to unsigned arithmetic) or more easily be imported from another language in order to reduce the risk of introducing errors by facilitating compiler checking. It is recommended to analyze the required support of both compiler systems to guard against relying on specific features which are not available in both.

The floating point model has been reformulated in Ada 95; in that connection the various floating point model attributes (e.g. Epsilon and Mantissa) were replaced by a new set (corresponding names Model_Epsilon and Model_Mantissa). Some Ada 95 compiler systems accept the former names in addition to the new ones; if you are transitioning to an Ada 95 compiler system which does not, attribute uses will need to be replaced. It should be noted that a consequence of the model changes is that some of Ada 95's corresponding attributes may yield (slightly) different values compared to the Ada 83 attributes; if the application uses these attributes, some analysis may be required to ensure correct operation following a transition. While dealing with attributes of floating point types, it should be noted that most Ada 83 compilers implement overflow checking on floating point operations and therefore evaluate Floating point type'Machine_Overflows to True and that most Ada 95 compilers in contrast implement floating point operations so that they saturate (result in a signed infinite value) in case of overflow and therefore evaluate Floating point type'Machine_Overflows to False (division by zero always causes an exception or makes the execution erroneous if Division_Check is suppressed).

Ada compiler system often provide more units in the predefined language environment than required by the language standard. In connection with transitioning from one compiler system to another, it is important to identify uses of such units within the application as they will most likely require changes. The only standardized unit you will need to look for is Low_Level_Io, which was removed from the Ada 95 standard. Consult the documentation for the Ada 83 compiler system in use to identify the implementation-specific units your application may depend on; it is difficult to estimate the risks of removing such dependencies which may hide a considerable implementation burden or be essential to the application's performance. Additionally, your application should not define units named Ada and Interfaces since they will clash with Ada 95 names.

Uses of Unchecked_Conversion are likely to be accepted by an Ada 95 compiler and behave exactly as in Ada 83. This should include all instances where the source and target types both are represented without indirections or implementation-specific components and both have the same size; it will be necessary to consult the Ada 83 and Ada 95 compiler system documentation to determine the types which fall in this category. Other uses (e.g. between types of unequal sizes) will require analysis to determine if they will produce the expected results (e.g. drop bits starting with the most significant bit when the target size is the smaller).

Conclusion
The process of transitioning from Ada 83 to Ada 95 can follow a set of established guidelines. Using those, it is possible to create virtually identical Ada 83 and Ada 95 versions of a given application. Special attention must be given to the implicit dependencies which often exist in an application on implementation-specific behaviour; these dependencies are often the most difficult to identify and the most costly to address. Good documentation for both the Ada 83 and Ada 95 compilers is necessary to answer many questions on implementation-specific behaviour. Investigate if an Ada 95 compiler is availlable which offers enhanced backward compatibility with Ada 83 as this may significantly reduce the risk and cost associated with the transition.

 

Contact
602-275-7172
sales@ddci.com

IDIQ Contract Vehicles:
--------------
AMCOM Express
DESP II
F2AST
R23G

Links

Support

Members Area
    -Member Login/Return
    -Login Help

Atlas Support Packages
    -Atlas Premium
    -Atlas Advantage
    -Atlas Choice

Complimentary Support

Submit a Software Trouble Report

Customer Quote:
"Regarding IBAS Engineering Services: We've been very fortunate on this (migration) project to have a great team of talented hard workers... We've been supported by an excellent team of truly dedicated (DDC-I) contractors... They made this project their own."