diff mbox series

[Modula-2,(C/C++/D/F/Go/Jit)] (Register spec fn) (v3)

Message ID 87k17z3sls.fsf@j228-gm.comp.glam.ac.uk
State New
Headers show
Series [Modula-2,(C/C++/D/F/Go/Jit)] (Register spec fn) (v3) | expand

Commit Message

Gaius Mulley Nov. 17, 2019, 6:49 a.m. UTC
Hello,

while spending the weekend on the Howland and Baker islands :-) I
thought I'd post version three of the patches which introduce Modula-2
into the GCC trunk.  The patches include:

  (*)  a patch to allow all front ends to register a lang spec function.
       (included are patches for all front ends to provide an empty
       callback function).
  (*)  patch diffs to allow the Modula-2 front end driver to be
       built using GCC Makefile and friends.

The compressed tarball includes:

  (*)  gcc/m2  (compiler driver and lang-spec stuff for Modula-2).
       Including the need for registering lang spec functions.
  (*)  gcc/testsuite/gm2  (a Modula-2 dejagnu test to ensure that
       the gm2 driver is built and can understands --version).

To integrate the changes you need to apply the patches and also extract
the tarball in the gcc directory:

   cd gcc-versionno/gcc && tar zxf gm2-v3.tar.gz

These patches have been re-written after taking on board the comments
found in these threads:

   https://gcc.gnu.org/ml/gcc-patches/2013-11/msg02620.html
   https://gcc.gnu.org/ml/gcc-patches/2019-06/msg00220.html
   https://gcc.gnu.org/ml/gcc-patches/2019-06/msg01885.html

In summary coding standards changes have been applied.  Modula-2
command line library choices are checked, all errors/asserts use GCC
routines and configure.ac is used instead of configure.in.

I've run make bootstrap and run the regression tests on trunk and no
extra failures occur for all languages touched in the ChangeLog.

I'm continuing to track gcc trunk with gm2 (master branch), which
builds on ppc64, amd64, armv7l and aarch64 (and have fixed
library/license gpl3 issues).  However these patches are currently
simply for the driver and a really basic testsuite case to minimise
the patch size.

At a later point (after it is reviewed/approved) the gm2 tree
http://git.savannah.gnu.org/cgit/gm2.git/tree/gcc-versionno/m2/ could
be included.  Together with the gm2 testsuite.

But for now here are the proposed patches and ChangeLogs and new files
(gm2-v3.tar.gz) (after the patches):

./ChangeLog

2019-11-16  Gaius Mulley  <gaius.mulley@southwales.ac.uk>

        * configure.ac (GM2_FOR_BUILD): Added.
        (GM2_FOR_TARGET): Added.
        Request build driver program gm2.
	(compare_exclusions) Add gcc/m2/gm2version.
        * Makefile.def (flags_to_pass): Added GM2_FOR_TARGET.
        Added (GM2FLAGS_FOR_TARGET): Added.  Assign GM2,
        * Makefile.tpl (GM2FLAGS): Added.
	(BUILD_EXPORTS): Added (GM2).  Added (GM2_FOR_BUILD).
        (EXTRA_TARGET_FLAGS): Added (GM2).  Added (GM2_FOR_TARGET).
	Added (GM2FLAGS).  Added (GM2FLAGS_FOR_TARGET).
	(BASE_TARGET_EXPORTS): Added (GM2).  Added (GM2_FOR_TARGET).
	(GM2_FOR_BUILD): Added.
	(GM2FLAGS): Added.
	(GM2_FOR_TARGET): Added.
	(EXTRA_HOST_FLAGS): Added (GM2).
	(POSTSTAGE1_FLAGS_TO_PASS): Added (GM2).  Added (GM2_FOR_BUILD).

./gcc/ChangeLog

