Ada Runtime Library: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
Type Image attributes
m Bot: Replace deprecated source tag with syntaxhighlight
 
(4 intermediate revisions by 2 users not shown)
Line 30:
== Creating a run-time library suitable for x86 operating-system development ==
 
''Note: This section assumes that you are using an x86/x86-64 host compiler and are targeting an x86 system. Creating a run-time for other targets will be different. This section also assumes that you have a suitable [[GNAT_Cross-Compiler|cross-compiler]]. While you may be able to copy run-time source files from your system GNAT installation, a compiler specific to your target system will still be required. A detailed guide to building a GNAT cross-compiler can be found [[GNAT_Cross-Compiler|here]].''
 
In order to compile Ada code for bare-metal targets using the GNAT compiler, developers will need to configure an appropriate Ada run-time library for their target platform. The Ada standard recommends that all of the packages defined in ‘Annex A: Predefined Language Environment’ be defined for a platform, but for the purposes of bare-metal development this is impractical.<br/>
Line 52:
For more information regarding GNAT project configuration refer to the AdaCore documentation: [https://docs.adacore.com/gprbuild-docs/html/gprbuild_ug/gnat_project_manager.html]
 
<sourcesyntaxhighlight lang="ada">
library project Runtime is
-- Tells Gprbuild to create any missing directories in the build process.
Line 123:
for Target use "i686-elf";
end Runtime;
</syntaxhighlight>
</source>
 
As noted in the source code comments above, in this setup the run-time sources are used as a run-time library during the build process. One method to implement this is to include a pre-requisite step in your makefile to copy the sources to the final build destination <tt>adainclude</tt> directory, then to specify this build directory as the run-time for the project. An example makefile for facilitating this can be seen below.
Line 129:
''Please note that this makefile may not be fit for all projects and purposes.''
 
<sourcesyntaxhighlight lang="make">
RUNTIME_BINARY := ${LIB_DIR}/libgnat.a
RUNTIME_PROJ := runtime
Line 176:
${LIB_DIR}:
mkdir -p ${LIB_DIR}
</syntaxhighlight>
</source>
 
 
Line 241:
|-
| <tt>ZCX_By_Default := False</tt>
| Indicates if zero cost exceptions are active by default. Refer to the [https://gcc.gnu.org/onlinedocs/gnat_ugn/Run-Time-Libraries.html documentation] for more information on Zero-cost-exceptions.
|-
| <tt>GCC_ZCX_Support := False</tt>
Line 249:
Also, add the following line in the private part of the package:
 
<sourcesyntaxhighlight lang="ada">
private
Run_Time_Name : constant String := "Bare Bones Run Time";
</syntaxhighlight>
</source>
 
According to <tt>targparm.ads</tt>, this directive should be the first thing after the private keyword.
Line 266:
 
'''x86.ads'''
<sourcesyntaxhighlight lang="ada">
-------------------------------------------------------------------------------
-- X86
Line 276:
pragma Preelaborate (x86);
end x86;
</syntaxhighlight>
</source>
 
'''x86-port_io.ads'''
<sourcesyntaxhighlight lang="ada">
with Interfaces;
with System;
Line 321:
);
end x86.Port_IO;
</syntaxhighlight>
</source>
 
 
'''x86-port_io.adb'''
<sourcesyntaxhighlight lang="ada">
with System.Machine_Code;
 
Line 367:
end Outb;
end x86.Port_IO;
</syntaxhighlight>
</source>
 
Fundamentally, the role of the runtime library is to implement the features defined in the Ada language standard for the particular target platform. This requires the creation of target-specific packages to interface with platform features such as internal clocks, [[UART|UARTs]] and [[PIT|timers]], among other things. These packages can then be used by language-defined packages in the runtime library to expose this functionality to the linked application.
Line 380:
A practical usage of this would be to define a <tt>runtime.xml</tt> file, placed within the final <tt>adainclude</tt> directory of the run-time library. This is used to automatically use a linker script for the target platform when the kernel is linked against the library.
 
<sourcesyntaxhighlight lang="xml">
<?xml version="1.0" ?>
<gprconfig>
Line 395:
</configuration>
</gprconfig>
</syntaxhighlight>
</source>
 
Where <tt>${RUNTIME}</tt> is a predefined variable made available by Gprbuild.
Line 403:
=== Exceptions ===
 
Exception handling in Ada is implemented in the run-time library package <tt>Ada.Exceptions</tt>. This is defined in section 11 of the the Ada Language Reference Manual and can be referenced [http://www.adaic.com/resources/add_content/standards/12rm/html/RM-11-4-1.html here]. Comprehensive exception handling functionality is typically disabled for bare-metal targets due to the large amount of underlying functionality required for its implementation, such as stack unwinding, streams, secondary stack, etc. As such it is not normally included in the run-time library for such targets. Local handling exceptions within a subprogram is still possible without the <tt>Ada.Exceptions</tt> package being implemented for a target.
For our bare-bones run-time library we require the use of the <tt>No_Exception_Propagation</tt> restriction pragma. This restriction ensures that an exception is never propagated over a subprogram boundary into an outer scope. Raising an exception over a subprogram boundary requires the use of <tt>setjmp/longjmp</tt> which are unsuitable for the purpose of bare-metal development. With this restriction applied the only case in which an exception may be raised is when the exception handler is contained within the same subprogram. According to [https://docs.adacore.com/gnat_rm-docs/html/gnat_rm/gnat_rm/standard_and_implementation_defined_restrictions.html#no-exception-propagation official documentation], the effect of this is that raising an exception is essentially a <tt>goto</tt> statement.<br/>
 
For oura bare-bones run-time library weused requirefor theoperating-system usedevelopment ofit is recommended to use the <tt>No_Exception_Propagation</tt> restriction pragma. This restriction ensures that an exception is never propagated over a subprogram boundary into an outer scope. RaisingThe animplementation of exception handling over a subprogram boundaryboundaries typically requires the use of <tt>setjmp/longjmp</tt>, which are unsuitable for the purpose of bare-metal development. With this restriction applied the only case in which an exception may be raised is when the exception handler is contained within the same subprogram. According to [https://docs.adacore.com/gnat_rm-docs/html/gnat_rm/gnat_rm/standard_and_implementation_defined_restrictions.html#no-exception-propagation official documentation], the effect of this is that raising an exception is essentially a <tt>goto</tt> statement.<br/>
 
Any exception not handled explicitly within the same subprogram will be caught by the <tt>Last_Chance_Handler</tt> subprogram.
 
Line 420 ⟶ 423:
 
'''s-imguns.ads'''
<sourcesyntaxhighlight lang="ada">
with System.Unsigned_Types;
 
Line 465 ⟶ 468:
 
end System.Img_Uns;
</syntaxhighlight>
</source>
 
'''s-imguns.adb'''
<sourcesyntaxhighlight lang="ada">
with System.Unsigned_Types; use System.Unsigned_Types;
 
Line 536 ⟶ 539:
 
end System.Img_Uns;
</syntaxhighlight>
</source>
 
User-defined images for a given type can be implemented by overriding the default implementation of the <tt>Put_Image</tt> attribute.