Contents
--------

 1. What is gnatelim
 2. How it works?
 3. Eliminate pragma
 4. gnatelim options
 5. Preparing tree and bind files for gnatelim
 6. Creating a list of Eliminate pragmas with gnatelim
 7. Minimizing your executables
 8. Manual correction of the list of Eliminate pragmas creating by gnatelim
 9. Processing precompiled Ada libraries and GNAT RTL
10. gnatelim usage cycle: summary
11. Related information
12. Submitting bug reports


1. What is gnatelim
   ----------------

When you are working with a program which shares some set of Ada packages
with other programs, it may happen, that your program uses only a part of
subprogram defined in these packages, whereas the code created for unused
subprograms increases the size of the executable your program.

gnatelim is a utility tracking unused subprograms in an Ada program. Its
output consists of a list of Eliminate pragmas marking all the subprograms
that are declared, but never called in a given program. Eliminate is a
GNAT-specific pragma, see section 3 for more details. By placing the list
of Eliminate pragmas in the GNAT configuration file gnat.adc and
recompiling your program, you may decrease the size of its executable,
because the compiler will not create the code for unused subprograms.

2. How it works?
   ------------

gnatelim is an ASIS application developed on top of the ASIS implementation
for GNAT. It needs a set of tree files representing a program to
analyze and the bind file for its main subprogram to be created in the
current directory (see sections 5 and 9). For the current version, it is a
gnatelim user's responsibility to maintain the consistency of the set of tree
files processed by gnatelim, if the user also changes the sources of the Ada
program to be processed.

To produce a list of Eliminate pragmas, gnatelim has to do an extensive
analysis and it may take some time. For example, to process itself, gnatelim
takes 4 minutes of CPU time on a Pentium 200.


3.  Eliminate pragma
    ----------------

The following description is talen "as is" from the GNAT Reference Manual,
version 3.11

Syntax:

    pragma Eliminate (
        [Unit_Name       =>] IDENTIFIER |
                             SELECTED_COMPONENT
      [,[Entity          =>] IDENTIFIER |
                             SELECTED_COMPONENT |
                             STRING_LITERAL]
      [,[Parameter_Types =>] PARAMETER_TYPES]
      [,[Result_Type     =>] result_SUBTYPE_MARK]);

    PARAMETER_TYPES ::=
      null
    | SUBTYPE_MARK {, SUBTYPE_MARK}

This pragma indicates that the given entity is unused in a program. The
entity may be either a subprogram or a variable. If the entity to be
eliminated is a library level subprogram, then only the first argument,
specifying the corresponding unit name, is required. If the item is an entity
of a library package, then the first argument specifies the unit name, and
the second argument specifies the particular entity. If the second argument
is in string form, it must correspond to the internal manner in which GNAT
stores entity names (see compilation unit Namet in the compiler sources for
details). The third and fourth parameters are optionally used to distinguish
between overloaded subprograms, in the same manner as is used for pragma
Import_Procedure. The effect of the pragma is to allow the compiler to
optionally eliminate the code or data associated with the named entity. If
the declaration of the entity would have resulted in side effects, these side
effects may or may not occur in the resulting program. Any reference to an
eliminated entity may cause a compile time error, link time error, or
incorrect results at runtime. The intention of pragma Eliminate is to allow a
program to be compiled in a system independent manner, with unused entities
eliminated, without the requirement of modifying the source text. Normally
the required set of Eliminate pragmas is constructed automatically using the
gnatelim tool.


4.  gnatelim options
    ----------------

The current version of gnatelim has the following command-line interface:

   gnatelim [options] name

'name' should be a full expanded Ada name of a main subprogram of a
program (partition).

gnatelim options:

-v

  verbose mode:
  - gnatelim version information is printed (in the form of Ada
    comments) in stdout;
  - the names of the files being processed are printed to
    standard-error;

-vf
  same as -v, but in addition various debugging information and
  information reflecting some details of the analysis done by
  gnatelim are printed to standard-error;

-a

  process RTL components: by default, gnatelim does not analyze the units
  which are the components of the GNAT Run-Time Library (RTL), and it does
  not generate Eliminate pragmas for subprograms declared in RTL. If '-a'
  option is set, RTL components are also analyzed (except some units, which
  contains subprograms implicitly called by the compiler);