2019-11-16  Gaius Mulley  <gaius.mulley@southwales.ac.uk>

        * gcc.c (allow_linker): Global variable to disable
        linker by the front end.
        (xputenv) remove static prototype.
        (lang_spec_functions): New variable.
        (lang_spec_functions_length): New variable.
        (xputenv): Removed static.
        (xgetenv): New function.
        (add_infile): Removed static.
        (fe_add_linker_option): New function to allow front ends
        to add linker options.
        (handle_OPT_B): New function to handle the -B option.
        (fe_mark_compiled): New function to mark a file as compiled.
        (driver_handle_option): Call handle_OPT_B.
        (print_option): New developer debugging function.
        (print_options): New developer debugging function.
        (dbg_options): New developer debugging function.
        (fe_add_spec_function): New function.
        (lookup_spec_function): Extended to search language
        spec functions.
        (driver::set_up_specs): Call (lang_register_spec_functions).
        (driver::maybe_run_linker): Test (allow_linker).
        * gcc.h (handle_OPT_B): Prototype.
        (fe_mark_compiled): Prototype.
        (save_switch): Prototype.
        (handle_OPT_B): Prototype.
        (fe_mark_compiled): Prototype.
        (fe_add_linker_option): Prototype.
        (fe_add_spec_function): Prototype.
        (xputenv): Prototype.
        (xgetenv): Prototype.
        (print_options): Prototype.
        (print_option): Prototype.
        (dbg_options): Prototype.
        (lang_register_spec_functions): Prototype.
        (allow_linker): Extern.
        * gcc/brig/brigspec.c (lang_register_spec_functions): Added.
        * c/gccspec.c (lang_register_spec_functions): Added.
        * c-family/cppspec.c (lang_register_spec_functions): Added.
        * cp/g++spec.c (lang_register_spec_functions): Added.
        * d/d-spec.cc (lang_register_spec_functions): Added.
        * fortran/gfortranspec.c(lang_register_spec_functions): Added.
        * gcc/go/gospec.c (lang_register_spec_functions): Added.
        * jit/jit-spec.c (lang_register_spec_functions): Added.
regards,
Gaius

Comments

Matthias Klose Dec. 6, 2019, 4:34 p.m. UTC | #1
On 17.11.19 07:49, Gaius Mulley wrote:
> 
> Hello,
> 
> while spending the weekend on the Howland and Baker islands :-) I
> thought I'd post version three of the patches which introduce Modula-2
> into the GCC trunk.  The patches include:

[...]

> At a later point (after it is reviewed/approved) the gm2 tree
> http://git.savannah.gnu.org/cgit/gm2.git/tree/gcc-versionno/m2/ could
> be included.  Together with the gm2 testsuite.
> 
> But for now here are the proposed patches and ChangeLogs and new files
> (gm2-v3.tar.gz) (after the patches):

I have updated my distro packaging to build gcc-10, including gm2 from the
trunk.  Both native and cross builds seem to work, with some glitches:

 - For native builds, the profiled build doesn't work, failing to link
   the gcov library. Failing that, I can't check the lto+profiled build.
   Both the profiled and lto+profiled builds are working on your gcc-9
   branch.

 - For cross builds, the libgm2 libraries install as host libraries,
   not target libraries (but are correctly built).  I sent one patch
   to Gaius, but couldn't figure out yet, why the libs are not
   installed as target libraries.

The packages are publicly available in Debian experimental [1] and Ubuntu focal
[2], test results are sent to the gcc-testresults ML.

Are you still aiming for inclusion in GCC 10?

Matthias

[1] https://tracker.debian.org/pkg/gcc-10
[2]
https://launchpad.net/~doko/+archive/ubuntu/toolchain/+sourcepub/10781708/+listing-archive-extra
Gaius Mulley Dec. 9, 2019, 4:41 p.m. UTC | #2
Matthias Klose <doko@ubuntu.com> writes:

> On 17.11.19 07:49, Gaius Mulley wrote:
>> 
>> Hello,
>> 
>> while spending the weekend on the Howland and Baker islands :-) I
>> thought I'd post version three of the patches which introduce Modula-2
>> into the GCC trunk.  The patches include:
>
> [...]
>
>> At a later point (after it is reviewed/approved) the gm2 tree
>> http://git.savannah.gnu.org/cgit/gm2.git/tree/gcc-versionno/m2/ could
>> be included.  Together with the gm2 testsuite.
>> 
>> But for now here are the proposed patches and ChangeLogs and new files
>> (gm2-v3.tar.gz) (after the patches):
>
> I have updated my distro packaging to build gcc-10, including gm2 from the
> trunk.  Both native and cross builds seem to work, with some glitches:
>
>  - For native builds, the profiled build doesn't work, failing to link
>    the gcov library. Failing that, I can't check the lto+profiled build.
>    Both the profiled and lto+profiled builds are working on your gcc-9
>    branch.
>
>  - For cross builds, the libgm2 libraries install as host libraries,
>    not target libraries (but are correctly built).  I sent one patch
>    to Gaius, but couldn't figure out yet, why the libs are not
>    installed as target libraries.
>
> The packages are publicly available in Debian experimental [1] and Ubuntu focal
> [2], test results are sent to the gcc-testresults ML.
>
> Are you still aiming for inclusion in GCC 10?
>
> Matthias
>
> [1] https://tracker.debian.org/pkg/gcc-10
> [2]
> https://launchpad.net/~doko/+archive/ubuntu/toolchain/+sourcepub/10781708/+listing-archive-extra

