diff mbox

[M2] Compiler driver patches

Message ID 87hab7vt8i.fsf@j228-gm.comp.glam.ac.uk
State New
Headers show

Commit Message

Gaius Mulley Nov. 20, 2013, 6:11 p.m. UTC
Here are some proposed patches which allow front end compiler drivers to
add command line arguments, add their own spec functions and also to
disable the default linker.

It does mean that each language front end compiler driver will need an
additional stub function, which at the very least does nothing.  The
patches below provide one for --languages=all.

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.

For more detail here is the Modula-2 lang_register_spec_functions:

/*
 *  lang_register_spec_functions - register the Modula-2 associated
 *                                 spec functions.
 */

void lang_register_spec_functions (void)
{
  fe_add_spec_function ("objects", get_objects);
  fe_add_spec_function ("nolink", no_link);
  fe_add_spec_function ("linkargs", get_link_args);
  fe_add_spec_function ("exec_prefix", add_exec_dir);
  fe_add_spec_function ("exec_name", add_exec_name);
}

The proposed patches for trunk were tested by configuring
--languages=all and building and running the regression testsuite.  No
further regressions were introduced.

Here is a possible gcc/ChangeLog entry:

2013-11-21  Gaius Mulley   <gaius.mulley@southwales.ac.uk>

        * gcc/gcc.c (handle_OPT_B): New function which reduces size of
        driver_handle_option.
        Also allows this function to be called by language
        specific spec option through fe_B_prefix.
        (fe_add_infile): New function non static.
        (fe_add_linker_option): New function, non static.
        (fe_add_spec_function): New function, non static.
        (fe_B_prefix): New function, non static.
        (fe_save_switch): New function, non static.
        * gcc/gcc.h (fe_add_infile): New function prototype.
        (fe_add_linker_option): New function prototype.
        (fe_add_spec_function): New function prototype.
        (fe_B_prefix): New function prototype.
        (fe_save_switch): New function prototype.
        allow_linker external declaration.
        gcc/c/gccspec.c (lang_register_spec_functions): New stub
        function.
        gcc/cp/g++spec.c (lang_register_spec_functions): New stub
        function.
        gcc/go/gospec.c (lang_register_spec_functions): New stub
        function.
        gcc/fortran/gfortranspec.c (lang_register_spec_functions):
        New stub function.
        gcc/java/jvspec.c (lang_register_spec_functions):
        New stub function.

The proposed patches follow:

Comments

Joseph Myers Nov. 20, 2013, 6:32 p.m. UTC | #1
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.

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.

> 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.

> @@ -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.

> +/* front end registered spec functions */

Comments should start with a capital letter and end with ".  */".
Gaius Mulley Nov. 20, 2013, 9:47 p.m. UTC | #2
"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
Joseph Myers Nov. 20, 2013, 10:47 p.m. UTC | #3
On Wed, 20 Nov 2013, Gaius Mulley wrote:

> 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:

Thanks for the explanation.  I think this is sufficiently complicated that 
driver patches to facilitate it can't effectively be reviewed separately 
from the gm2 driver itself (i.e. the two patches should be posted for 
review at the same time), unless the driver patches make sense as cleanups 
in their own right in the context of the front ends already in tree.

The sort of change that's more suitable for review indepedent of the front 
end would be e.g. fixes for optimization bugs where you've only triggered 
the bug with M2 input but will propose the patch on the basis that the 
GIMPLE produced by the front end is valid and is being transformed in an 
invalid way, even if no other front end produces that GIMPLE.
Gaius Mulley Nov. 21, 2013, 1:55 p.m. UTC | #4
"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Wed, 20 Nov 2013, Gaius Mulley wrote:
>
>> 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:
>
> Thanks for the explanation.  I think this is sufficiently complicated that 
> driver patches to facilitate it can't effectively be reviewed separately 
> from the gm2 driver itself (i.e. the two patches should be posted for 
> review at the same time), unless the driver patches make sense as cleanups 
> in their own right in the context of the front ends already in tree.
>
> The sort of change that's more suitable for review indepedent of the front 
> end would be e.g. fixes for optimization bugs where you've only triggered 
> the bug with M2 input but will propose the patch on the basis that the 
> GIMPLE produced by the front end is valid and is being transformed in an 
> invalid way, even if no other front end produces that GIMPLE.