-m

  check missed units: if this option is set, gnatelim checks, that all the
  units which (according to the bind file) has to be analyzed by gnatelim
  are really represented by the set of tree files processed by gnatelim
  (depending on whether or not '-a' option is set). By default (that is, if
  '-m' option is not set), gnatelim analyzes a set of units represented by a
  given set of tree files "as is" (excluding library packages which require
  bodies, but for which bodies are not available).


5.  Preparing tree and bind files for gnatelim
    ------------------------------------------

As an ASIS application built on top of ASIS-for-GNAT, gnatelim needs a
proper set of tree files to be created in the directory from which
gnatelim is called. It also needs a bind file for the program for which it
is called to be placed into this directory.

Suppose that Main_Prog is the name of a main subprogram, and this
subprogram is in file main_prog.ads or main_prog.adb (names of child units
are also allowed in this position.)

To create a minimal set of tree files covering the whole program, you may
call gnatmake for this program with -gnatc -gnatt compiler options:

   gnatmake -c [-f] -gnatc -gnatt Main_Prog

-c gnatmake option turns off the bind and link phases, which are
impossible anyway, because sources are compiled with -gnatc option, which
turns off generating object files.

If you have already done some compilations in your current directory, you
should use -f gnatmake option, which forces recompilation of all the
needed sources, even if they are up-to-date with the existing ALI files.

To create a bind file for gnatelim, run gnatbind for the main subprogram.
gnatelim can work with either Ada or C bind file, if both are present, it
works with the Ada bind file.

If you run gnatbind just after calling gnatmake for creating the tree
files, or if there is some inconsistency between the existing object and
source files, gnatbind will produce an error message, and you will have to
reapply gnatmake, but without -gnatc -gnatt compiler options.

To avoid problems with creating a consistent data for gnatelim, you may
use the following procedure. It creates all the data needed by gnatelim
from scratch and therefore guarantees their consistency:

1. creating a bind file:

      gnatmake -c Main_Prog
      gnatbind main_prog.ali

   (if you would like to get an Ada bind file, use -A option for gnatbind:

      gnatbind -A main_prog.ali
   )

2. creating a set of tree files:

      gnatmake -f -c -gnatc -gnatt Main_Prog

Note, that gnatelim needs neither object nor ALI files, so you may delete
them at this stage.