Hello,

yes I'm still aiming for inclusion in GCC 10.  I'm still examining the
target/host bugs in the libgm2 build infrastructure (and slowly going
insane :-).  I'll also look at the lto+profiled build - great to hear
the gcc-9/gm2 branch works.  How do the GCC 10 gm2 v3 patches look?


regards,
Gaius
Matthias Klose Dec. 10, 2019, 1:41 p.m. UTC | #3
On 09.12.19 17:41, Gaius Mulley wrote:
> Matthias Klose <doko@ubuntu.com> writes:
> 
>> On 17.11.19 07:49, Gaius Mulley wrote:
>>>
>>> Hello,
>>>
>>> while spending the weekend on the Howland and Baker islands :-) I
>>> thought I'd post version three of the patches which introduce Modula-2
>>> into the GCC trunk.  The patches include:
>>
>> [...]
>>
>>> At a later point (after it is reviewed/approved) the gm2 tree
>>> http://git.savannah.gnu.org/cgit/gm2.git/tree/gcc-versionno/m2/ could
>>> be included.  Together with the gm2 testsuite.
>>>
>>> But for now here are the proposed patches and ChangeLogs and new files
>>> (gm2-v3.tar.gz) (after the patches):
>>
>> I have updated my distro packaging to build gcc-10, including gm2 from the
>> trunk.  Both native and cross builds seem to work, with some glitches:
>>
>>  - For native builds, the profiled build doesn't work, failing to link
>>    the gcov library. Failing that, I can't check the lto+profiled build.
>>    Both the profiled and lto+profiled builds are working on your gcc-9
>>    branch.
>>
>>  - For cross builds, the libgm2 libraries install as host libraries,
>>    not target libraries (but are correctly built).  I sent one patch
>>    to Gaius, but couldn't figure out yet, why the libs are not
>>    installed as target libraries.
>>
>> The packages are publicly available in Debian experimental [1] and Ubuntu focal
>> [2], test results are sent to the gcc-testresults ML.
>>
>> Are you still aiming for inclusion in GCC 10?
>>
>> Matthias
>>
>> [1] https://tracker.debian.org/pkg/gcc-10
>> [2]
>> https://launchpad.net/~doko/+archive/ubuntu/toolchain/+sourcepub/10781708/+listing-archive-extra
> 
> Hello,
> 
> yes I'm still aiming for inclusion in GCC 10.  I'm still examining the
> target/host bugs in the libgm2 build infrastructure (and slowly going
> insane :-).  I'll also look at the lto+profiled build - great to hear
> the gcc-9/gm2 branch works.  How do the GCC 10 gm2 v3 patches look?

I didn't have to modify any of these for my gcc-10 packaging, from my point of
view these look ok. However I can't officially review any of those.

Matthias
diff mbox series

Patch

--- gcc-versionno-orig/configure.ac	2019-11-16 19:39:50.601732918 +0000
+++ gcc-versionno/configure.ac	2019-11-16 21:55:44.558406239 +0000
@@ -1329,6 +1329,7 @@ 
   GFORTRAN_FOR_BUILD=${GFORTRAN_FOR_BUILD-gfortran}
   GOC_FOR_BUILD=${GOC_FOR_BUILD-gccgo}
   GDC_FOR_BUILD=${GDC_FOR_BUILD-gdc}
+  GM2_FOR_BUILD=${GM2_FOR_BUILD-gm2}
   DLLTOOL_FOR_BUILD=${DLLTOOL_FOR_BUILD-dlltool}
   LD_FOR_BUILD=${LD_FOR_BUILD-ld}
   NM_FOR_BUILD=${NM_FOR_BUILD-nm}