Again thank you for the feedback - yes this all sounds sensible.  I'll
work on the patch for the 'gm2' driver and associated conforming front
end config and makefile files and submit them together with the above,

regards,
Gaius
diff mbox

Patch

--- gcc-trunk-svn/gcc/gcc.h	2013-11-14 14:53:57.000000000 +0000
+++ gcc-trunk/gcc/gcc.h	2013-11-20 15:10:21.264388233 +0000
@@ -36,6 +36,13 @@ 
 extern void record_temp_file (const char *, int, int);
 extern void pfatal_with_name (const char *) ATTRIBUTE_NORETURN;
 extern void set_input (const char *);
+extern void fe_save_switch (const char *opt, size_t n_args,
+			    const char *const *args, bool validated, bool known);
+extern void fe_B_prefix (const char *arg);
+extern void fe_add_infile (const char *infile, const char *lang);
+extern void fe_add_linker_option (const char *option);
+extern void fe_add_spec_function (const char *name, const char *(*func) (int, const char **));
+extern void lang_register_spec_functions (void);
 
 /* Spec files linked with gcc.c must provide definitions for these.  */
 
@@ -55,4 +62,8 @@ 
 
 extern const char **outfiles;
 
+/* Default setting is true, but can be overridden by the language
+   front end to prohibit the linker from being invoked.  */
+extern int allow_linker;
+
 #endif /* ! GCC_GCC_H */
--- gcc-trunk-svn/gcc/gcc.c	2013-11-14 14:53:57.000000000 +0000
+++ gcc-trunk/gcc/gcc.c	2013-11-20 16:49:08.928244038 +0000
@@ -164,6 +164,10 @@ 
 static const char *cross_compile = "0";
 #endif
 
+/* The lang specs might wish to override the default linker.
+ */
+int allow_linker = 1;
+
 /* Greatest exit code of sub-processes that has been encountered up to
    now.  */
 static int greatest_status = 1;
@@ -267,6 +271,7 @@ 
 static const char *pass_through_libs_spec_func (int, const char **);
 static const char *replace_extension_spec_func (int, const char **);
 static char *convert_white_space (char *);
+static void handle_OPT_B (const char *arg);
 
 /* The Specs Language
 
@@ -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:\
@@ -1361,6 +1367,10 @@ 
   { 0, 0 }
 };
 
+/* front end registered spec functions */
+static struct spec_function *lang_spec_functions = NULL;
+static unsigned int lang_spec_functions_length = 0;
+
 static int processing_spec_function;
 
 /* Add appropriate libgcc specs to OBSTACK, taking into account
@@ -3227,6 +3237,73 @@ 
   n_switches++;
 }
 
+/* Allow compiler driver to save an option OPT with N_ARGS arguments
+   in array ARGS, marking it as validated if VALIDATED and KNOWN if
+   it is an internal switch.  */
+
+void
+fe_save_switch (const char *opt, size_t n_args, const char *const *args,
+		bool validated, bool known)
+{
+  save_switch (opt, n_args, args, validated, known);
+}
+
+/* Allow compiler driver to add an OPT_B option.  */
+
+void fe_B_prefix (const char *arg)
+{
+  handle_OPT_B (arg);
+}
+
+/* Allow compiler driver to add linker options.  */
+
+void
+fe_add_linker_option (const char *option)
+{
+  add_linker_option (option, strlen (option));
+}
+
+/* Handle the OPT_B option by adding the prefix to exec, startfile and
+   include search paths.  */
+
+static
+void handle_OPT_B (const char *arg)
+{
+  size_t len = strlen (arg);
+  
+  /* Catch the case where the user has forgotten to append a
+     directory separator to the path.  Note, they may be using
+     -B to add an executable name prefix, eg "i386-elf-", in
+     order to distinguish between multiple installations of
+     GCC in the same directory.  Hence we must check to see
+     if appending a directory separator actually makes a
+     valid directory name.  */
+  if (!IS_DIR_SEPARATOR (arg[len - 1])
+      && is_directory (arg, false))
+    {
+      char *tmp = XNEWVEC (char, len + 2);
+      strcpy (tmp, arg);
+      tmp[len] = DIR_SEPARATOR;
+      tmp[++len] = 0;
+      arg = tmp;
+    }
+
+  add_prefix (&exec_prefixes, arg, NULL,
+	      PREFIX_PRIORITY_B_OPT, 0, 0);
+  add_prefix (&startfile_prefixes, arg, NULL,
+	      PREFIX_PRIORITY_B_OPT, 0, 0);
+  add_prefix (&include_prefixes, arg, NULL,
+	      PREFIX_PRIORITY_B_OPT, 0, 0);
+}
+
+/* Save the infile */
+
+void
+fe_add_infile (const char *infile, const char *lang)
+{
+  add_infile (infile, lang);
+}
+
 /* Handle an option DECODED that is unknown to the option-processing
    machinery.  */
 
@@ -3582,33 +3659,7 @@ 
       break;
 
     case OPT_B:
-      {
-	size_t len = strlen (arg);
-
-	/* Catch the case where the user has forgotten to append a
-	   directory separator to the path.  Note, they may be using
-	   -B to add an executable name prefix, eg "i386-elf-", in
-	   order to distinguish between multiple installations of
-	   GCC in the same directory.  Hence we must check to see
-	   if appending a directory separator actually makes a
-	   valid directory name.  */
-	if (!IS_DIR_SEPARATOR (arg[len - 1])
-	    && is_directory (arg, false))
-	  {
-	    char *tmp = XNEWVEC (char, len + 2);
-	    strcpy (tmp, arg);
-	    tmp[len] = DIR_SEPARATOR;
-	    tmp[++len] = 0;
-	    arg = tmp;
-	  }
-
-	add_prefix (&exec_prefixes, arg, NULL,
-		    PREFIX_PRIORITY_B_OPT, 0, 0);
-	add_prefix (&startfile_prefixes, arg, NULL,
-		    PREFIX_PRIORITY_B_OPT, 0, 0);
-	add_prefix (&include_prefixes, arg, NULL,
-		    PREFIX_PRIORITY_B_OPT, 0, 0);
-      }
+      handle_OPT_B (arg);
       validated = true;
       break;
 
@@ -5438,6 +5489,33 @@ 
   return 0;
 }
 
+/* Allow the front end to register a spec function.  */
+
+void fe_add_spec_function (const char *name, const char *(*func) (int, const char **))
+{
+  const struct spec_function *f = lookup_spec_function (name);
+  struct spec_function *fl;
+  unsigned int i;
+
+  if (f != NULL)
+    fatal_error ("spec function (%s) already registered", name);
+
+  if (lang_spec_functions == NULL)
+    lang_spec_functions_length = 1;
+
+  lang_spec_functions_length++;
+  fl = (struct spec_function *) xmalloc (sizeof (const struct spec_function)*lang_spec_functions_length);
+  for (i=0; i<lang_spec_functions_length-2; i++)
+    fl[i] = lang_spec_functions[i];
+  free (lang_spec_functions);
+  lang_spec_functions = fl;
+
+  lang_spec_functions[lang_spec_functions_length-2].name = name;
+  lang_spec_functions[lang_spec_functions_length-2].func = func;
+  lang_spec_functions[lang_spec_functions_length-1].name = NULL;
+  lang_spec_functions[lang_spec_functions_length-1].func = NULL;
+}
+
 /* Look up a spec function.  */
 
 static const struct spec_function *
@@ -5449,6 +5527,11 @@ 
     if (strcmp (sf->name, name) == 0)
       return sf;
 
