Provide a way for spec fragments to detect which language specific
driver is in use. This allows for language-specific functionality to
be included during linking, like unwind constructors for C++ exception
handling.

Signed-off-by: Keith Packard <[email protected]>
---
 gcc/algol68/a68spec.cc      |  3 +++
 gcc/c-family/cppspec.cc     |  3 +++
 gcc/c/gccspec.cc            |  3 +++
 gcc/cobol/gcobolspec.cc     |  3 +++
 gcc/cp/g++spec.cc           |  3 +++
 gcc/d/d-spec.cc             |  2 ++
 gcc/doc/invoke.texi         | 17 +++++++++++++++++
 gcc/fortran/gfortranspec.cc |  3 +++
 gcc/gcc.cc                  | 28 ++++++++++++++++++++++++++++
 gcc/gcc.h                   |  3 +++
 gcc/go/gospec.cc            |  3 +++
 gcc/jit/jit-spec.cc         |  3 +++
 gcc/m2/gm2spec.cc           |  3 +++
 gcc/rust/rustspec.cc        |  3 +++
 14 files changed, 80 insertions(+)

diff --git a/gcc/algol68/a68spec.cc b/gcc/algol68/a68spec.cc
index bc11abde76e..6c9dbf05a9e 100644
--- a/gcc/algol68/a68spec.cc
+++ b/gcc/algol68/a68spec.cc
@@ -220,3 +220,6 @@ lang_specific_pre_link (void)
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0; /* Not used for Algol68.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = "algol68";
diff --git a/gcc/c-family/cppspec.cc b/gcc/c-family/cppspec.cc
index bee629f33df..c1f436a0bdd 100644
--- a/gcc/c-family/cppspec.cc
+++ b/gcc/c-family/cppspec.cc
@@ -198,3 +198,6 @@ int lang_specific_pre_link (void)
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = NULL;
diff --git a/gcc/c/gccspec.cc b/gcc/c/gccspec.cc
index af438f26f21..b47a5abd28d 100644
--- a/gcc/c/gccspec.cc
+++ b/gcc/c/gccspec.cc
@@ -105,3 +105,6 @@ lang_specific_pre_link (void)
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for C.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = "c";
diff --git a/gcc/cobol/gcobolspec.cc b/gcc/cobol/gcobolspec.cc
index 500d55dc6b1..672081a6a65 100644
--- a/gcc/cobol/gcobolspec.cc
+++ b/gcc/cobol/gcobolspec.cc
@@ -569,3 +569,6 @@ lang_specific_pre_link (void)
 
   return 0;
 }
+
+/* Language target for this driver */
+const char *lang_specific_language = "cobol";
diff --git a/gcc/cp/g++spec.cc b/gcc/cp/g++spec.cc
index ab6482d4f5d..7ddaacdf396 100644
--- a/gcc/cp/g++spec.cc
+++ b/gcc/cp/g++spec.cc
@@ -495,3 +495,6 @@ int lang_specific_pre_link (void)  /* Not used for C++.  */
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for C++.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = "c++";
diff --git a/gcc/d/d-spec.cc b/gcc/d/d-spec.cc
index 442bc1d8820..f88d1b84ea5 100644
--- a/gcc/d/d-spec.cc
+++ b/gcc/d/d-spec.cc
@@ -529,3 +529,5 @@ lang_specific_pre_link (void)
 
 int lang_specific_extra_outfiles = 0;  /* Not used for D.  */
 
+/* Language target for this driver */
+const char *lang_specific_language = "d";
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 87c0470c3db..09ab6270c2b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -39566,6 +39566,23 @@ intended to be passed to the LTO linker plugin.
 The @code{print-asm-header} function takes no arguments and simply
 prints a banner like:
 
+@item @code{if-driverlang}
+The @code{if-driverlang} spec function takes at least two arguments
+and an optional third one. The first argument is a language name as is
+used with @option{-x}. That is compared with the target language of
+the Compilation Driver, for example the target language for @file{gcc}
+is @samp{c} and the target language for @file{g++} is @samp{c++}. If
+they match, the function returns the second argument. If they do not
+match, the function returns the third argument if there is one, or
+NULL otherwise. This can be used to select general options or linker
+parameters based upon which Compilation Driver was invoked. Here is a
+small example of its usage:
+
+@smallexample
+*startfile:
+crt0%O%s %:if-driverlang(c++ crtbegin%O%s)
+@end smallexample
+
 @smallexample
 Assembler options
 =================
