GNAT with the LLVM Back End (GNAT User’s Guide for Native Platforms)

### 4.8 GNAT with the LLVM Back End ¶

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 a subset of types: scalar types; records whose field offsets are known at compile time, including discriminated records fitting this description; and arrays. Records that have a field whose size or offset is only known at run time do not yet have correct debugging data. 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.

In some situations, a name in the source may not be available. Renamings are not currently emitted into the debugging data. When debugging a nested function, variables from enclosing scopes will not be available. You will have to examine those variables in their hosting frame.

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:

- GNAT LLVM includes a version of `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 explicitly selecting GNAT LLVM in your existing GPR project file by adding `for Toolchain_Name ("Ada") use "GNAT_LLVM";`. You can also generate an explicit toolchain configuration file with `gprconfig` and use 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`.

GNAT LLVM understands the same target triplets as the GCC version of GNAT.