[PATCH] Modula-2 into the GCC tree on master
Gaius Mulley
gaiusmod2@gmail.com
Mon Jan 18 01:09:13 GMT 2021
Hello,
here is a patch which merges the gm2 front end into the GCC tree. The
patches have been boostrapped under x86_64 GNU/Linux Debian Stretch
built using make -j 24 and also under x86_64 GNU/Linux Debian Buster
using make -j 4.
Tested on Debian Stretch x86_64
===============================
built GCC bootstrap 3 times:
1. built vanilla GCC (enabling bootstrap) enabling front ends:
brig,c,c++,go,d,fortran and ran the regression tests.
2. the patches below were applied and associated tarball untarred.
The same front ends brig,c,c++,go,d,fortran (again building from
bootstrap) were enabled (no m2) and ran the regression tests.
There were no changes to the regression test results between 1 and
2.
3. Then it was rebuilt (from bootstrap) enabling the front ends
brig,c,c++,go,d,fortran,m2 and ran the
regression tests and again no extra failures were seen.
[should I also be testing ada?]
Built on Debian Buster x86_64
=============================
Built a patched tree enabling bootstrap make -j 4 for front ends c,c++,m2
all compiled and bootstrapped.
How to merge
============
1. apply patches below to the master GCC tree.
2. cd gcc-git-top
wget http://floppsie.comp.glam.ac.uk/download/c/gm2-front-end-20210116-tar.gz
tar zxf gm2-front-end-20210116-tar.gz
rm gm2-front-end-20210116-tar.gz
# new directories libgm2 and gcc/m2 are created and populated
3. cd gcc-git-top
autogen Makefile.def
autoconf
cd libgm2
/bin/sh ./autogen.sh
when built this implements iso, pim2, pim3 and pim4 editions of Modula-2
with access to GCC features (gcc/m2/gm2.texi).
hope this is useful - enjoy,
regards,
Gaius
2021-01-18 Gaius Mulley <gaiusmod2@gmail.com>
* configure.ac (GM2_FOR_TARGET): Added.
Request build driver program gm2.
(libgm2) option added.
(compare_exclusions) includes SYSTEM and M2Version.
* Makefile.def (GM2_FOR_TARGET): Added.
(GM2FLAGS_FOR_TARGET): Added. Assign GM2,
GM2_FOR_BUILD, GM2_FOR_TARGET and GM2FLAGS.
Pass variables to make. Add new language Modula-2
(m2). (target_modules) includes libgm2. (flags_to_pass)
includes GM2_FOR_TARGET and GM2FLAGS_FOR_TARGET.
* Makefile.tpl (GM2FLAGS): Added. (GM2) Added.
(GM2_FOR_BUILD) Added.
gcc/
* gcc/brig/brigspec.c (lang_register_spec_functions): Added.
* gcc/c-family/cppspec.c (lang_register_spec_functions): Added.
* gcc/c/gccspec.c (lang_register_spec_functions): Added.
* gcc/cp/g++spec.c (lang_register_spec_functions): Added.
* gcc/d/d-spec.cc (lang_register_spec_functions): Added.
* gcc/fortran/gfortranspec.c(lang_register_spec_functions): Added.
* gcc/gcc.c (allow_linker): Global variable to disable
linker by the front end. (xputenv) available externally.
(xgetenv) New function. (save_switch) available externally.
(fe_add_linker_option) New function. (handle_OPT_B) New function.
(fe_add_infile) New function. (fe_mark_compiled) New function.
(driver_handle_option) call handle_OPT_B. (print_option) New
function. (print_options) New function. (dbg_options) New function.
(fe_add_spec_function) New function. (lookup_spec_function)
checks front end registered functions.
(driver::set_up_specs): call lang_register_spec_functions.
(maybe_run_linker): Check allow_linker before running the linker.
* gcc/gcc.h (fe_save_switch): Prototype.
(handle_OPT_B) Prototype. (fe_add_infile) 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/go/gospec.c (lang_register_spec_functions): Added.
Patches
=======
diff --git a/Makefile.def b/Makefile.def
index 3e38f61193f..ef428b98f40 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -180,6 +180,7 @@ target_modules = { module= libffi; no_install=true; };
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; };
@@ -298,6 +299,8 @@ flags_to_pass = { flag= GOC_FOR_TARGET ; };
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 ; };
@@ -652,6 +655,7 @@ languages = { language=obj-c++; gcc-check-target=check-obj-c++; };
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;
diff --git a/Makefile.tpl b/Makefile.tpl
index 3b88f351d5b..fb1c3cfc47a 100644
--- a/Makefile.tpl
+++ b/Makefile.tpl
@@ -161,6 +161,7 @@ BUILD_EXPORTS = \
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 @@ HOST_EXPORTS = \
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 @@ BASE_TARGET_EXPORTS = \
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 @@ DLLTOOL_FOR_BUILD = @DLLTOOL_FOR_BUILD@
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 @@ CXXFLAGS = @CXXFLAGS@
LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates
GOCFLAGS = $(CFLAGS)
GDCFLAGS = $(CFLAGS)
+GM2FLAGS = $(CFLAGS)
CREATE_GCOV = create_gcov
@@ -518,6 +523,7 @@ RAW_CXX_FOR_TARGET=$(STAGE_CC_WRAPPER) @RAW_CXX_FOR_TARGET@
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 @@ EXTRA_HOST_FLAGS = \
'GFORTRAN=$(GFORTRAN)' \
'GOC=$(GOC)' \
'GDC=$(GDC)' \
+ 'GM2=$(GM2)' \
'LD=$(LD)' \
'LIPO=$(LIPO)' \
'NM=$(NM)' \
@@ -673,6 +680,7 @@ POSTSTAGE1_FLAGS_TO_PASS = \
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 @@ EXTRA_TARGET_FLAGS = \
'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)' \
@@ -733,6 +743,7 @@ TARGET_FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS)
# cross-building scheme.
EXTRA_GCC_FLAGS = \
"GCC_FOR_TARGET=$(GCC_FOR_TARGET)" \
+ "GM2_FOR_TARGET=$(GM2_FOR_TARGET)" \
"`echo 'STMP_FIXPROTO=$(STMP_FIXPROTO)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
"`echo 'LIMITS_H_TEST=$(LIMITS_H_TEST)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`"
diff --git a/configure.ac b/configure.ac
index 088e735c5db..917d5255997 100644
--- a/configure.ac
+++ b/configure.ac
@@ -163,6 +163,7 @@ target_libraries="target-libgcc \
target-libffi \
target-libobjc \
target-libada \
+ target-libgm2 \
target-libgo \
target-libphobos \
target-zlib"
@@ -452,6 +453,12 @@ if test "${ENABLE_LIBADA}" != "yes" ; then
noconfigdirs="$noconfigdirs gnattools"
fi
+AC_ARG_ENABLE(libgm2,
+[AS_HELP_STRING([--enable-libgm2], [build libgm2 directory])],
+ENABLE_LIBGM2=$enableval,
+ENABLE_LIBGM2=yes)
+
+
AC_ARG_ENABLE(libssp,
[AS_HELP_STRING([--enable-libssp], [build libssp directory])],
ENABLE_LIBSSP=$enableval,
@@ -3504,6 +3511,7 @@ NCN_STRICT_CHECK_TARGET_TOOLS(GCC_FOR_TARGET, gcc, ${CC_FOR_TARGET})
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)
@@ -3540,6 +3548,8 @@ GCC_TARGET_TOOL(gccgo, GOC_FOR_TARGET, GOC,
[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/gm2 -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])
@@ -3666,6 +3676,8 @@ AC_SUBST(stage2_werror_flag)
# Specify what files to not compare during bootstrap.
compare_exclusions="gcc/cc*-checksum\$(objext) | gcc/ada/*tools/*"
+compare_exclusions="$compare_exclusions | *m2/*/M2Version*\$(objext)"
+compare_exclusions="$compare_exclusions | *m2/*/SYSTEM*\$(objext)"
case "$target" in
hppa*64*-*-hpux*) ;;
hppa*-*-hpux*) compare_exclusions="$compare_exclusions | */libgcc/lib2funcs* | gcc/function-tests.o" ;;
diff --git a/gcc/brig/brigspec.c b/gcc/brig/brigspec.c
index cbbc8ea076d..e10a1fb3023 100644
--- a/gcc/brig/brigspec.c
+++ b/gcc/brig/brigspec.c
@@ -134,3 +134,11 @@ int lang_specific_pre_link (void) /* Not used for Brig. */ { return 0; }
/* 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)
+{
+}
diff --git a/gcc/c-family/cppspec.c b/gcc/c-family/cppspec.c
index 65902b9f0d5..7a1f8d10a21 100644
--- a/gcc/c-family/cppspec.c
+++ b/gcc/c-family/cppspec.c
@@ -198,3 +198,9 @@ 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. */
+
+/* lang_register_spec_functions. Not used for cpp. */
+void
+lang_register_spec_functions (void)
+{
+}
diff --git a/gcc/c/gccspec.c b/gcc/c/gccspec.c
index db353a35585..67af876eb99 100644
--- a/gcc/c/gccspec.c
+++ b/gcc/c/gccspec.c
@@ -105,3 +105,9 @@ 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. */
+
+/* lang_register_spec_functions. Not used for C. */
+void
+lang_register_spec_functions (void)
+{
+}
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index 3c9bd1490b4..88a302c2157 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -434,3 +434,9 @@ 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++. */
+
+/* lang_register_spec_functions. Not used for C++. */
+void
+lang_register_spec_functions (void)
+{
+}
diff --git a/gcc/d/d-spec.cc b/gcc/d/d-spec.cc
index 16ff1539e9f..e2fb787f5e1 100644
--- a/gcc/d/d-spec.cc
+++ b/gcc/d/d-spec.cc
@@ -490,3 +490,10 @@ lang_specific_pre_link (void)
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)
+{
+}
diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c
index 97db139deea..4c6045b9f06 100644
--- a/gcc/fortran/gfortranspec.c
+++ b/gcc/fortran/gfortranspec.c
@@ -447,4 +447,12 @@ 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. */
+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)
+{
+}
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 7dccfadfef2..27ef1f1bf07 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -328,6 +328,10 @@ static const char *cross_compile = "1";
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;
@@ -356,7 +360,6 @@ static void set_spec (const char *, const char *, bool);
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);
@@ -1775,6 +1779,10 @@ static const struct spec_function static_spec_functions[] =
{ 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
@@ -2937,12 +2945,20 @@ add_to_obstack (char *path, void *data)
/* 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.
@@ -3871,7 +3887,7 @@ alloc_switch (void)
/* 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)
{
@@ -3916,6 +3932,66 @@ set_source_date_epoch_envvar ()
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);
+}
+
+/* Save the infile. */
+
+void
+fe_add_infile (const char *infile, const char *lang)
+{
+ add_infile (infile, lang);
+}
+
+/* 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. */
@@ -4417,33 +4493,7 @@ driver_handle_option (struct gcc_options *opts,
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;
@@ -4566,6 +4616,68 @@ single_input_file_index ()
return ret;
}
+/* 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'. */
@@ -6752,6 +6864,33 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
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 *
@@ -6763,6 +6902,11 @@ lookup_spec_function (const char *name)
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;
}
@@ -8249,6 +8393,8 @@ driver::set_up_specs () const
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"))
@@ -8979,7 +9125,8 @@ driver::maybe_run_linker (const char *argv0) const
/* 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;
@@ -9048,7 +9195,7 @@ driver::maybe_run_linker (const char *argv0) const
/* 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] == '*'))
diff --git a/gcc/gcc.h b/gcc/gcc.h
index 244edbc26c6..217352fef73 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -73,9 +73,28 @@ struct spec_function
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_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 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 +116,8 @@ driver_get_configure_time_options (void (*cb)(const char *option,
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 */
diff --git a/gcc/go/gospec.c b/gcc/go/gospec.c
index aaf64e73949..3a4f50e2fc9 100644
--- a/gcc/go/gospec.c
+++ b/gcc/go/gospec.c
@@ -440,3 +440,9 @@ 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. */
+
+/* lang_register_spec_functions. Not used for Go. */
+void
+lang_register_spec_functions (void)
+{
+}
More information about the Gcc-patches
mailing list