![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Coding Issues Migrating from VADS to Apex This section provides the known coding issues that a customer will face transitioning from VADS to Apex, regardless of the target Ada dialect used with Apex. We note where fixes differ for the Ada dialect.
When moving code from VADS to Apex, typically there will be some changes required, particularly in those language areas where compiler implementations are free to interpret the language differently. The first question to be addressed is whether to move the code to Apex Ada 83, or make the complete change to Apex Ada 95 as part of the conversion.
Arguments for simplicity would suggest making changes in small increments,that is, moving only to Apex Ada 83, and then later, if desired, moving to Apex Ada 95. However, there are several areas where code changes to make VADS code work with Apex are easier in the Ada 95 dialect than the Ada 83 dialect. For example, Apex does not support passive tasks. If code performance is critical, then Ada 95 is critical to make use of protected types to replace passive tasks; the translation is straightforward, and the resulting code is faster and more general than what VADS provided with passive tasks.
It is our guarded opinion that converting directly to Apex Ada 95 is marginally more desirable than converting only to Apex Ada 83, or converting in two steps.
The following description was developed based on usage of various Apex 3.0 versions, with some information from the Apex 3.2.x versions. It is possible that subsequent patches and incremental updates to Apex may change the messages that are output, or fix some of the areas where workarounds are particularly difficult. For items labeled "bug", the problem is due to a bug in Apex that we expect to fix in a subsequent version or patch.
Note that we have tried to identify all transition issues in this document. If you encounter an issue that is not covered, you are strongly encouraged to make this known to the support team so we can help you determine the appropriate changes, and also develop changes in Apex to make future transitions easier.
The following topics are covered here:
- VADS Addressing Trick Using Erroneous Code
- Invalid Code Permitted by VADS
- Package Math not supported in Apex 3.x (MIPS cross only)
- Missing or Changed Pragmas
- Non-Static System.Address'Ref
- Passive Tasks to Protected Types
VADS Addressing Trick Using Erroneous CodeIn some versions of embedded VADS, a trick may be used to generate long address references in code. The issue comes about on platforms where subroutines might be located further than the typical short offset might allow. For example, on MIPS targets, the one-instruction jump instructions can jump to any address for which the high-order 4-bits are identical, a memory range of 256MB.
Normally 256MB for the application is sufficient, but some systems are designed with main memory in one 256MB bank and a different kind of memory (such as non-volatile RAM) located in a different bank. When jumping to a subroutine located in a different bank, the normal jumps do not provide sufficient addressing space for the linker to modify the instruction to reach the intended destination.
The linker has a feature for adding patch jump code that uses a longer sequence of instructions (and register saving) to reach the intended destination. However, some customers prefer to have the compiler simply generate the necessary instructions in-line. For VADS, there were various tricks used to force the compiler to generate the appropriate long calls.
One such trick was to use code similar to the following:
procedure Do_Something(X : Integer) ; procedure Do_Something_Alias(X : Integer) ; pragma Interface(Ada, Do_Something_Alias ); for Do_Something_Alias use at Do_Something'Address ; . . . Do_Something_Alias( 13 ) ;
Note that this code is nonsense. There is no body for
Do_Something,
so specifying an address for it is senseless. The Apex compiler properly rejects this code, stating thatDo_Something'Address
is invalid for the address clause, and also complaining that there is no body to completeDo_Something
. It is only a quirk of VADS that permitted this to compile and have the desired effect.With Apex Ada 95, the appropriate solution is to use an object of an access type to the desired function. The object then has the appropriate width (32-bits on MIPS) to address directly any part of memory. The call then uses the access object, which retains the appropriate 32-bit addressing. For the code above, the solution in Ada 95 would look like this:
procedure Do_Something( X : Integer ) ; pragma Interface(Ada, Do_Something ) ; type Do_Something_Access is access procedure Do_Something(X : Integer ) ; Do_Something_Alias : Do_Something_Access_Type := Do_Something'Access ; . . . Do_Something_Alias ( 13 ) ;With Apex Ada 83, the solution is more complex. For creating the full 32-bit references, objects of type address may be used. However, writing the calls using these address objects is more awkward. The calls must use machine_code procedures and jump to the desired location (letting the referenced routine's return code return to the original caller).
Invalid Code Permitted by VADSThe VADS compiler is not as strict as Apex and occasionally there are code segments that compile in VADS but are rejected by Apex. This section lists those known areas where this occurs.
Incorrect Use of La Instruction in MIPS Machine_Code
In VADS, the following machine_code instruction compiles:
Code_2'(La, R1, +16#00070000#);
The VADS generated instructions load the constant into R1, not the address of the constant as might be supposed from the load address instruction. Apex rejects this code with the following error message:
&&& [GSK] symbolic_operand(), suspicious decl kind: LITERAL_DECL"Code_2'(La, R1, +16#00070000#);" (Assembly_Routines.Pack_Fft'Body.13S) &&& [GSK] Exception (PROGRAM_ERROR) caught in Code_Unit
Admittedly the error message is of no help, however the fix is quite simple. The instruction simply needs to be changes to a "load immediate" instruction:
Code_2'(Li, R1, +16#00070000#);
Package Math not supported in Apex 3.x (MIPS cross only)The
package Math
is not supported in Apex 3.x cross to MIPS, as it was in Apex 2.4.6 and in VADS. Note that the package is provided for all native compilers in vads_compatibility_static.ss. The only embedded target system where VADS provided this package is MIPS.For Ada 83 under Apex 3.2 and beyond (for MIPS embedded targets), there is currently no good solution to transitioning code from VADS that uses the Math package.
For Ada 95 under Apex 3.2 and beyond (for MIPS embedded targets), a Math package is provided in vads_compatibility_static.ss that is very similar to the VADS Math package. It is simply a pure renaming of the mathematical functions found in the Ada 95 "strict" (Ada 95 code) package
Generic_Elementary_Functions
and corresponding instances (Elementary_Functions, Long_Elementary_Functions
, andShort_Elementary_Functions
). It typically requires no application code changes to use. User code could be modified to use the Ada 95 packages directly, but this package allows a transition without any code modifications, and has no execution time impact (no extra instructions).The only differences from the VADS version of this package are the elimination of the Bessel functions (rarely, if ever, used) and the elimination of the locally defined exceptions. The Ada 95 functions in Apex 3.2 are much faster than the original functions in VADS, so application speed is significantly increased.
For Apex 3.0.1 Ada 95 MIPS cross users, it is possible to obtain a copy of the math.1.ada and math.2.ada sources used in Apex 3.2 and use them with the Apex 3.0 definitions of the
*_Elementary_Functions
packages. However, the Ada 95 math implementation in Apex 3.0 was significantly slower than with Apex 3.2, and is also slower than VADS. However, the ease of transition may make this desirable, particularly if an upgrade to Apex 3.2 is planned in the near future.
Missing or Changed PragmasA number of VADS pragmas are missing or have different interpretations or limitations in Apex. Here is what to do in each known case:
Non-Static System.Address'RefIn VADS,
System.Address'Ref
applied to a static value is itself static. In Apex, it is always dynamic. Typically this has little effect, but at least two cases it can cause compilation problems.Note that this may also cause slower startup in Apex than VADS for global data and routines, because dynamic value initialization requires code execution, while static initialization is computed at compile time and is part of the loaded image. (This effect only occurs with global data. Data declared in subroutines must always be dynamically initialized because all routines are reentrant in Ada.)
The first problem case occurs when elaboration must be static, such as in the
V_Krn_Conf
andV_Usr_Conf
configuration tables. These tables must be static because they are used before elaboration has completed. Typically the code includes one of the following pragmas:
No_Elaborate
Suppress_Elaboration_Checks
Export_Elaboration_Procedure
The typical solution is to change items of
type System.Address
to some other type that can be initialized with a static value. If that is not feasible, then often the code can be changed so that the offending item no longer is required to be statically initialized.The second problem case occurs when using
System.Address
constants withmachine_code
. The prototypical example (using MIPS instructions) is the following:
package One is Addr_Value : constant System.Address := System.Address'Ref (16#FF00_1234#); ... with One ; with Machine_Code ; package body Two is procedure Do_Something is use Machine_Code ; begin Code'2 (Li, T1, One.Addr_Value'Ref ) ; ...
The Apex compiler creates an error in this case, referencing the
Code'2
line with a message like:
>>> Line 1234: Code_2'(Li, T1, One.Addr_Value'Ref); *** One.Addr_Value is incompatible with the required operand mode
The code may be changed mechanically to work around the problem. A typical change is:
package One is Addr_Value_Const : constant := 16#FF00_1234# ; -- ADDED Addr_Value : constant System.Address := System.Address'Ref (Addr_Value_Const); -- CHANGED ... with One ; with Machine_Code ; package body Two is procedure Do_Something is use Machine_Code ; begin Code'2 (Li, T1, Immed_Mod32(One.Addr_Value_Const) ) ; -- CHANGED ...
This change requires adding the
X_const
declaration, expressing theX system.address
constant in terms ofX_const
(so the consistency is clear), and fixing themachine_code
operand to useX_const
instead ofX'ref
. The functionImmed_Mod32()
must be applied to theX_const
to make it the correct type for themachine_code
instruction.
Passive Tasks to Protected TypesVADS supports
"Pragma Passive"
applied to a suitable task. This pragma changes all task rendezvous calls into simple function calls, protected by a semaphore. The result is significantly increased speed of rendezvous.Passive tasks are in essence little more than critical regions guarding a sequence of code. The sequence of code is the accept body. Passive tasks use mutexes to guard the critical region. Under VADS, passive tasks must be individual tasks (not task types) and the body code must have one of the following structures:
Accept form: task body PT is <decls> begin loop accept <entry_decl_n> do <accept_body_n> end ; end loop; end Pt ; Select form: task body PT is <decls> begin loop select when <condition_1> => accept <entry_decl_1> do <accept_body_1> end ; when <condition_n> => accept <entry_decl_n> do <accept_body_n> end ; end select ; end loop; end Pt ;
Only these two forms are allowed. The
select
statement cannot containterminate
ordelay
alternatives, nor can it have anelse
clause.The code in the
accept
bodies must not have any active task actions. Actions such as a blocking call to another task, delay statements, task creation, and the like are prohibited.For Apex Ada 83, there is no alternative for VADS passive tasks. In Apex Ada 83 the task must be used without
pragma Passive
,that is, as an active task. This will impact application speed, with the severity depending on how often the task entries are called. Typically passive task calls are made less frequently than programmers suppose, so the net effect in a real application is likely only on the order of a few percent, but could be as much as 10 or 20 percent slowdown.For Apex Ada 95, a protected type object can be used, and provides even faster speed than obtained with
pragma Passive.
The Ada 95 construct can be made into a data type so multiple objects with the same structure can be defined just as is possible with passive tasks.The Ada 95 protected type is a much more powerful construct than Ada 83 VADS passive tasks. For example, procedures and functions can be defined in addition to entries, to allow more access to the declarative items. A buffer "count of items stored" function could be implemented using a function, resulting in much faster execution and less blocking than possible with passive tasks.
For the accept form of a passive task, the transformation is:
Accept form: protected type Pt_T is procedure <entry_decl_n> ; private <decls> end Pt_T ; protected body Pt_T is procedure <entry_decl_n> is begin <accept_body_n> end ; end Pt_T ; Pt : Pt_T ;
Basically the declarative items are moved to the private part of the specification and the entry definition and accept statement are transformed into a procedure call. This is more efficient than using an entry call, and the limited definition permits this to be implemented with a single procedure call. If appropriate the procedure call could be transformed into a function call.
For the select form of the passive task, the transformation is:
Select form: protected type Pt_t is entry <entry_decl_1> ; entry <entry_decl_n> ; private <decls> end Stack ; protected body Pt_t is entry <entry_decl_1> when <condition_1> is begin <accept_body_1> end ; entry <entry_decl_n> when <condition_n> is begin <accept_body_n> end ; end Pt_t ; Pt : Pt_t ;
Basically the declarative items are moved to the private part of the specification and the accepts within the select loop are changed into protected entry bodies. The conditions of the select are moved to be conditions applied to the individual entries.
The code sequences typically need little, if any work. The one case where changes might be necessary are if there are any explicit mutex actions in the body.
If the passive task has an interrupt mutex associated with it, the same effect may be achieved by using standard Ada 95 constructions:
pragma Interrupt_Priority ; -- added inside specification of Pt_T
Note that in Ada 95, the level of interrupt should be set to the highest interrupt that will be using the type, the "Ceiling" priority. That way higher priority interrupts can still occur during calls to the protected type.
Also, since there is no task life associated with protected objects, any reference to it as a task must be deleted. In particular, calls with exception handling of
Tasking_Error
exceptions can be eliminated, as the calls do not involve a task. Any use of task attributes, for examplePt'Callable
orPt'Terminated
should be eliminated. Effectively the routines are always callable and never terminated.The additional forms of
pragma Passive
in VADS (Abort_Safe
orAbort_Unsafe
) may be ignored, as they have no meaning with protected types where there is no task state to be considered. Anyabort
statements referring to the passive task should be deleted when it is converted to a protected type.
Rational Software Corporation http://www.rational.com support@rational.com techpubs@rational.com Copyright © 1993-2002, Rational Software Corporation. All rights reserved. |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |