6.6. Run-Time System Issues

ERC32 Ada includes a run-time system that supports C and Ada. This includes the basic functions that are common to both languages, such as program startup, exception management and low-level input/output. In addition, each language is supported by a number of standard libraries, as required by the language definition.

6.6.1. The Stack

The Ada main program is given a stack, where the location and size are determined by the linker script file. The stack is used to support subprogram calls, and typically contains a linked sequence of stack frames that contain saved registers and subprogram data.

Each task has a stack that is allocated at elaboration time from the free memory declared in the linker script file. If insufficient free memory is available, then the predefined exception Storage_Error is raised.

Interrupt handlers use a separate stack also declared in the linker script file.

6.6.2. Subprogram Call and Parameter Handling

The subprogram calling convention follows the SPARC standard and uses register windows with the save and restore instructions.

Register saving. ERC32 Ada uses the callee-save convention for saving registers across subprogram calls. On entry to a subprogram, the registers of the calling subprogram are saved by stepping the current register window pointer. Most of the time, there is sufficient space in the ERC32 register cache to complete the save without actually transferring any registers to memory. It is only when the cache fills that a transfer is needed. On return from a subprogram, the registers are restored using the restore instruction.

Parameter passing. Up to 6 words of parameters are passed in registers %o0 to %o5. Any further parameters are passed on the stack. For a function, or a procedure with a single out parameter, the result is passed out in register %o0.

The call instruction. ERC32 Ada uses the call instruction to call a subprogram.

Subprogram entry. For subprogram entry, the compiler generates code to establish a new stack frame. This may include code to check for stack overflow. The compiler is able to recognize several special cases where the worst-case code can be improved. In particular, for leaf[1] subprograms that have no need for a stack frame data, the stack frame is completely eliminated and the code to set up the frame, and remove it on exit, is not generated.

Subprogram exit. For subprogram exit, the compiler generates code to remove the current stack frame, and return to the calling subprogram.

The return value. Function values are returned in a register if possible. If not then the calling subprogram allocates space in its stack frame then passes the address of the space to the called subprogram, which copies the function value to that address.

6.6.3. Data Representation

The following table shows the number of bits in the data representation for the ERC32 Microprocessor.

TypeERC32 Microprocessor
Integer8, 16, 32 and 64 signed
Modular8, 16, 32 and 64 unsigned
Fixed8, 16, 32 and 64 signed
Floating Point32 and 64
Enumeration8, 16, 32 and 64

Storage allocation for array types is simply the number of components multiplied by the allocation for each component. Components can be packed and bit aligned in some cases. Unconstrained arrays have a descriptor with lower and upper bounds for each index. Note that dynamically unconstrained arrays are prohibited.

Storage allocation for record types is the sum of the individual component allocations, which are byte aligned by default. Components can be packed and bit aligned in some cases.

The pragma Pack causes packable array and record components to be allocated in adjacent bits without regard to byte boundaries.

6.6.4. Implementation of Ada Tasking

ERC32 Ada supports a limited form of Ada tasking that permits static tasks, protected types and a limited form of rendezvous. The features supported may be further restricted by use of individual restrictions, or by the pragma Profile.

The general strategy is for the compiler to translate Ada tasking operations into run-time system calls, using data types from the predefined package XGC.Tasking.

Some language features (delays for example) are supported by child subprograms.

In addition the package XGC.Preemption_Control is required to give the run-time system exclusive access to the tasking data structures.

The above packages are only included in an application program if the corresponding language features are used. A null program is linked with only the minimal run-time system module art0.S.

Notes

[1]

A leaf subprogram is one that makes no subprogram calls.