+  if (lang_spec_functions != NULL)
+    for (sf = lang_spec_functions; sf->name != NULL; sf++)
+      if (strcmp (sf->name, name) == 0)
+	return sf;
+
   return NULL;
 }
 
@@ -6452,6 +6535,8 @@ 
 			   spec_version, dir_separator_str, NULL);
   just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
 
+  lang_register_spec_functions ();
+
   specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
   /* Read the specs file unless it is a default one.  */
   if (specs_file != 0 && strcmp (specs_file, "specs"))
@@ -7054,7 +7139,8 @@ 
 
   /* Run ld to link all the compiler output files.  */
 
-  if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
+  if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2
+      && allow_linker)
     {
       int tmp = execution_count;
 
@@ -7120,7 +7206,7 @@ 
   /* If options said don't run linker,
      complain about input files to be given to the linker.  */
 
-  if (! linker_was_run && !seen_error ())
+  if (! linker_was_run && !seen_error () && allow_linker)
     for (i = 0; (int) i < n_infiles; i++)
       if (explicit_link_files[i]
 	  && !(infiles[i].language && infiles[i].language[0] == '*'))
--- gcc-trunk-svn/gcc/c/gccspec.c	2013-11-14 14:48:29.000000000 +0000
+++ gcc-trunk/gcc/c/gccspec.c	2013-11-20 15:19:31.976372618 +0000
@@ -104,5 +104,11 @@ 
   return 0;  /* Not used for C.  */
 }
 
+/* lang_register_spec_functions.  Not used for C.  */
+void
+lang_register_spec_functions (void)
+{
+}
+
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for C.  */
--- gcc-trunk-svn/gcc/c-family/cppspec.c	2013-11-14 14:48:28.000000000 +0000
+++ gcc-trunk/gcc/c-family/cppspec.c	2013-11-20 13:51:02.968499605 +0000
@@ -194,5 +194,11 @@ 
   return 0;  /* Not used for cpp.  */
 }
 
+/* lang_register_spec_functions.  Not used for cpp.  */
+void
+lang_register_spec_functions (void)
+{
+}
+
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
--- gcc-trunk-svn/gcc/cp/g++spec.c	2013-11-14 14:52:52.000000000 +0000
+++ gcc-trunk/gcc/cp/g++spec.c	2013-11-20 13:50:25.676500496 +0000
@@ -369,5 +369,11 @@ 
   return 0;
 }
 
+/* lang_register_spec_functions.  Not used for C++.  */
+void
+lang_register_spec_functions (void)
+{
+}
+
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for C++.  */
--- gcc-trunk-svn/gcc/go/gospec.c	2013-11-14 14:52:54.000000000 +0000
+++ gcc-trunk/gcc/go/gospec.c	2013-11-20 13:52:13.572497916 +0000
@@ -406,5 +406,11 @@ 
   return 0;
 }
 
+/* lang_register_spec_functions.  Not used for Go.  */
+void
+lang_register_spec_functions (void)
+{
+}
+
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for Go.  */
--- gcc-trunk-svn/gcc/fortran/gfortranspec.c	2013-11-14 14:53:29.000000000 +0000
+++ gcc-trunk/gcc/fortran/gfortranspec.c	2013-11-20 15:19:26.984372552 +0000
@@ -480,5 +480,11 @@ 
   return 0;
 }
 
+/* lang_register_spec_functions.  Not used for fortran.  */
+void
+lang_register_spec_functions (void)
+{
+}
+
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;	/* Not used for F77.  */
--- gcc-trunk-svn/gcc/java/jvspec.c	2013-11-14 14:48:28.000000000 +0000
+++ gcc-trunk/gcc/java/jvspec.c	2013-11-20 14:51:59.372412643 +0000
@@ -641,3 +641,9 @@ 
     }
   return err;
 }
+
+/* lang_register_spec_functions.  Not used for Java.  */
+void
+lang_register_spec_functions (void)
+{
+}