diff --git a/gcc/fortran/gfortranspec.cc b/gcc/fortran/gfortranspec.cc
index d0df0ee6171..bc206bb58a0 100644
--- a/gcc/fortran/gfortranspec.cc
+++ b/gcc/fortran/gfortranspec.cc
@@ -448,3 +448,6 @@ lang_specific_pre_link (void)
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for F77.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = "f77";
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 6b6f6f87c52..bc5c90880d5 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -463,6 +463,7 @@ static const char *debug_level_greater_than_spec_func (int, 
const char **);
 static const char *dwarf_version_greater_than_spec_func (int, const char **);
 static const char *find_fortran_preinclude_file (int, const char **);
 static const char *join_spec_func (int, const char **);
+static const char *if_driverlang_spec_function (int, const char **);
 static char *convert_white_space (char *);
 static char *quote_spec (char *);
 static char *quote_spec_arg (char *);
@@ -1825,6 +1826,7 @@ static const struct spec_function static_spec_functions[] 
=
   { "dwarf-version-gt",                dwarf_version_greater_than_spec_func },
   { "fortran-preinclude-file", find_fortran_preinclude_file},
   { "join",                    join_spec_func},
+  { "if-driverlang",            if_driverlang_spec_function },
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -11252,6 +11254,32 @@ join_spec_func (int argc, const char **argv)
   return XOBFINISH (&obstack, const char *);
 }
 
+/* if-driverlang built-in spec function.
+
+   Checks to see if the language-specific driver has specified a
+   language name that matches the first arg. Returns the second arg if
+   so, otherwise returns the third arg if it is present.  */
+
+static const char *
+if_driverlang_spec_function (int argc, const char **argv)
+{
+  const char *language;
+
+  /* Must have two or three arguments.  */
+  if (argc != 2 && argc != 3)
+    return NULL;
+
+  language = lang_specific_language;
+
+  if (language && !strcmp (argv[0], language))
+    return argv[1];
+
+  if (argc == 3)
+    return argv[2];
+
+  return NULL;
+}
+
 /* If any character in ORIG fits QUOTE_P (_, P), reallocate the string
    so as to precede every one of them with a backslash.  Return the
    original string or the reallocated one.  */
diff --git a/gcc/gcc.h b/gcc/gcc.h
index d2884314310..e5d9428e564 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -88,6 +88,9 @@ extern int n_infiles;
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 extern int lang_specific_extra_outfiles;
 
+/* The target language of the current driver, NULL if none */
+extern const char *lang_specific_language;
+
 /* A vector of corresponding output files is made up later.  */
 
 extern const char **outfiles;
diff --git a/gcc/go/gospec.cc b/gcc/go/gospec.cc
index 6e7d05197e8..0e5ec8e3b7f 100644
--- a/gcc/go/gospec.cc
+++ b/gcc/go/gospec.cc
@@ -463,3 +463,6 @@ int lang_specific_pre_link (void)  /* Not used for Go.  */
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for Go.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = "go";
diff --git a/gcc/jit/jit-spec.cc b/gcc/jit/jit-spec.cc
index 004195b8b74..e04e800d04d 100644
--- a/gcc/jit/jit-spec.cc
+++ b/gcc/jit/jit-spec.cc
@@ -39,3 +39,6 @@ lang_specific_pre_link (void)
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;  /* Not used for jit.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = NULL;
diff --git a/gcc/m2/gm2spec.cc b/gcc/m2/gm2spec.cc
index 755c60b1c88..e54c5e24158 100644
--- a/gcc/m2/gm2spec.cc
+++ b/gcc/m2/gm2spec.cc
@@ -966,3 +966,6 @@ lang_specific_pre_link (void)  /* Not used for M2.  */
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0;
+
+/* Language target for this driver */
+const char *lang_specific_language = "modula-2";
diff --git a/gcc/rust/rustspec.cc b/gcc/rust/rustspec.cc
index 509e2990df3..a18a82d7700 100644
--- a/gcc/rust/rustspec.cc
+++ b/gcc/rust/rustspec.cc
@@ -189,3 +189,6 @@ lang_specific_pre_link (void) /* Not used for Rust.  */
 
 /* Number of extra output files that lang_specific_pre_link may generate.  */
 int lang_specific_extra_outfiles = 0; /* Not used for Rust.  */
+
+/* Language target for this driver */
+const char *lang_specific_language = "rust";
-- 
2.51.0

Reply via email to