diff options
Diffstat (limited to 'gcc/gcc.c')
-rw-r--r-- | gcc/gcc.c | 144 |
1 files changed, 109 insertions, 35 deletions
diff --git a/gcc/gcc.c b/gcc/gcc.c index a9ed7e21696..6bc8e150a67 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -684,9 +684,15 @@ proper position among the other output files. */ #endif /* config.h can define SWITCHES_NEED_SPACES to control which options - require spaces between the option and the argument. */ + require spaces between the option and the argument. + + We define SWITCHES_NEED_SPACES to include "o" by default. This + causes "-ofoo.o" to be split into "-o foo.o" during the initial + processing of the command-line, before being seen by the specs + machinery. This makes sure we record "foo.o" as the temporary file + to be deleted in the case of error, rather than "-ofoo.o". */ #ifndef SWITCHES_NEED_SPACES -#define SWITCHES_NEED_SPACES "" +#define SWITCHES_NEED_SPACES "o" #endif /* config.h can define ENDFILE_SPEC to override the default crtn files. */ @@ -764,10 +770,24 @@ proper position among the other output files. */ /* We want %{T*} after %{L*} and %D so that it can be used to specify linker scripts which exist in user specified directories, or in standard directories. */ +/* We pass any -flto and -fwhopr flags on to the linker, which is expected + to understand them. In practice, this means it had better be collect2. */ #ifndef LINK_COMMAND_SPEC #define LINK_COMMAND_SPEC "\ %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ - %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ + %(linker) \ + %{fuse-linker-plugin: \ + -plugin %(linker_plugin_file) \ + -plugin-opt=%(lto_wrapper) \ + -plugin-opt=%(lto_gcc) \ + %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \ + %{static:-plugin-opt=-pass-through=-lc} \ + %{O*:-plugin-opt=-O%*} \ + %{w:-plugin-opt=-w} \ + %{f*:-plugin-opt=-f%*} \ + } \ + %{flto} %{fwhopr} %l " LINK_PIE_SPEC \ + "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\ @@ -815,6 +835,10 @@ static const char *endfile_spec = ENDFILE_SPEC; static const char *startfile_spec = STARTFILE_SPEC; static const char *switches_need_spaces = SWITCHES_NEED_SPACES; static const char *linker_name_spec = LINKER_NAME; +static const char *linker_plugin_file_spec = ""; +static const char *lto_wrapper_spec = ""; +static const char *lto_gcc_spec = ""; +static const char *lto_libgcc_spec = ""; static const char *link_command_spec = LINK_COMMAND_SPEC; static const char *link_libgcc_spec = LINK_LIBGCC_SPEC; static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC; @@ -891,11 +915,15 @@ static const char *asm_options = static const char *invoke_as = #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT -"%{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\ - %{!S:-o %|.s |\n as %(asm_options) %|.s %A }"; +"%{!fwpa:\ + %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\ + %{!S:-o %|.s |\n as %(asm_options) %|.s %A }\ + }"; #else -"%{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\ - %{!S:-o %|.s |\n as %(asm_options) %m.s %A }"; +"%{!fwpa:\ + %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\ + %{!S:-o %|.s |\n as %(asm_options) %m.s %A }\ + }"; #endif /* Some compilers have limits on line lengths, and the multilib_select @@ -962,7 +990,7 @@ static struct user_specs *user_specs_head, *user_specs_tail; #ifdef HAVE_TARGET_EXECUTABLE_SUFFIX /* This defines which switches stop a full compilation. */ #define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \ - ((CHAR) == 'c' || (CHAR) == 'S') + ((CHAR) == 'c' || (CHAR) == 'S' || (CHAR) == 'E') #ifndef SWITCH_CURTAILS_COMPILATION #define SWITCH_CURTAILS_COMPILATION(CHAR) \ @@ -1653,6 +1681,10 @@ static struct spec_list static_specs[] = INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), INIT_STATIC_SPEC ("multilib_options", &multilib_options), INIT_STATIC_SPEC ("linker", &linker_name_spec), + INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec), + INIT_STATIC_SPEC ("lto_wrapper", <o_wrapper_spec), + INIT_STATIC_SPEC ("lto_gcc", <o_gcc_spec), + INIT_STATIC_SPEC ("lto_libgcc", <o_libgcc_spec), INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix), @@ -1974,7 +2006,7 @@ static int argbuf_index; static int have_o_argbuf_index = 0; -/* Were the options -c or -S passed. */ +/* Were the options -c, -S or -E passed. */ static int have_c = 0; /* Was the option -o passed. */ @@ -4116,6 +4148,7 @@ process_command (int argc, const char **argv) case 'S': case 'c': + case 'E': if (p[1] == 0) { have_c = 1; @@ -4131,7 +4164,7 @@ process_command (int argc, const char **argv) { int skip; - /* Forward scan, just in case -S or -c is specified + /* Forward scan, just in case -S, -E or -c is specified after -o. */ int j = i + 1; if (p[1] == 0) @@ -4162,7 +4195,10 @@ process_command (int argc, const char **argv) argv[i] = convert_filename (argv[i], ! have_c, 0); #endif /* Save the output name in case -save-temps=obj was used. */ - save_temps_prefix = xstrdup ((p[1] == 0) ? argv[i + 1] : argv[i] + 1); + if ((p[1] == 0) && argv[i + 1]) + save_temps_prefix = xstrdup(argv[i + 1]); + else + save_temps_prefix = xstrdup(argv[i] + 1); goto normal_switch; default: @@ -4532,20 +4568,32 @@ process_command (int argc, const char **argv) } else { + const char *p = strchr (argv[i], '@'); + char *fname; #ifdef HAVE_TARGET_OBJECT_SUFFIX argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK)); #endif + if (!p) + fname = xstrdup (argv[i]); + else + { + fname = (char *)xmalloc (p - argv[i] + 1); + memcpy (fname, argv[i], p - argv[i]); + fname[p - argv[i]] = '\0'; + } + + if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0) + { + perror_with_name (fname); + error_count++; + } + else + { + infiles[n_infiles].language = spec_lang; + infiles[n_infiles++].name = argv[i]; + } - if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0) - { - perror_with_name (argv[i]); - error_count++; - } - else - { - infiles[n_infiles].language = spec_lang; - infiles[n_infiles++].name = argv[i]; - } + free (fname); } } @@ -4608,11 +4656,6 @@ set_collect_gcc_options (void) if ((switches[i].live_cond & SWITCH_IGNORE) != 0) continue; - /* Don't use -fwhole-program when compiling the init and fini routines, - since we'd wrongly assume that the routines aren't needed. */ - if (strcmp (switches[i].part1, "fwhole-program") == 0) - continue; - obstack_grow (&collect_obstack, "'-", 2); q = switches[i].part1; while ((p = strchr (q, '\''))) @@ -6834,14 +6877,6 @@ main (int argc, char **argv) multilib_defaults = XOBFINISH (&multilib_obstack, const char *); } - /* Set up to remember the pathname of gcc and any options - needed for collect. We use argv[0] instead of programname because - we need the complete pathname. */ - obstack_init (&collect_obstack); - obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); - obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); - xputenv (XOBFINISH (&collect_obstack, char *)); - #ifdef INIT_ENVIRONMENT /* Set up any other necessary machine specific environment variables. */ xputenv (INIT_ENVIRONMENT); @@ -7055,6 +7090,27 @@ main (int argc, char **argv) the subdirectory based on the options. */ set_multilib_dir (); + /* Set up to remember the pathname of gcc and any options + needed for collect. We use argv[0] instead of programname because + we need the complete pathname. */ + obstack_init (&collect_obstack); + obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); + obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); + xputenv (XOBFINISH (&collect_obstack, char *)); + + /* Set up to remember the pathname of the lto wrapper. */ + + lto_wrapper_spec = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false); + if (lto_wrapper_spec) + { + obstack_init (&collect_obstack); + obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=", + sizeof ("COLLECT_LTO_WRAPPER=") - 1); + obstack_grow (&collect_obstack, lto_wrapper_spec, + strlen (lto_wrapper_spec) + 1); + xputenv (XOBFINISH (&collect_obstack, char *)); + } + /* Warn about any switches that no pass was interested in. */ for (i = 0; (int) i < n_switches; i++) @@ -7267,7 +7323,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" } if (!combine_inputs && have_c && have_o && lang_n_infiles > 1) - fatal ("cannot specify -o with -c or -S with multiple files"); + fatal ("cannot specify -o with -c, -S or -E with multiple files"); if (combine_flag && save_temps_flag) { @@ -7475,6 +7531,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (num_linker_inputs > 0 && error_count == 0 && print_subprocess_help < 2) { int tmp = execution_count; + const char *fuse_linker_plugin = "fuse-linker-plugin"; /* We'll use ld if we can't find collect2. */ if (! strcmp (linker_name_spec, "collect2")) @@ -7483,6 +7540,23 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (s == NULL) linker_name_spec = "ld"; } + + if (switch_matches (fuse_linker_plugin, + fuse_linker_plugin + strlen (fuse_linker_plugin), 0)) + { + linker_plugin_file_spec = find_a_file (&exec_prefixes, + "liblto_plugin.so", X_OK, + false); + if (!linker_plugin_file_spec) + fatal ("-fuse-linker-plugin, but liblto_plugin.so not found"); + + lto_libgcc_spec = find_a_file (&startfile_prefixes, "libgcc.a", + R_OK, true); + if (!lto_libgcc_spec) + fatal ("could not find libgcc.a"); + } + lto_gcc_spec = argv[0]; + /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables for collect. */ putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false); |