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 <gaiusm...@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) +{ +}