[PATCH, M2] Compiler driver patches

Gaius Mulley gaius.mulley@southwales.ac.uk
Thu Nov 21 00:05:00 GMT 2013


"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Wed, 20 Nov 2013, Gaius Mulley wrote:
>
>> As an example of why this is required - the Modula-2 compiler driver
>> uses its own linker.  So it needs to both suppress the default linker
>> and also get a list of objects generated from a compiler invocation.
>
> I think you'll need to explain that a lot more - what you mean by using 
> its own linker, why it uses it, and what the implications are for 
> mixed-language programs, for LTO, for target-specific aspects of linker 
> specs (including LINK_COMMAND_SPEC).  In general patches submitted 
> separately from the front end need to be given a self-contained 
> motivation - it's a lot harder to get confidence in the design of a 
> feature without users of that feature being posted at the same time.

Thanks for all the comments regarding the set of patches.  Perhaps the
statement "use its own linker" is misleading.  When gm2 is asked to link
a module hello.mod it does the following:

  gm2 hello.mod
    (compiles hello.mod -> hello.o)
    (and now performs the link) which involves:

  (a)   building up a dependency graph of all dependent modules (thus the
        requirement that the user supply foo.mod rather than foo.o).
  (b)   with this list it works out where the objects reside (user
        directories or system installed libraries/archives).
  (c)   builds up a scaffold main module (by default in C++ although
        users can request C - normally for small memory targets).
        In C++ this scaffold takes the form:

extern "C" void exit(int);

extern "C" void RTExceptions_DefaultErrorCatch(void);
extern "C" void _M2_Storage_init (int argc, char *argv[]);
extern "C" void _M2_Storage_finish (void);
extern "C" void _M2_SYSTEM_init (int argc, char *argv[]);
extern "C" void _M2_SYSTEM_finish (void);
extern "C" void _M2_M2RTS_init (int argc, char *argv[]);
extern "C" void _M2_M2RTS_finish (void);
extern "C" void _M2_RTExceptions_init (int argc, char *argv[]);
extern "C" void _M2_RTExceptions_finish (void);
extern "C" void _M2_ASCII_init (int argc, char *argv[]);
extern "C" void _M2_ASCII_finish (void);
extern "C" void _M2_Debug_init (int argc, char *argv[]);
extern "C" void _M2_Debug_finish (void);
extern "C" void _M2_SysStorage_init (int argc, char *argv[]);
extern "C" void _M2_SysStorage_finish (void);
extern "C" void _M2_StrLib_init (int argc, char *argv[]);
extern "C" void _M2_StrLib_finish (void);
extern "C" void _M2_Indexing_init (int argc, char *argv[]);
extern "C" void _M2_Indexing_finish (void);
extern "C" void _M2_termios_init (int argc, char *argv[]);
extern "C" void _M2_termios_finish (void);
extern "C" void _M2_FIO_init (int argc, char *argv[]);
extern "C" void _M2_FIO_finish (void);
extern "C" void _M2_errno_init (int argc, char *argv[]);
extern "C" void _M2_errno_finish (void);
extern "C" void _M2_IO_init (int argc, char *argv[]);
extern "C" void _M2_IO_finish (void);
extern "C" void _M2_StdIO_init (int argc, char *argv[]);
extern "C" void _M2_StdIO_finish (void);
extern "C" void _M2_M2EXCEPTION_init (int argc, char *argv[]);
extern "C" void _M2_M2EXCEPTION_finish (void);
extern "C" void _M2_SysExceptions_init (int argc, char *argv[]);
extern "C" void _M2_SysExceptions_finish (void);
extern "C" void _M2_StrIO_init (int argc, char *argv[]);
extern "C" void _M2_StrIO_finish (void);
extern "C" void _M2_NumberIO_init (int argc, char *argv[]);
extern "C" void _M2_NumberIO_finish (void);
extern "C" void _M2_hello_init (int argc, char *argv[]);
extern "C" void _M2_hello_finish (void);

extern "C" void M2RTS_ExecuteTerminationProcedures(void);
extern "C" void M2RTS_ExecuteInitialProcedures(void);