@@ -1343,6 +1344,7 @@ 
   GFORTRAN_FOR_BUILD="\$(GFORTRAN)"
   GOC_FOR_BUILD="\$(GOC)"
   GDC_FOR_BUILD="\$(GDC)"
+  GM2_FOR_BUILD="\$(GM2)"
   DLLTOOL_FOR_BUILD="\$(DLLTOOL)"
   LD_FOR_BUILD="\$(LD)"
   NM_FOR_BUILD="\$(NM)"
@@ -3353,6 +3355,7 @@ 
 AC_SUBST(GFORTRAN_FOR_BUILD)
 AC_SUBST(GOC_FOR_BUILD)
 AC_SUBST(GDC_FOR_BUILD)
+AC_SUBST(GM2_FOR_BUILD)
 AC_SUBST(LDFLAGS_FOR_BUILD)
 AC_SUBST(LD_FOR_BUILD)
 AC_SUBST(NM_FOR_BUILD)
@@ -3464,6 +3467,7 @@ 
 NCN_STRICT_CHECK_TARGET_TOOLS(GFORTRAN_FOR_TARGET, gfortran)
 NCN_STRICT_CHECK_TARGET_TOOLS(GOC_FOR_TARGET, gccgo)
 NCN_STRICT_CHECK_TARGET_TOOLS(GDC_FOR_TARGET, gdc)
+NCN_STRICT_CHECK_TARGET_TOOLS(GM2_FOR_TARGET, gm2)

 ACX_CHECK_INSTALLED_TARGET_TOOL(AR_FOR_TARGET, ar)
 ACX_CHECK_INSTALLED_TARGET_TOOL(AS_FOR_TARGET, as)
@@ -3500,6 +3504,8 @@ 
 		[gcc/gccgo -B$$r/$(HOST_SUBDIR)/gcc/], go)
 GCC_TARGET_TOOL(gdc, GDC_FOR_TARGET, GDC,
 		[gcc/gdc -B$$r/$(HOST_SUBDIR)/gcc/], d)
+GCC_TARGET_TOOL(gm2, GM2_FOR_TARGET, GM2,
+		[gcc/xgm2 -B$$r/$(HOST_SUBDIR)/gcc/], m2)
 GCC_TARGET_TOOL(ld, LD_FOR_TARGET, LD, [ld/ld-new])
 GCC_TARGET_TOOL(lipo, LIPO_FOR_TARGET, LIPO)
 GCC_TARGET_TOOL(nm, NM_FOR_TARGET, NM, [binutils/nm-new])
@@ -3625,11 +3631,11 @@ 

 # Specify what files to not compare during bootstrap.

-compare_exclusions="gcc/cc*-checksum\$(objext) | gcc/ada/*tools/*"
+compare_exclusions="gcc/cc*-checksum\$(objext) | gcc/ada/*tools/* | gcc/m2/gm2version\$(objext) "
 case "$target" in
   hppa*64*-*-hpux*) ;;
-  hppa*-*-hpux*) compare_exclusions="gcc/cc*-checksum\$(objext) | */libgcc/lib2funcs* | gcc/ada/*tools/* | gcc/function-tests.o" ;;
-  powerpc*-ibm-aix*) compare_exclusions="gcc/cc*-checksum\$(objext) | gcc/ada/*tools/* | *libgomp*\$(objext)" ;;
+  hppa*-*-hpux*) compare_exclusions="gcc/cc*-checksum\$(objext) | */libgcc/lib2funcs* | gcc/ada/*tools/* | gcc/function-tests.o | gcc/m2/gm2version\$(objext)" ;;
+  powerpc*-ibm-aix*) compare_exclusions="gcc/cc*-checksum\$(objext) | gcc/ada/*tools/* | *libgomp*\$(objext) | gcc/m2/gm2version\$(objext)" ;;
 esac
 AC_SUBST(compare_exclusions)

--- gcc-versionno-orig/gcc/gcc.c	2019-11-16 19:41:24.653085080 +0000
+++ gcc-versionno/gcc/gcc.c	2019-11-16 21:10:17.581547801 +0000
@@ -304,6 +304,9 @@ 
 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;
