This section outlines the usage of the GNAT compiler with the LLVM back end and highlights its key limitations. Certain GNAT versions, referred to as GNAT LLVM, include an alternative LLVM back end alongside the GCC back end, providing access to utilities that operate at the LLVM Intermediate Representation (IR) level. This also enhances safety by facilitating dissimilar redundancy through diverse code generation techniques, allowing for the creation of two distinct binaries from the same source code.
Although both GNAT LLVM and the GCC-based GNAT follow most ABI rules,
there are some cases where there you may encounter an incompatibility
between the two compilers. One such case for the 64-bit Intel X86 is
a difference in parameter passing when a structure that consists of 64
bits is passed. The native LLVM handling (and hence that of GNAT LLVM)
and clang
disagree in this case. GCC follows clang
. The formal
ABI agrees with LLVM.
In any case, we don’t recommend you link code compiled with GNAT LLVM
to code compiled by the GCC version of GNAT. This is a specific case
of the general rule that you should compile all your Ada code with the
same version of GNAT. Both gnatmake
and gprbuild
ensure this
is done.
You may, however, run into this incompatibility if you pass such a record between C and Ada. In general, we recommend keeping the data passed between C and Ada as simple as practical.
GNAT LLVM currently provides limited support for debugging data. It
provides full line number information for declarations and statements,
but not sufficient debugging data to display all Ada data
structures. GNAT LLVM outputs complete debugging data only for types
with a direct equivalent in C, namely records without discriminants
and constrained arrays whose dimensions are known at compile time. You
will not be able to use gdb
print commands to look at objects not
of those types or to display components of those types. You can use
low-level gdb
commands that display memory to view such data
provided you know how they’re laid out. Debugging information may
also be limited for bitfields (fields whose size and position
aren’t on byte boundaries)
In addition, debugging information may be confusing if you have
out
parameters to subprograms. If you have a procedure with only
one out
parameter, GNAT LLVM converts that to a function returning
an object of that type. If you have multiple out
parameters or
have a function that also has an out
parameter, GNAT LLVM converts
that subprogram into a function that returns a record where each field
is either an out
parameter or the function return value, if any.
The debug information reflects these transformations and not the original
Ada source code.
GNAT LLVM doesn’t fully implement the -fcheck-stack
switch.
When you specify it, the code generated by GNAT LLVM tests for allocating
overly-large items on the stack, but not all cases of stack overflow. For
example, if you have a very deep recursion where each call only uses a
small amount of stack and the total stack depth exceeds the amount of
available stack, the program will be terminated by a signal instead of
raising an Ada exception.
GNAT LLVM doesn’t support the Scalar_Storage_Order
pragma except when
it’s used to confirm the chosen storage order. This is because this facility
is provided by GCC but not by LLVM.
GNAT LLVM doesn’t support Convention C++, which provides so-called ‘name mangling’ by encoding parameter and return datatypes into a function name.
We provide two options that you can use to build code with GNAT LLVM:
gnatmake
called
llvm-gnatmake
, which is equivalent to gnatmake
and has the
same switches, except that it uses GNAT LLVM instead of the GCC
version of GNAT.
gprbuild
can detect and use GNAT LLVM when it is installed.
gprbuild
uses the first applicable compiler on the executable
search path, including GNAT LLVM. An easy way to build with GNAT
LLVM is to make it available on the operating system’s search path
before any other Ada compiler (such as the GCC version of GNAT). To
avoid accidentally using a different compiler than the one you want
to use, we recommend generating an explicit toolchain configuration
file with gprconfig
and using it with gprbuild
; see the
‘GPRbuild and GPR Companion Tools User’s Guide’ for details. You
can determine from the first line of the .ali
file
which version of GNAT built that file because it contains either
GNAT
or GNAT-LLVM
.
You can also explicitly select GNAT LLVM in your existing GPR project
file by adding for Toolchain_Name("Ada") use "GNAT_LLVM";
GNAT LLVM understands the same target triplets as the GCC version of GNAT.