Note also, that creating the right set of tree files is an important part of
using gnatelim. When successfully called at "empty" place (or when called
with -f' option), gnatmake create a set of tree files representing all units
needed by the main subprogram to make up a partition, and it is exactly what
gnatelim needs to perform its analysis. By default, gnatelim does not check
the completeness of a set of tree files it processes, but it assumes, that
this completeness has already been ensured by the preceding call to gnatmake.
The '-m' option is intended to be used as some kind of debugging means in
case if gnatelim generates wrong Eliminate pragmas.

(See also section 9 concerning processing precompiled Ada libraries).


6.  Creating a list of Eliminate pragmas with gnatelim
    --------------------------------------------------

To create the list of Eliminate pragmas for your program, call gnatelim
with the name of its main subprogram as a command-line parameter. Note,
that gnatelim produces its output in stdout, so use the output
redirection to put these pragmas in the gnat.adc configuration file:

   gnatelim Main_Prog > gnat.adc

If you already have the configuration file for you program in the current
directory and if you would like to keep its existing content, use another
form of output redirection to append the gnatelim output to the existing
gnat.adc  file:

   gnatelim Main_Prog >> gnat.adc


7.  Minimizing your executables
    ---------------------------

Suppose that you have already got the list of Eliminate pragmas for your
program, and you have put these pragmas into gnat.adc file (Note, that
gnat.adc may contain also some other configuration pragmas, for example
Source_File_Name). To get a smaller executable for your program, you have
to recompile the program completely, having this gnat.adc file in your
current directory. To continue our example from sections 5 and 6, and
supposing, that we have everything in the current directory, the next step
is

   gnatmake -f Main_Prog

(you will need '-f' option for gnatmake to recompile everything with the
set of pragmas Eliminate you have got from gnatelim).

Be aware, that a set of Eliminate pragmas is individual for every program.
Therefore, you should never merge sets of Eliminate pragmas created for
different programs in one gnat.adc file.


8. Manual correction of the list of Eliminate pragmas creating by gnatelim
   -----------------------------------------------------------------------

In a very rare case gnatelim may try to eliminate subprograms which cannot
really be eliminated because they are actually called in the program. (It
is a very rare case for the current gnatelim version, but it still happens).
In this case, you will get an error message from the compiler of the form:

file.adb:106:07: cannot call eliminated subprogram "My_Prog"

You have to correct the gnat.adc file manually by suppressing the
faulty Eliminate pragmas. It is advised to recompile from scratch when
this happens, because you need a consistent gnat.adc file during the
complete compilation in order to get an meaningful result.

NOTE: generating erroneous Eliminate pragmas is a bug; we will appreciate
your letting us know about it by submitting a bug report (see chapter 12).


9. Processing precompiled Ada libraries and GNAT RTL
   -------------------------------------------------

The GNAT Run-Time Library exists as a precompiled set of Ada sources. For a
user Ada program which makes use of some RTL components (e.g., input-output
packages), these components are not recompiled when the program is
(re)compiled, but the specs of RTL components are processed when the user's
components depended on these specs are compiled.

As a result, a set of tree files created for gnatelim by using gnatmake (as
it is described above in section 5), will contain only specs, but not bodies
of RTL components.

Some other precompiled Ada libraries may exist as a part of a particular GNAT
installation. Technically, in case of GNAT a precompiled library is a set of
source, object and ALI (Ada library information) files, where ALI files are
locked (made read-only), and these sources normally are not recompiled when
applying gnatmake to a user program which uses the library. Therefore, for
such a user program, a set of tree files created by gnatmake will contain
only specs, but not bodies of library components.

If a user wishes to apply gnatelim to some program which uses precompiled Ada
libraries, he has three possibilities:

(1) not to analyze any component of any library (Eliminate pragmas will not
    be generated for subprograms declared in Ada libraries);

(2) to analyze all used precompiled Ada libraries except GNAT RTL;

(3) to analyze all used precompiled Ada libraries including GNAT RTL;

To take the first approach, the user has to follow the procedure
described above in section 5: the bodies for components of precompiled
libraries will not be presented by a set of tree files created for gnatelim,
and gnatelim excludes the specs of library components from the analysis.

To take the second approach, the user has to call gnatmake with '-a'
option when creating a set of tree files for gnatelim and when recompiling
his program with the set of Eliminate pragmas created by gnatelim. '-a'
option forces the recompilation of all the precompiled library components
(and all the results of such recompilations, that is, object and tree files
are put in the current directory). Note, that gnatelim should be called
without '-a' option, if GNAT RTL components should not be analyzed.

In this case gnatelim will generate Eliminate pragmas for subprograms
declared in precompiled Ada libraries (except GNAT RTL), and when the user
will create an exectutable for his program, library components will be
recompiled again with these pragmas.

To take the third approach, the user has to call both gnatmake and
gnatelim with '-a' options. The difference between this and the previous case
is that in this case gnatelim will analyze also the GNAT RTL components and
it will generate Eliminate pragmas for them.

Note that for gnatmake '-f' and '-a' options act independently and none of
them implies the other one.


10. gnatelim usage cycle: summary
    -----------------------------

Here is a summary of the steps you have to do to reduce the size of your
executables with gnatelim. Note, that this is only an example, which
creates all the data for gnatelim from scratch. You may try to reuse the
tree file and the bind file when running gnatelim several times for the
same program (but we would not advise you to do this, you can lose more
time if running into a problem of the consistency of the gnatelim input
data then you need to create everything needed by gnatelim from scratch).
You may also use other GNAT options (you may to control the optimization
level, produce the debugging information, set search path etc).

   --  producing a set of tree files and a bind file:

   gnatmake -c Main_Prog
   gnatbind [-A] main_prog.ali
   gnatmake -f -c [-a] -gnatc -gnatt Main_Prog

   --  generating a list of Eliminate pragmas
   gnatelim [-a] Main_Prog >[>] gnat.adc

   --  recompiling everything with gnat.adc file to create a smaller
   --  executable (manual correction of gnat.adc may be needed):

   gnatmake -f [-a] Main_Prog


11. Related information
    -------------------

See GNAT User's Guide for more details about GNAT options.
See ASIS-for-GNAT User's Guide for more details concerning tree files.


12. Submitting bug reports
    ----------------------
All bug reports, as well as any comments concerning the gnatelim
functionality and options, which are very welcome, should be sent to
asis-report@gnat.com.

For bug reports, as usual don't forget to supply the Ada partition
necessary to reproduce the problem.