@@ -332,7 +335,6 @@ 
 static struct compiler *lookup_compiler (const char *, size_t, const char *);
 static char *build_search_list (const struct path_prefix *, const char *,
 				bool, bool);
-static void xputenv (const char *);
 static void putenv_from_prefixes (const struct path_prefix *, const char *,
 				  bool);
 static int access_check (const char *, int);
@@ -1654,6 +1656,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
@@ -2745,12 +2751,20 @@ 

 /* Add or change the value of an environment variable, outputting the
    change to standard error if in verbose mode.  */
-static void
+void
 xputenv (const char *string)
 {
   env.xput (string);
 }

+/* Get the environment variable through the managed env.  */
+
+const char *
+xgetenv (const char *key)
+{
+  return env.get (key);
+}
+
 /* Build a list of search directories from PATHS.
    PREFIX is a string to prepend to the list.
    If CHECK_DIR_P is true we ensure the directory exists.
@@ -3651,7 +3665,7 @@ 
 /* Store an input file with the given NAME and LANGUAGE in
    infiles.  */

-static void
+void
 add_infile (const char *name, const char *language)
 {
   alloc_infile ();
@@ -3679,7 +3693,7 @@ 
 /* 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.  */

-static void
+void
 save_switch (const char *opt, size_t n_args, const char *const *args,
 	     bool validated, bool known)
 {
@@ -3724,6 +3738,58 @@ 
   setenv ("SOURCE_DATE_EPOCH", source_date_epoch, 0);
 }

+void
+fe_add_linker_option (const char *option)
+{
+  add_linker_option (option, strlen (option));
+}
+
+/* Handle the -B option by adding the prefix to exec, startfile and
+   include search paths.  */
+
+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);
+}
+
+/* Mark a file as compiled.  */
+
+void
+fe_mark_compiled (const char *name)
+{
+  int max = n_infiles + lang_specific_extra_outfiles;
+  int i;
+
+  for (i = 0; i < max; i++)
+    if (filename_cmp (name, infiles[i].name) == 0)
+      infiles[i].compiled = true;
+}
+
 /* Handle an option DECODED that is unknown to the option-processing
    machinery.  */

@@ -4207,33 +4273,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;

@@ -4319,6 +4359,68 @@ 
   handlers->handlers[2].mask = CL_TARGET;
 }

+/* print_option a debugging routine to display option i with a leading desc
+   string.  */
+
+void
+print_option (const char *desc, unsigned int i,
+	      struct cl_decoded_option *in_decoded_options)
+{
+  printf (desc);
+  printf (" [%d]", i);
+  switch (in_decoded_options[i].opt_index)
+    {
+
+    case N_OPTS:
+      break;
+    case OPT_SPECIAL_unknown:
+      printf (" flag <unknown>");
+      break;
+    case OPT_SPECIAL_ignore:
+      printf (" flag <ignore>");
+      break;
+    case OPT_SPECIAL_program_name:
+      printf (" flag <program name>");
+      break;
+    case OPT_SPECIAL_input_file:
+      printf (" flag <input file name>");
+      break;
+    default:
+      printf (" flag [%s]",
+              cl_options[in_decoded_options[i].opt_index].opt_text);
+    }
+
+  if (in_decoded_options[i].arg == NULL)
+    printf (" no arg");
+  else
+    printf (" arg [%s]", in_decoded_options[i].arg);
+  printf (" orig text [%s]",
+          in_decoded_options[i].orig_option_with_args_text);
+  printf (" value [%ld]", in_decoded_options[i].value);
+  printf (" error [%d]\n", in_decoded_options[i].errors);
+}
+
+/* print_options display all options with a leading string desc.  */
+
+void
+print_options (const char *desc,
+	       unsigned int in_decoded_options_count,
+	       struct cl_decoded_option *in_decoded_options)
+{
+  for (unsigned int i = 0; i < in_decoded_options_count; i++)
+    print_option (desc, i, in_decoded_options);
+}
+
+/* dbg_options display all options.  */
+
+void
+dbg_options (unsigned int in_decoded_options_count,
+	     struct cl_decoded_option *in_decoded_options)
+{
+  print_options ("dbg_options", in_decoded_options_count,
+		 in_decoded_options);
+}
+
 /* Create the vector `switches' and its contents.
    Store its length in `n_switches'.  */

