diff options
Diffstat (limited to 'gcc/gcc.c')
-rw-r--r-- | gcc/gcc.c | 194 |
1 files changed, 149 insertions, 45 deletions
@@ -319,6 +319,12 @@ static const char *spec_host_machine = DEFAULT_REAL_TARGET_MACHINE; static char *offload_targets = NULL; +#if OFFLOAD_DEFAULTED +/* Set to true if -foffload has not been used and offload_targets + is set to the configured in default. */ +static bool offload_targets_default; +#endif + /* Nonzero if cross-compiling. When -b is used, the value comes from the `specs' file. */ @@ -910,7 +916,7 @@ proper position among the other output files. */ than in ASM_DEBUG_SPEC, so that it applies to both .s and .c etc. compilations. */ # define ASM_DEBUG_DWARF_OPTION "" -# elif defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) +# elif defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) && !defined(HAVE_LD_BROKEN_PE_DWARF5) # define ASM_DEBUG_DWARF_OPTION "%{%:dwarf-version-gt(4):--gdwarf-5;" \ "%:dwarf-version-gt(3):--gdwarf-4;" \ "%:dwarf-version-gt(2):--gdwarf-3;" \ @@ -1900,7 +1906,7 @@ init_spec (void) when given the proper command line arguments. */ while (*p) { - if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0) + if (in_sep && *p == '-' && startswith (p, "-lgcc")) { init_gcc_specs (&obstack, "-lgcc_s" @@ -1923,7 +1929,7 @@ init_spec (void) p += 5; in_sep = 0; } - else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0) + else if (in_sep && *p == 'l' && startswith (p, "libgcc.a%s")) { /* Ug. We don't know shared library extensions. Hope that systems that use this form don't do shared libraries. */ @@ -2236,7 +2242,7 @@ close_at_file (void) if (n_args == 0) return; - char **argv = (char **) alloca (sizeof (char *) * (n_args + 1)); + char **argv = XALLOCAVEC (char *, n_args + 1); char *temp_file = make_at_file (); char *at_argument = concat ("@", temp_file, NULL); FILE *f = fopen (temp_file, "w"); @@ -2378,7 +2384,7 @@ read_specs (const char *filename, bool main_p, bool user_p) /* Skip '\n'. */ p++; - if (!strncmp (p1, "%include", sizeof ("%include") - 1) + if (startswith (p1, "%include") && (p1[sizeof "%include" - 1] == ' ' || p1[sizeof "%include" - 1] == '\t')) { @@ -2399,7 +2405,7 @@ read_specs (const char *filename, bool main_p, bool user_p) read_specs (new_filename ? new_filename : p1, false, user_p); continue; } - else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) + else if (startswith (p1, "%include_noerr") && (p1[sizeof "%include_noerr" - 1] == ' ' || p1[sizeof "%include_noerr" - 1] == '\t')) { @@ -2423,7 +2429,7 @@ read_specs (const char *filename, bool main_p, bool user_p) fnotice (stderr, "could not find specs file %s\n", p1); continue; } - else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) + else if (startswith (p1, "%rename") && (p1[sizeof "%rename" - 1] == ' ' || p1[sizeof "%rename" - 1] == '\t')) { @@ -3056,6 +3062,11 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode, return xstrdup (DEFAULT_LINKER); #endif +#ifdef DEFAULT_DSYMUTIL + if (! strcmp (name, "dsymutil") && access (DEFAULT_DSYMUTIL, mode) == 0) + return xstrdup (DEFAULT_DSYMUTIL); +#endif + /* Determine the filename to execute (special case for absolute paths). */ if (IS_ABSOLUTE_PATH (name)) @@ -3245,7 +3256,7 @@ execute (void) n_commands++; /* Get storage for each command. */ - commands = (struct command *) alloca (n_commands * sizeof (struct command)); + commands = XALLOCAVEC (struct command, n_commands); /* Split argbuf into its separate piped processes, and record info about each one. @@ -3424,13 +3435,13 @@ execute (void) struct pex_time *times = NULL; int ret_code = 0; - statuses = (int *) alloca (n_commands * sizeof (int)); + statuses = XALLOCAVEC (int, n_commands); if (!pex_get_status (pex, n_commands, statuses)) fatal_error (input_location, "failed to get exit status: %m"); if (report_times || report_times_to_file) { - times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time)); + times = XALLOCAVEC (struct pex_time, n_commands); if (!pex_get_times (pex, n_commands, times)) fatal_error (input_location, "failed to get process times: %m"); } @@ -3496,7 +3507,7 @@ execute (void) && WEXITSTATUS (status) == ICE_EXIT_CODE && i == 0 && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) - && ! strncmp (p + 1, "cc1", 3)) + && startswith (p + 1, "cc1")) try_generate_repro (commands[0].argv); if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); @@ -3746,6 +3757,7 @@ display_help (void) fputs (_(" -dumpspecs Display all of the built in spec strings.\n"), stdout); fputs (_(" -dumpversion Display the version of the compiler.\n"), stdout); fputs (_(" -dumpmachine Display the compiler's target processor.\n"), stdout); + fputs (_(" -foffload=<targets> Specify offloading targets.\n"), stdout); fputs (_(" -print-search-dirs Display the directories in the compiler's search path.\n"), stdout); fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library.\n"), stdout); fputs (_(" -print-file-name=<lib> Display the full path to library <lib>.\n"), stdout); @@ -3971,6 +3983,87 @@ driver_wrong_lang_callback (const struct cl_decoded_option *decoded, static const char *spec_lang = 0; static int last_language_n_infiles; + +/* Check that GCC is configured to support the offload target. */ + +static bool +check_offload_target_name (const char *target, ptrdiff_t len) +{ + const char *n, *c = OFFLOAD_TARGETS; + while (c) + { + n = strchr (c, ','); + if (n == NULL) + n = strchr (c, '\0'); + if (len == n - c && strncmp (target, c, n - c) == 0) + break; + c = *n ? n + 1 : NULL; + } + if (!c) + { + auto_vec<const char*> candidates; + size_t olen = strlen (OFFLOAD_TARGETS) + 1; + char *cand = XALLOCAVEC (char, olen); + memcpy (cand, OFFLOAD_TARGETS, olen); + for (c = strtok (cand, ","); c; c = strtok (NULL, ",")) + candidates.safe_push (c); + + char *target2 = XALLOCAVEC (char, len + 1); + memcpy (target2, target, len); + target2[len] = '\0'; + + error ("GCC is not configured to support %qs as offload target", target2); + + if (candidates.is_empty ()) + inform (UNKNOWN_LOCATION, "no offloading targets configured"); + else + { + char *s; + const char *hint = candidates_list_and_hint (target2, s, candidates); + if (hint) + inform (UNKNOWN_LOCATION, + "valid offload targets are: %s; did you mean %qs?", s, hint); + else + inform (UNKNOWN_LOCATION, "valid offload targets are: %s", s); + XDELETEVEC (s); + } + return false; + } + return true; +} + +/* Sanity check for -foffload-options. */ + +static void +check_foffload_target_names (const char *arg) +{ + const char *cur, *next, *end; + /* If option argument starts with '-' then no target is specified and we + do not need to parse it. */ + if (arg[0] == '-') + return; + end = strchr (arg, '='); + if (end == NULL) + { + error ("%<=%>options missing after %<-foffload-options=%>target"); + return; + } + + cur = arg; + while (cur < end) + { + next = strchr (cur, ','); + if (next == NULL) + next = end; + next = (next > end) ? end : next; + + /* Retain non-supported targets after printing an error as those will not + be processed; each enabled target only processes its triplet. */ + check_offload_target_name (cur, next - cur); + cur = next + 1; + } +} + /* Parse -foffload option argument. */ static void @@ -4000,34 +4093,25 @@ handle_foffload_option (const char *arg) memcpy (target, cur, next - cur); target[next - cur] = '\0'; - /* If 'disable' is passed to the option, stop parsing the option and clean - the list of offload targets. */ - if (strcmp (target, "disable") == 0) + /* Reset offloading list and continue. */ + if (strcmp (target, "default") == 0) { free (offload_targets); - offload_targets = xstrdup (""); - break; + offload_targets = NULL; + goto next_item; } - /* Check that GCC is configured to support the offload target. */ - c = OFFLOAD_TARGETS; - while (c) + /* If 'disable' is passed to the option, clean the list of + offload targets and return, even if more targets follow. + Likewise if GCC is not configured to support that offload target. */ + if (strcmp (target, "disable") == 0 + || !check_offload_target_name (target, next - cur)) { - n = strchr (c, ','); - if (n == NULL) - n = strchr (c, '\0'); - - if (next - cur == n - c && strncmp (target, c, n - c) == 0) - break; - - c = *n ? n + 1 : NULL; + free (offload_targets); + offload_targets = xstrdup (""); + return; } - if (!c) - fatal_error (input_location, - "GCC is not configured to support %s as offload target", - target); - if (!offload_targets) { offload_targets = target; @@ -4061,7 +4145,7 @@ handle_foffload_option (const char *arg) memcpy (offload_targets + offload_targets_len, target, next - cur + 1); } } - +next_item: cur = next + 1; XDELETEVEC (target); } @@ -4493,8 +4577,16 @@ driver_handle_option (struct gcc_options *opts, flag_wpa = ""; break; + case OPT_foffload_options_: + check_foffload_target_names (arg); + break; + case OPT_foffload_: handle_foffload_option (arg); + if (arg[0] == '-' || NULL != strchr (arg, '=')) + save_switch (concat ("-foffload-options=", arg, NULL), + 0, NULL, validated, true); + do_save = false; break; default: @@ -4828,7 +4920,22 @@ process_command (unsigned int decoded_options_count, /* If the user didn't specify any, default to all configured offload targets. */ if (ENABLE_OFFLOADING && offload_targets == NULL) - handle_foffload_option (OFFLOAD_TARGETS); + { + handle_foffload_option (OFFLOAD_TARGETS); +#if OFFLOAD_DEFAULTED + offload_targets_default = true; +#endif + } + + /* Handle -gtoggle as it would later in toplev.c:process_options to + make the debug-level-gt spec function work as expected. */ + if (flag_gtoggle) + { + if (debug_info_level == DINFO_LEVEL_NONE) + debug_info_level = DINFO_LEVEL_NORMAL; + else + debug_info_level = DINFO_LEVEL_NONE; + } if (output_file && strcmp (output_file, "-") != 0 @@ -5827,10 +5934,7 @@ compile_input_file_p (struct infile *infile) static void do_specs_vec (vec<char_p> vec) { - unsigned ix; - char *opt; - - FOR_EACH_VEC_ELT (vec, ix, opt) + for (char *opt : vec) { do_spec_1 (opt, 1, NULL); /* Make each accumulated option a separate argument. */ @@ -6425,8 +6529,6 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) { const char *p1 = p; char *string; - char *opt; - unsigned ix; /* Skip past the option value and make a copy. */ if (*p != '{') @@ -6437,7 +6539,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) string = save_string (p1 + 1, p - p1 - 2); /* See if we already recorded this option. */ - FOR_EACH_VEC_ELT (linker_options, ix, opt) + for (const char *opt : linker_options) if (! strcmp (string, opt)) { free (string); @@ -7324,7 +7426,7 @@ check_live_switch (int switchnum, int prefix_length) break; case 'W': case 'f': case 'm': case 'g': - if (! strncmp (name + 1, "no-", 3)) + if (startswith (name + 1, "no-")) { /* We have Xno-YYY, search for XYYY. */ for (i = switchnum + 1; i < n_switches; i++) @@ -8305,9 +8407,7 @@ driver::set_up_specs () const && do_spec_2 (startfile_prefix_spec, NULL) == 0 && do_spec_1 (" ", 0, NULL) == 0) { - const char *arg; - int ndx; - FOR_EACH_VEC_ELT (argbuf, ndx, arg) + for (const char *arg : argbuf) add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1); } @@ -8484,6 +8584,10 @@ driver::maybe_putenv_OFFLOAD_TARGETS () const obstack_grow (&collect_obstack, offload_targets, strlen (offload_targets) + 1); xputenv (XOBFINISH (&collect_obstack, char *)); +#if OFFLOAD_DEFAULTED + if (offload_targets_default) + xputenv ("OFFLOAD_TARGET_DEFAULT=1"); +#endif } free (offload_targets); |