diff options
Diffstat (limited to 'gcc/lto-wrapper.c')
-rw-r--r-- | gcc/lto-wrapper.c | 326 |
1 files changed, 199 insertions, 127 deletions
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 46a88b2..82cfa6b 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -53,6 +53,13 @@ along with GCC; see the file COPYING3. If not see driver to lto-wrapper. */ #define OFFLOAD_TARGET_NAMES_ENV "OFFLOAD_TARGET_NAMES" +/* By default there is no special suffix for target executables. */ +#ifdef TARGET_EXECUTABLE_SUFFIX +#define HAVE_TARGET_EXECUTABLE_SUFFIX +#else +#define TARGET_EXECUTABLE_SUFFIX "" +#endif + enum lto_mode_d { LTO_MODE_NONE, /* Not doing LTO. */ LTO_MODE_LTO, /* Normal LTO. */ @@ -126,7 +133,7 @@ maybe_unlink (const char *file) } /* Template of LTRANS dumpbase suffix. */ -#define DUMPBASE_SUFFIX ".ltrans18446744073709551615" +#define DUMPBASE_SUFFIX "ltrans18446744073709551615" /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS environment. */ @@ -192,11 +199,14 @@ static void merge_and_complain (struct cl_decoded_option **decoded_options, unsigned int *decoded_options_count, struct cl_decoded_option *fdecoded_options, - unsigned int fdecoded_options_count) + unsigned int fdecoded_options_count, + struct cl_decoded_option *decoded_cl_options, + unsigned int decoded_cl_options_count) { unsigned int i, j; struct cl_decoded_option *pic_option = NULL; struct cl_decoded_option *pie_option = NULL; + struct cl_decoded_option *cf_protection_option = NULL; /* ??? Merge options from files. Most cases can be handled by either unioning or intersecting @@ -211,6 +221,17 @@ merge_and_complain (struct cl_decoded_option **decoded_options, In absence of that it's unclear what a good default is. It's also difficult to get positional handling correct. */ + /* Look for a -fcf-protection option in the link-time options + which overrides any -fcf-protection from the lto sections. */ + for (i = 0; i < decoded_cl_options_count; ++i) + { + struct cl_decoded_option *foption = &decoded_cl_options[i]; + if (foption->opt_index == OPT_fcf_protection_) + { + cf_protection_option = foption; + } + } + /* The following does what the old LTO option code did, union all target and a selected set of common options. */ for (i = 0; i < fdecoded_options_count; ++i) @@ -287,6 +308,48 @@ merge_and_complain (struct cl_decoded_option **decoded_options, foption->orig_option_with_args_text); break; + case OPT_fcf_protection_: + /* Default to link-time option, else append or check identical. */ + if (!cf_protection_option + || cf_protection_option->value == CF_CHECK) + { + for (j = 0; j < *decoded_options_count; ++j) + if ((*decoded_options)[j].opt_index == foption->opt_index) + break; + if (j == *decoded_options_count) + append_option (decoded_options, decoded_options_count, foption); + else if ((*decoded_options)[j].value != foption->value) + { + if (cf_protection_option + && cf_protection_option->value == CF_CHECK) + fatal_error (input_location, + "option -fcf-protection with mismatching values" + " (%s, %s)", + (*decoded_options)[j].arg, foption->arg); + else + { + /* Merge and update the -fcf-protection option. */ + (*decoded_options)[j].value &= (foption->value + & CF_FULL); + switch ((*decoded_options)[j].value) + { + case CF_NONE: + (*decoded_options)[j].arg = "none"; + break; + case CF_BRANCH: + (*decoded_options)[j].arg = "branch"; + break; + case CF_RETURN: + (*decoded_options)[j].arg = "return"; + break; + default: + gcc_unreachable (); + } + } + } + } + break; + case OPT_O: case OPT_Ofast: case OPT_Og: @@ -501,24 +564,24 @@ merge_and_complain (struct cl_decoded_option **decoded_options, break; else if (i < *decoded_options_count && j == fdecoded_options_count) { - warning (0, "Extra option to -Xassembler: %s," - " dropping all -Xassembler and -Wa options.", + warning (0, "Extra option to %<-Xassembler%>: %s," + " dropping all %<-Xassembler%> and %<-Wa%> options.", (*decoded_options)[i].arg); xassembler_options_error = true; break; } else if (i == *decoded_options_count && j < fdecoded_options_count) { - warning (0, "Extra option to -Xassembler: %s," - " dropping all -Xassembler and -Wa options.", + warning (0, "Extra option to %<-Xassembler%>: %s," + " dropping all %<-Xassembler%> and %<-Wa%> options.", fdecoded_options[j].arg); xassembler_options_error = true; break; } else if (strcmp ((*decoded_options)[i].arg, fdecoded_options[j].arg)) { - warning (0, "Options to Xassembler do not match: %s, %s," - " dropping all -Xassembler and -Wa options.", + warning (0, "Options to %<-Xassembler%> do not match: %s, %s," + " dropping all %<-Xassembler%> and %<-Wa%> options.", (*decoded_options)[i].arg, fdecoded_options[j].arg); xassembler_options_error = true; break; @@ -631,6 +694,7 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts, case OPT_fopenacc: case OPT_fopenacc_dim_: case OPT_foffload_abi_: + case OPT_fcf_protection_: case OPT_g: case OPT_O: case OPT_Ofast: @@ -823,6 +887,7 @@ compile_offload_image (const char *target, const char *compiler_path, unsigned int linker_opt_count) { char *filename = NULL; + char *dumpbase; char **argv; char *suffix = XALLOCAVEC (char, sizeof ("/accel//mkoffload") + strlen (target)); @@ -846,8 +911,13 @@ compile_offload_image (const char *target, const char *compiler_path, "could not find %s in %s (consider using %<-B%>)", suffix + 1, compiler_path); + dumpbase = concat (dumppfx, "x", target, NULL); + /* Generate temporary output file name. */ - filename = make_temp_file (".target.o"); + if (save_temps) + filename = concat (dumpbase, ".o", NULL); + else + filename = make_temp_file (".target.o"); struct obstack argv_obstack; obstack_init (&argv_obstack); @@ -868,6 +938,9 @@ compile_offload_image (const char *target, const char *compiler_path, compiler_opt_count); append_diag_options (&argv_obstack, linker_opts, linker_opt_count); + obstack_ptr_grow (&argv_obstack, "-dumpbase"); + obstack_ptr_grow (&argv_obstack, dumpbase); + /* Append options specified by -foffload last. In case of conflicting options we expect offload compiler to choose the latest. */ append_offload_options (&argv_obstack, target, compiler_opts, @@ -903,7 +976,6 @@ compile_images_for_offload_targets (unsigned in_argc, char *in_argv[], return; unsigned num_targets = parse_env_var (target_names, &names, NULL); - int next_name_entry = 0; const char *compiler_path = getenv ("COMPILER_PATH"); if (!compiler_path) goto out; @@ -913,19 +985,13 @@ compile_images_for_offload_targets (unsigned in_argc, char *in_argv[], offload_names = XCNEWVEC (char *, num_targets + 1); for (unsigned i = 0; i < num_targets; i++) { - /* HSA does not use LTO-like streaming and a different compiler, skip - it. */ - if (strcmp (names[i], "hsa") == 0) - continue; - - offload_names[next_name_entry] + offload_names[i] = compile_offload_image (names[i], compiler_path, in_argc, in_argv, compiler_opts, compiler_opt_count, linker_opts, linker_opt_count); - if (!offload_names[next_name_entry]) + if (!offload_names[i]) fatal_error (input_location, "problem with building target image for %s", names[i]); - next_name_entry++; } out: @@ -988,12 +1054,14 @@ find_crtoffloadtable (void) /* A subroutine of run_gcc. Examine the open file FD for lto sections with name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS - and OPT_COUNT. Return true if we found a matchingn section, false + and OPT_COUNT. Return true if we found a matching section, false otherwise. COLLECT_GCC holds the value of the environment variable with the same name. */ static bool find_and_merge_options (int fd, off_t file_offset, const char *prefix, + struct cl_decoded_option *decoded_cl_options, + unsigned int decoded_cl_options_count, struct cl_decoded_option **opts, unsigned int *opt_count, const char *collect_gcc) { @@ -1040,7 +1108,9 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix, else merge_and_complain (&fdecoded_options, &fdecoded_options_count, - f2decoded_options, f2decoded_options_count); + f2decoded_options, f2decoded_options_count, + decoded_cl_options, + decoded_cl_options_count); fopts += strlen (fopts) + 1; } @@ -1100,12 +1170,7 @@ debug_objcopy (const char *infile, bool rename) } if (save_temps) - { - outfile = (char *) xmalloc (strlen (orig_infile) - + sizeof (".debug.temp.o") + 1); - strcpy (outfile, orig_infile); - strcat (outfile, ".debug.temp.o"); - } + outfile = concat (orig_infile, ".debug.temp.o", NULL); else outfile = make_temp_file (".debug.temp.o"); errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err, rename); @@ -1236,28 +1301,33 @@ init_num_threads (void) /* FIXME: once using -std=c++11, we can use std::thread::hardware_concurrency. */ -/* Return true when a jobserver is running and can accept a job. */ +/* Test and return reason why a jobserver cannot be detected. */ -static bool +static const char * jobserver_active_p (void) { + #define JS_PREFIX "jobserver is not available: " + #define JS_NEEDLE "--jobserver-auth=" + const char *makeflags = getenv ("MAKEFLAGS"); if (makeflags == NULL) - return false; + return JS_PREFIX "%<MAKEFLAGS%> environment variable is unset"; - const char *needle = "--jobserver-auth="; - const char *n = strstr (makeflags, needle); + const char *n = strstr (makeflags, JS_NEEDLE); if (n == NULL) - return false; + return JS_PREFIX "%<" JS_NEEDLE "%> is not present in %<MAKEFLAGS%>"; int rfd = -1; int wfd = -1; - return (sscanf (n + strlen (needle), "%d,%d", &rfd, &wfd) == 2 - && rfd > 0 - && wfd > 0 - && is_valid_fd (rfd) - && is_valid_fd (wfd)); + if (sscanf (n + strlen (JS_NEEDLE), "%d,%d", &rfd, &wfd) == 2 + && rfd > 0 + && wfd > 0 + && is_valid_fd (rfd) + && is_valid_fd (wfd)) + return NULL; + else + return JS_PREFIX "cannot access %<" JS_NEEDLE "%> file descriptors"; } /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */ @@ -1291,6 +1361,8 @@ run_gcc (unsigned argc, char *argv[]) bool linker_output_rel = false; bool skip_debug = false; unsigned n_debugobj; + const char *incoming_dumppfx = dumppfx = NULL; + static char current_dir[] = { '.', DIR_SEPARATOR, '\0' }; /* Get the driver and options. */ collect_gcc = getenv ("COLLECT_GCC"); @@ -1373,6 +1445,7 @@ run_gcc (unsigned argc, char *argv[]) } if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX, + decoded_options, decoded_options_count, &fdecoded_options, &fdecoded_options_count, collect_gcc)) { @@ -1402,6 +1475,10 @@ run_gcc (unsigned argc, char *argv[]) linker_output = option->arg; break; + /* We don't have to distinguish between -save-temps=* and + -save-temps, -dumpdir already carries that + information. */ + case OPT_save_temps_: case OPT_save_temps: save_temps = 1; break; @@ -1447,6 +1524,10 @@ run_gcc (unsigned argc, char *argv[]) skip_debug = option->arg && !strcmp (option->arg, "0"); break; + case OPT_dumpdir: + incoming_dumppfx = dumppfx = option->arg; + break; + default: break; } @@ -1473,38 +1554,59 @@ run_gcc (unsigned argc, char *argv[]) auto_parallel = 0; parallel = 0; } - else if (!jobserver && jobserver_active_p ()) + else { - parallel = 1; - jobserver = 1; + const char *jobserver_error = jobserver_active_p (); + if (jobserver && jobserver_error != NULL) + warning (0, jobserver_error); + else if (!jobserver && jobserver_error == NULL) + { + parallel = 1; + jobserver = 1; + } } - if (linker_output) + if (!dumppfx) { - char *output_dir, *base, *name; - bool bit_bucket = strcmp (linker_output, HOST_BIT_BUCKET) == 0; - - output_dir = xstrdup (linker_output); - base = output_dir; - for (name = base; *name; name++) - if (IS_DIR_SEPARATOR (*name)) - base = name + 1; - *base = '\0'; - - linker_output = &linker_output[base - output_dir]; - if (*output_dir == '\0') - { - static char current_dir[] = { '.', DIR_SEPARATOR, '\0' }; - output_dir = current_dir; - } - if (!bit_bucket) + if (!linker_output + || strcmp (linker_output, HOST_BIT_BUCKET) == 0) + dumppfx = "a."; + else { - obstack_ptr_grow (&argv_obstack, "-dumpdir"); - obstack_ptr_grow (&argv_obstack, output_dir); + const char *obase = lbasename (linker_output), *temp; + + /* Strip the executable extension. */ + size_t blen = strlen (obase), xlen; + if ((temp = strrchr (obase + 1, '.')) + && (xlen = strlen (temp)) + && (strcmp (temp, ".exe") == 0 +#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) + || strcmp (temp, TARGET_EXECUTABLE_SUFFIX) == 0 +#endif + || strcmp (obase, "a.out") == 0)) + dumppfx = xstrndup (linker_output, + obase - linker_output + blen - xlen + 1); + else + dumppfx = concat (linker_output, ".", NULL); } + } - obstack_ptr_grow (&argv_obstack, "-dumpbase"); + /* If there's no directory component in the dumppfx, add one, so + that, when it is used as -dumpbase, it overrides any occurrence + of -dumpdir that might have been passed in. */ + if (!dumppfx || lbasename (dumppfx) == dumppfx) + dumppfx = concat (current_dir, dumppfx, NULL); + + /* Make sure some -dumpdir is passed, so as to get predictable + -dumpbase overriding semantics. If we got an incoming -dumpdir + argument, we'll pass it on, so don't bother with another one + then. */ + if (!incoming_dumppfx) + { + obstack_ptr_grow (&argv_obstack, "-dumpdir"); + obstack_ptr_grow (&argv_obstack, ""); } + obstack_ptr_grow (&argv_obstack, "-dumpbase"); /* Remember at which point we can scrub args to re-use the commons. */ new_head_argc = obstack_object_size (&argv_obstack) / sizeof (void *); @@ -1576,6 +1678,7 @@ cont1: fatal_error (input_location, "cannot open %s: %m", filename); if (!find_and_merge_options (fd, file_offset, OFFLOAD_SECTION_NAME_PREFIX, + decoded_options, decoded_options_count, &offload_fdecoded_options, &offload_fdecoded_options_count, collect_gcc)) @@ -1610,15 +1713,11 @@ cont1: if (lto_mode == LTO_MODE_LTO) { - if (linker_output) - { - obstack_ptr_grow (&argv_obstack, linker_output); - flto_out = (char *) xmalloc (strlen (linker_output) - + sizeof (".lto.o") + 1); - strcpy (flto_out, linker_output); - strcat (flto_out, ".lto.o"); - } - else + /* -dumpbase argument for LTO. */ + flto_out = concat (dumppfx, "lto.o", NULL); + obstack_ptr_grow (&argv_obstack, flto_out); + + if (!save_temps) flto_out = make_temp_file (".lto.o"); obstack_ptr_grow (&argv_obstack, "-o"); obstack_ptr_grow (&argv_obstack, flto_out); @@ -1626,47 +1725,17 @@ cont1: else { const char *list_option = "-fltrans-output-list="; - size_t list_option_len = strlen (list_option); - char *tmp; - if (linker_output) - { - char *dumpbase = (char *) xmalloc (strlen (linker_output) - + sizeof (".wpa") + 1); - strcpy (dumpbase, linker_output); - strcat (dumpbase, ".wpa"); - obstack_ptr_grow (&argv_obstack, dumpbase); - } + /* -dumpbase argument for WPA. */ + char *dumpbase = concat (dumppfx, "wpa", NULL); + obstack_ptr_grow (&argv_obstack, dumpbase); - if (linker_output && save_temps) - { - ltrans_output_file = (char *) xmalloc (strlen (linker_output) - + sizeof (".ltrans.out") + 1); - strcpy (ltrans_output_file, linker_output); - strcat (ltrans_output_file, ".ltrans.out"); - } + if (save_temps) + ltrans_output_file = concat (dumppfx, "ltrans.out", NULL); else - { - char *prefix = NULL; - if (linker_output) - { - prefix = (char *) xmalloc (strlen (linker_output) + 2); - strcpy (prefix, linker_output); - strcat (prefix, "."); - } - - ltrans_output_file = make_temp_file_with_prefix (prefix, - ".ltrans.out"); - free (prefix); - } - list_option_full = (char *) xmalloc (sizeof (char) * - (strlen (ltrans_output_file) + list_option_len + 1)); - tmp = list_option_full; - - obstack_ptr_grow (&argv_obstack, tmp); - strcpy (tmp, list_option); - tmp += list_option_len; - strcpy (tmp, ltrans_output_file); + ltrans_output_file = make_temp_file (".ltrans.out"); + list_option_full = concat (list_option, ltrans_output_file, NULL); + obstack_ptr_grow (&argv_obstack, list_option_full); if (jobserver) { @@ -1822,16 +1891,10 @@ cont: output_name = XOBFINISH (&env_obstack, char *); /* Adjust the dumpbase if the linker output file was seen. */ - if (linker_output) - { - char *dumpbase - = (char *) xmalloc (strlen (linker_output) - + sizeof (DUMPBASE_SUFFIX) + 1); - snprintf (dumpbase, - strlen (linker_output) + sizeof (DUMPBASE_SUFFIX), - "%s.ltrans%u", linker_output, i); - argv_ptr[0] = dumpbase; - } + int dumpbase_len = (strlen (dumppfx) + sizeof (DUMPBASE_SUFFIX)); + char *dumpbase = (char *) xmalloc (dumpbase_len + 1); + snprintf (dumpbase, dumpbase_len, "%sltrans%u.ltrans", dumppfx, i); + argv_ptr[0] = dumpbase; argv_ptr[1] = "-fltrans"; argv_ptr[2] = "-o"; @@ -1883,23 +1946,32 @@ cont: putenv (xstrdup ("MAKEFLAGS=")); putenv (xstrdup ("MFLAGS=")); } - new_argv[0] = getenv ("MAKE"); - if (!new_argv[0]) - new_argv[0] = "make"; - new_argv[1] = "-f"; - new_argv[2] = makefile; - i = 3; + + char **make_argv = buildargv (getenv ("MAKE")); + if (make_argv) + { + for (unsigned argc = 0; make_argv[argc]; argc++) + obstack_ptr_grow (&argv_obstack, make_argv[argc]); + } + else + obstack_ptr_grow (&argv_obstack, "make"); + + obstack_ptr_grow (&argv_obstack, "-f"); + obstack_ptr_grow (&argv_obstack, makefile); if (!jobserver) { snprintf (jobs, 31, "-j%ld", auto_parallel ? nthreads_var : parallel); - new_argv[i++] = jobs; + obstack_ptr_grow (&argv_obstack, jobs); } - new_argv[i++] = "all"; - new_argv[i++] = NULL; + obstack_ptr_grow (&argv_obstack, "all"); + obstack_ptr_grow (&argv_obstack, NULL); + new_argv = XOBFINISH (&argv_obstack, const char **); + pex = collect_execute (new_argv[0], CONST_CAST (char **, new_argv), NULL, NULL, PEX_SEARCH, false); do_wait (new_argv[0], pex); + freeargv (make_argv); maybe_unlink (makefile); makefile = NULL; for (i = 0; i < nr; ++i) |