@@ -6072,6 +6174,37 @@ 
   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 (input_location, "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 *
@@ -6083,6 +6216,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;
 }

@@ -7568,6 +7706,8 @@ 
 			   accel_dir_suffix, 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"))
@@ -8264,7 +8404,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;

@@ -8333,7 +8474,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-versionno-orig/gcc/gcc.h	2019-11-16 19:41:24.657085054 +0000
+++ gcc-versionno/gcc/gcc.h	2019-11-16 21:14:25.339946029 +0000
@@ -73,9 +73,27 @@ 
 extern int do_spec (const char *);
 extern void record_temp_file (const char *, int, int);
 extern void set_input (const char *);
+extern void save_switch (const char *opt, size_t n_args,
+			 const char *const *args,
+			 bool validated, bool known);
+extern void handle_OPT_B (const char *arg);
+extern void fe_mark_compiled (const char *);
+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 xputenv (const char *value);
+extern const char *xgetenv (const char *key);
+extern void print_options (const char *desc,
+			   unsigned int in_decoded_options_count,
+			   struct cl_decoded_option *in_decoded_options);
+extern void print_option (const char *desc, unsigned int i,
+			  struct cl_decoded_option *in_decoded_options);
+extern void dbg_options (unsigned int in_decoded_options_count,
+			 struct cl_decoded_option *in_decoded_options);

 /* Spec files linked with gcc.c must provide definitions for these.  */

+extern void lang_register_spec_functions (void);
+
 /* Called before processing to change/add/remove arguments.  */
 extern void lang_specific_driver (struct cl_decoded_option **,
 				  unsigned int *, int *);
@@ -97,4 +115,8 @@ 
 					      void *user_data),
 				   void *user_data);

