How does the input file name get into gnat1?



In Frontend, we see Lib.Load.Load_Main_Source being called.
This is a parameterless procedure - so where does the file name come from?
It turns out that the answer to this question requires a fair amount of digging in the GCC and GNAT source code:

The gcc compiler driver program determines which compiler proper to invoke and passes (a filtered version of) the command line with which it was called to the selected compiler, in our case gnat1.
The main program of gnat1 is written in C, see file main.c in the gcc subdirectory of the GCC source distribution,

int
main (int argc, char **argv)
{
  toplev toplev (NULL, /* external_timer */
                 true /* init_signals */);

  return toplev.main (argc, argv);
}
The input filename is passed from the main program's argv on to the function toplev::main (toplev.c) which calls the function decode_cmdline_options_to_array_default_mask (opts-global.c). This function returns the decoded options in the variable save_decoded_options which is passed to the call of lang_hooks.init_options. Being the gnat1 program, this call is implemented in the GNAT specific file ada/gcc-interface/misc.c :
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
LANG_HOOKS_INITIALIZER is defined in langhooks-def.h :
/* The whole thing.  The structure is defined in langhooks.h.  */
#define LANG_HOOKS_INITIALIZER { \
  LANG_HOOKS_NAME, \
  [...], \
  LANG_HOOKS_INIT_OPTIONS, \
  [...]
and the LANG_HOOKS_INIT_OPTIONS function is again furnished by ada/gcc-interface/misc.c :
#define LANG_HOOKS_INIT_OPTIONS                gnat_init_options
This means that the mentioned lang_hooks.init_options call ends up calling the gnat_init_options function which saves the options received via its parameter to the GNAT specific global variables save_argc and save_argv. (As a side note, the GNAT global variables gnat_argc and gnat_argv are also filled - but they contain only 1 resp. argv[0]. Thus, they are not used for conveying the Ada input file.)
As another side note, the further options processing in toplev::main, such as the call to decode_options which in turn calls read_cmdline_options(), is not relevant to the Ada input file; in particular, the resulting opts->x_main_input_filename is not used by the GNAT frontend.

After a few other initializations, toplev::main calls the function do_compile (also in toplev.c). As the first action, this function calls process_options (still toplev.c) which sets the global variable main_input_filename. After further initializations, it executes this code:

  if (lang_dependent_init (main_input_filename))
    compile_file ();
The function lang_dependent_init (toplev.c) through some hooks and macros calls the function gnat_init (ada/gcc-interface/misc.c). However, gnat_init does not handle the input file name. Looking further, the function compile_file (toplev.c) calls lang_hooks.parse_file which through some hooks and macros calls the function gnat_parse_file (ada/gcc-interface/misc.c). This function makes the transition from the C to the Ada world by calling
  _ada_gnat1drv ();
The Ada procedure Gnat1drv (ada/gnat1drv.adb) calls the procedure Scan_Compiler_Arguments from package Back_End. This procedure copies the input file name from save_argv (see above) using the procedure Add_File from package Osint. Add_File adds the file to the File_Names and File_Indexes in the private part of the Osint package spec. These variables are used by the function Next_Main_Source in package Osint.C which is called from Lib.Load.Load_Main_Source.








Version info:

This text applies to recent gcc versions (last checked with svn trunk of 2016-07-22). The original version of this text was based on gcc-4.6.