static void init (int argc, char *argv[])
{
   try {
       _M2_Storage_init (argc, argv);
       _M2_SYSTEM_init (argc, argv);
       _M2_M2RTS_init (argc, argv);
       _M2_RTExceptions_init (argc, argv);
       _M2_ASCII_init (argc, argv);
       _M2_Debug_init (argc, argv);
       _M2_SysStorage_init (argc, argv);
       _M2_StrLib_init (argc, argv);
       _M2_Indexing_init (argc, argv);
       _M2_termios_init (argc, argv);
       _M2_FIO_init (argc, argv);
       _M2_errno_init (argc, argv);
       _M2_IO_init (argc, argv);
       _M2_StdIO_init (argc, argv);
       _M2_M2EXCEPTION_init (argc, argv);
       _M2_SysExceptions_init (argc, argv);
       _M2_StrIO_init (argc, argv);
       _M2_NumberIO_init (argc, argv);
      M2RTS_ExecuteInitialProcedures ();
       _M2_hello_init (argc, argv);
    }
    catch (...) {
       RTExceptions_DefaultErrorCatch();
    }
}

static void finish (void)
{
   try {
      M2RTS_ExecuteTerminationProcedures ();
      _M2_hello_finish ();
      _M2_NumberIO_finish ();
      _M2_StrIO_finish ();
      _M2_SysExceptions_finish ();
      _M2_M2EXCEPTION_finish ();
      _M2_StdIO_finish ();
      _M2_IO_finish ();
      _M2_errno_finish ();
      _M2_FIO_finish ();
      _M2_termios_finish ();
      _M2_Indexing_finish ();
      _M2_StrLib_finish ();
      _M2_SysStorage_finish ();
      _M2_Debug_finish ();
      _M2_ASCII_finish ();
      _M2_RTExceptions_finish ();
      _M2_M2RTS_finish ();
      _M2_SYSTEM_finish ();
      _M2_Storage_finish ();
      exit (0);
    }
    catch (...) {
       RTExceptions_DefaultErrorCatch();
    }
}

int main (int argc, char *argv[])
{
   init (argc, argv);
   finish ();
   return (0);
}


  (d)  it compiles this using g++
  (e)  archives all dependent objects to a temporary archive
  (f)  links the final scaffold + temporary archive against chosen
       system libraries (pim, iso) by invoking 'gcc'.

you can just pass hello.o to 'gm2' and it would treat it in the same way
as 'gcc' - just that users would need to maintain their own scaffold
program.  gm2 allows users to maintain their own dependency list and
pass this into the link process (useful if the init order needs to be
altered).

This works well with mixed languages, I've had C++ throw exceptions and
Modula-2 catch them and visa versa.  It also works nicely with swig and
I've had Python catch an exception generated from Modula-2.  A Modula-2
module can be made into a Python module with a two line link command.

  http://gcc.gnu.org/wiki/summit2010?action=AttachFile&do=get&target=gaius-gcc2010.pdf

The LINK_COMMAND_SPEC is unaltered as ultimately gcc does do the final
link after the above is complete.

> I suspect that some of the driver changes could better be motivated, in 
> the absence of a front-end submission, as part of a refactoring of 
> existing drivers, if there is anything you found existing drivers did that 
> you also wanted to do in your driver but where there was no better way of 
> using it than copy-and-paste.
>
>> /*
>>  *  lang_register_spec_functions - register the Modula-2 associated
>>  *                                 spec functions.
>>  */
>
> Note the leading "*" on each line of comments isn't GNU style.

ah yes sorry!

>> void lang_register_spec_functions (void)
>
> And there should be a newline not a space between the return type and the 
> function name.
>
>> 2013-11-21  Gaius Mulley   <gaius.mulley@southwales.ac.uk>
>> 
>>         * gcc/gcc.c (handle_OPT_B): New function which reduces size of
>
> ChangeLot entries don't include the leading gcc/ - they are always 
> relative to the directory containing the ChangeLog file.

ok.

>> @@ -757,6 +762,7 @@
>>  /* We pass any -flto flags on to the linker, which is expected
>>     to understand them.  In practice, this means it had better be collect2.  */
>>  /* %{e*} includes -export-dynamic; see comment in common.opt.  */
>> +
>>  #ifndef LINK_COMMAND_SPEC
>>  #define LINK_COMMAND_SPEC "\
>>  %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
>
> Generally avoid spurious diff hunks like this that just change whitespace 
> in existing code.

yes indeed, sorry.

>> +/* front end registered spec functions */
>
> Comments should start with a capital letter and end with ".  */".

many thanks for taking the time to comment on the patch,

regards,
Gaius



More information about the Gcc-patches mailing list