+/* 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-versionno-orig/Makefile.def	2019-11-16 19:53:44.140002522 +0000
+++ gcc-versionno/Makefile.def	2019-11-16 19:31:07.169352156 +0000
@@ -169,6 +169,7 @@ 
 target_modules = { module= zlib; };
 target_modules = { module= rda; };
 target_modules = { module= libada; };
+// target_modules = { module= libgm2; lib_path=.libs; };
 target_modules = { module= libgomp; bootstrap= true; lib_path=.libs; };
 target_modules = { module= libitm; lib_path=.libs; };
 target_modules = { module= libatomic; lib_path=.libs; };
@@ -287,6 +288,8 @@ 
 flags_to_pass = { flag= GOCFLAGS_FOR_TARGET ; };
 flags_to_pass = { flag= GDC_FOR_TARGET ; };
 flags_to_pass = { flag= GDCFLAGS_FOR_TARGET ; };
+flags_to_pass = { flag= GM2_FOR_TARGET ; };
+flags_to_pass = { flag= GM2FLAGS_FOR_TARGET ; };
 flags_to_pass = { flag= LD_FOR_TARGET ; };
 flags_to_pass = { flag= LIPO_FOR_TARGET ; };
 flags_to_pass = { flag= LDFLAGS_FOR_TARGET ; };
@@ -622,6 +625,7 @@ 
 languages = { language=go;	gcc-check-target=check-go;
 				lib-check-target=check-target-libgo;
 				lib-check-target=check-gotools; };
+languages = { language=m2;	gcc-check-target=check-m2; };
 languages = { language=brig;	gcc-check-target=check-brig;
 				lib-check-target=check-target-libhsail-rt; };
 languages = { language=d;	gcc-check-target=check-d;
--- gcc-versionno-orig/Makefile.tpl	2019-11-16 19:53:44.891997361 +0000
+++ gcc-versionno/Makefile.tpl	2019-11-16 19:31:07.169352156 +0000
@@ -161,6 +161,7 @@ 
 	GOCFLAGS="$(GOCFLAGS_FOR_BUILD)"; export GOCFLAGS; \
 	GDC="$(GDC_FOR_BUILD)"; export GDC; \
 	GDCFLAGS="$(GDCFLAGS_FOR_BUILD)"; export GDCFLAGS; \
+	GM2="$(GM2_FOR_BUILD)"; export GM2; \
 	DLLTOOL="$(DLLTOOL_FOR_BUILD)"; export DLLTOOL; \
 	LD="$(LD_FOR_BUILD)"; export LD; \
 	LDFLAGS="$(LDFLAGS_FOR_BUILD)"; export LDFLAGS; \
@@ -198,6 +199,7 @@ 
 	GFORTRAN="$(GFORTRAN)"; export GFORTRAN; \
 	GOC="$(GOC)"; export GOC; \
 	GDC="$(GDC)"; export GDC; \
+	GM2="$(GM2)"; export GM2; \
 	AR="$(AR)"; export AR; \
 	AS="$(AS)"; export AS; \
 	CC_FOR_BUILD="$(CC_FOR_BUILD)"; export CC_FOR_BUILD; \
@@ -296,6 +298,7 @@ 
 	GFORTRAN="$(GFORTRAN_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GFORTRAN; \
 	GOC="$(GOC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GOC; \
 	GDC="$(GDC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GDC; \
+	GM2="$(GM2_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export GM2; \
 	DLLTOOL="$(DLLTOOL_FOR_TARGET)"; export DLLTOOL; \
 	LD="$(COMPILER_LD_FOR_TARGET)"; export LD; \
 	LDFLAGS="$(LDFLAGS_FOR_TARGET)"; export LDFLAGS; \
@@ -362,6 +365,7 @@ 
 GFORTRAN_FOR_BUILD = @GFORTRAN_FOR_BUILD@
 GOC_FOR_BUILD = @GOC_FOR_BUILD@
 GDC_FOR_BUILD = @GDC_FOR_BUILD@
+GM2_FOR_BUILD = @GM2_FOR_BUILD@
 LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
 LD_FOR_BUILD = @LD_FOR_BUILD@
 NM_FOR_BUILD = @NM_FOR_BUILD@
@@ -431,6 +435,7 @@ 
 LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates
 GOCFLAGS = $(CFLAGS)
 GDCFLAGS = $(CFLAGS)
+GM2FLAGS = $(CFLAGS)

 CREATE_GCOV = create_gcov

@@ -518,6 +523,7 @@ 
 GFORTRAN_FOR_TARGET=$(STAGE_CC_WRAPPER) @GFORTRAN_FOR_TARGET@
 GOC_FOR_TARGET=$(STAGE_CC_WRAPPER) @GOC_FOR_TARGET@
 GDC_FOR_TARGET=$(STAGE_CC_WRAPPER) @GDC_FOR_TARGET@
+GM2_FOR_TARGET=$(STAGE_CC_WRAPPER) @GM2_FOR_TARGET@
 DLLTOOL_FOR_TARGET=@DLLTOOL_FOR_TARGET@
 LD_FOR_TARGET=@LD_FOR_TARGET@

@@ -647,6 +653,7 @@ 
 	'GFORTRAN=$(GFORTRAN)' \
 	'GOC=$(GOC)' \
 	'GDC=$(GDC)' \
+	'GM2=$(GM2)' \
 	'LD=$(LD)' \
 	'LIPO=$(LIPO)' \
 	'NM=$(NM)' \
@@ -673,6 +680,7 @@ 
 	CC="$${CC}" CC_FOR_BUILD="$${CC_FOR_BUILD}" \
 	CXX="$${CXX}" CXX_FOR_BUILD="$${CXX_FOR_BUILD}" \
 	GDC="$${GDC}" GDC_FOR_BUILD="$${GDC_FOR_BUILD}" \
+	GM2="$${GM2}" GM2_FOR_BUILD="$${GM2_FOR_BUILD}" \
 	GNATBIND="$${GNATBIND}" \
 	LDFLAGS="$${LDFLAGS}" \
 	HOST_LIBS="$${HOST_LIBS}" \
@@ -707,6 +715,8 @@ 
 	'GOCFLAGS=$$(GOCFLAGS_FOR_TARGET)' \
 	'GDC=$$(GDC_FOR_TARGET) $$(XGCC_FLAGS_FOR_TARGET) $$(TFLAGS)' \
 	'GDCFLAGS=$$(GDCFLAGS_FOR_TARGET)' \
+	'GM2=$$(GM2_FOR_TARGET) $$(XGCC_FLAGS_FOR_TARGET) $$(TFLAGS)' \
+	'GM2FLAGS=$$(GM2FLAGS_FOR_TARGET)' \
 	'LD=$(COMPILER_LD_FOR_TARGET)' \
 	'LDFLAGS=$$(LDFLAGS_FOR_TARGET)' \
 	'LIBCFLAGS=$$(LIBCFLAGS_FOR_TARGET)' \
--- gcc-versionno-orig/gcc/brig/brigspec.c	2019-11-16 19:40:53.377300458 +0000
+++ gcc-versionno/gcc/brig/brigspec.c	2019-11-16 19:31:07.173352127 +0000
@@ -134,3 +134,11 @@ 
 /* Number of extra output files that lang_specific_pre_link may generate.  */

 int lang_specific_extra_outfiles = 0; /* Not used for Brig.  */
+
+/* lang_register_spec_functions register the Brig associated spec
+   functions.  Not used for Brig.  */
+
+void
+lang_register_spec_functions (void)
+{
+}
--- gcc-versionno-orig/gcc/c/gccspec.c	2019-11-16 19:41:07.637202254 +0000
+++ gcc-versionno/gcc/c/gccspec.c	2019-11-16 19:31:07.173352127 +0000
@@ -105,3 +105,9 @@ 

 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for C.  */
+
+/* lang_register_spec_functions.  Not used for C.  */
+void
+lang_register_spec_functions (void)
+{
+}
--- gcc-versionno-orig/gcc/c-family/cppspec.c	2019-11-16 19:41:05.457217265 +0000
+++ gcc-versionno/gcc/c-family/cppspec.c	2019-11-16 19:31:07.173352127 +0000
@@ -198,3 +198,9 @@ 

 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
+
+/* lang_register_spec_functions.  Not used for cpp.  */
+void
+lang_register_spec_functions (void)
+{
+}
--- gcc-versionno-orig/gcc/cp/g++spec.c	2019-11-16 19:47:37.750518964 +0000
+++ gcc-versionno/gcc/cp/g++spec.c	2019-11-16 19:31:07.173352127 +0000
@@ -403,3 +403,9 @@ 

 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for C++.  */
+
+/* lang_register_spec_functions.  Not used for C++.  */
+void
+lang_register_spec_functions (void)
+{
+}
--- gcc-versionno-orig/gcc/d/d-spec.cc	2019-11-16 19:41:10.645181539 +0000
+++ gcc-versionno/gcc/d/d-spec.cc	2019-11-16 19:31:07.541349571 +0000
@@ -514,3 +514,10 @@ 

 int lang_specific_extra_outfiles = 0;  /* Not used for D.  */

+/* lang_register_spec_functions register the D associated spec
+   functions.  Not used for D.  */
+
+void
+lang_register_spec_functions (void)
+{
+}
--- gcc-versionno-orig/gcc/fortran/gfortranspec.c	2019-11-16 19:49:45.657640192 +0000
+++ gcc-versionno/gcc/fortran/gfortranspec.c	2019-11-16 19:31:07.541349571 +0000
@@ -447,4 +447,12 @@ 
 }

 /* Number of extra output files that lang_specific_pre_link may generate.  */
-int lang_specific_extra_outfiles = 0;	/* Not used for F77.  */
+int lang_specific_extra_outfiles = 0;	/* Not used for Fortran.  */
+
+/* lang_register_spec_functions register the Fortran associated spec
+   functions.  */
+
+void
+lang_register_spec_functions (void)
+{
+}
--- gcc-versionno-orig/gcc/go/gospec.c	2019-11-16 19:47:58.686375101 +0000
+++ gcc-versionno/gcc/go/gospec.c	2019-11-16 19:31:07.545349543 +0000
@@ -440,3 +440,11 @@ 

 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for Go.  */
+
+/* lang_register_spec_functions register the Go associated spec
+   functions.  Not used for Go.  */
+
+void
+lang_register_spec_functions (void)
+{
+}
--- gcc-versionno-orig/gcc/jit/jit-spec.c	2019-11-16 19:41:29.569051233 +0000
+++ gcc-versionno/gcc/jit/jit-spec.c	2019-11-16 20:37:00.848833621 +0000
@@ -39,3 +39,11 @@ 

 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for jit.  */
+
+/* lang_register_spec_functions register the jit associated spec
+   functions.  Not used for jit.  */
+
+void
+lang_register_spec_functions (void)
+{
+}