/* Compiler driver program that can handle many languages.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "flags.h"
#include "opts.h"
#include "params.h"
-#include "vec.h"
#include "filenames.h"
/* By default there is no special suffix for target executables. */
/* The target machine. */
static const char *spec_machine = DEFAULT_TARGET_MACHINE;
+static const char *spec_host_machine = DEFAULT_REAL_TARGET_MACHINE;
+
+/* List of offload targets. */
+
+static char *offload_targets = NULL;
/* Nonzero if cross-compiling.
When -b is used, the value comes from the `specs' file. */
#ifndef LINK_SSP_SPEC
#ifdef TARGET_LIBC_PROVIDES_SSP
-#define LINK_SSP_SPEC "%{fstack-protector:}"
+#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ "|fstack-protector-strong|fstack-protector-explicit:}"
#else
-#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-strong|fstack-protector-all:-lssp_nonshared -lssp}"
+#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ "|fstack-protector-strong|fstack-protector-explicit" \
+ ":-lssp_nonshared -lssp}"
#endif
#endif
+#ifdef ENABLE_DEFAULT_PIE
+#define NO_PIE_SPEC "no-pie|static"
+#define PIE_SPEC NO_PIE_SPEC "|r|shared:;"
+#define NO_FPIE1_SPEC "fno-pie"
+#define FPIE1_SPEC NO_FPIE1_SPEC ":;"
+#define NO_FPIE2_SPEC "fno-PIE"
+#define FPIE2_SPEC NO_FPIE2_SPEC ":;"
+#define NO_FPIE_SPEC NO_FPIE1_SPEC "|" NO_FPIE2_SPEC
+#define FPIE_SPEC NO_FPIE_SPEC ":;"
+#define NO_FPIC1_SPEC "fno-pic"
+#define FPIC1_SPEC NO_FPIC1_SPEC ":;"
+#define NO_FPIC2_SPEC "fno-PIC"
+#define FPIC2_SPEC NO_FPIC2_SPEC ":;"
+#define NO_FPIC_SPEC NO_FPIC1_SPEC "|" NO_FPIC2_SPEC
+#define FPIC_SPEC NO_FPIC_SPEC ":;"
+#define NO_FPIE1_AND_FPIC1_SPEC NO_FPIE1_SPEC "|" NO_FPIC1_SPEC
+#define FPIE1_OR_FPIC1_SPEC NO_FPIE1_AND_FPIC1_SPEC ":;"
+#define NO_FPIE2_AND_FPIC2_SPEC NO_FPIE2_SPEC "|" NO_FPIC2_SPEC
+#define FPIE2_OR_FPIC2_SPEC NO_FPIE2_AND_FPIC2_SPEC ":;"
+#define NO_FPIE_AND_FPIC_SPEC NO_FPIE_SPEC "|" NO_FPIC_SPEC
+#define FPIE_OR_FPIC_SPEC NO_FPIE_AND_FPIC_SPEC ":;"
+#else
+#define PIE_SPEC "pie"
+#define NO_PIE_SPEC PIE_SPEC "|r|shared:;"
+#define FPIE1_SPEC "fpie"
+#define NO_FPIE1_SPEC FPIE1_SPEC ":;"
+#define FPIE2_SPEC "fPIE"
+#define NO_FPIE2_SPEC FPIE2_SPEC ":;"
+#define FPIE_SPEC FPIE1_SPEC "|" FPIE2_SPEC
+#define NO_FPIE_SPEC FPIE_SPEC ":;"
+#define FPIC1_SPEC "fpic"
+#define NO_FPIC1_SPEC FPIC1_SPEC ":;"
+#define FPIC2_SPEC "fPIC"
+#define NO_FPIC2_SPEC FPIC2_SPEC ":;"
+#define FPIC_SPEC FPIC1_SPEC "|" FPIC2_SPEC
+#define NO_FPIC_SPEC FPIC_SPEC ":;"
+#define FPIE1_OR_FPIC1_SPEC FPIE1_SPEC "|" FPIC1_SPEC
+#define NO_FPIE1_AND_FPIC1_SPEC FPIE1_OR_FPIC1_SPEC ":;"
+#define FPIE2_OR_FPIC2_SPEC FPIE2_SPEC "|" FPIC2_SPEC
+#define NO_FPIE2_AND_FPIC2_SPEC FPIE1_OR_FPIC2_SPEC ":;"
+#define FPIE_OR_FPIC_SPEC FPIE_SPEC "|" FPIC_SPEC
+#define NO_FPIE_AND_FPIC_SPEC FPIE_OR_FPIC_SPEC ":;"
+#endif
+
#ifndef LINK_PIE_SPEC
#ifdef HAVE_LD_PIE
-#define LINK_PIE_SPEC "%{pie:-pie} "
+#define LD_PIE_SPEC "-pie"
#else
-#define LINK_PIE_SPEC "%{pie:} "
+#define LD_PIE_SPEC ""
#endif
+#define LINK_PIE_SPEC "%{no-pie:} " "%{" PIE_SPEC ":" LD_PIE_SPEC "} "
#endif
#ifndef LINK_BUILDID_SPEC
#define PLUGIN_COND_CLOSE ""
#endif
#define LINK_PLUGIN_SPEC \
- "%{"PLUGIN_COND": \
+ "%{" PLUGIN_COND": \
-plugin %(linker_plugin_file) \
-plugin-opt=%(lto_wrapper) \
-plugin-opt=-fresolution=%u.res \
%{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
- }"PLUGIN_COND_CLOSE
+ }" PLUGIN_COND_CLOSE
#else
/* The linker used doesn't support -plugin, reject -fuse-linker-plugin. */
#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=address}}\
%{%:sanitize(thread):" LIBTSAN_SPEC "\
- %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}\
+ %{static:%ecannot specify -static with -fsanitize=thread}}\
%{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
%{%:sanitize(leak):" LIBLSAN_SPEC "}}}"
#endif
%{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}"
#endif
+#ifndef CHKP_SPEC
+#define CHKP_SPEC ""
+#endif
+
/* -u* was put back because both BSD and SysV seem to support it. */
/* %{static:} simply prevents an error message if the target machine
doesn't handle -static. */
%(linker) " \
LINK_PLUGIN_SPEC \
"%{flto|flto=*:%<fcompare-debug*} \
- %{flto} %{flto=*} %l " LINK_PIE_SPEC \
+ %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \
"%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
"%X %{o*} %{e*} %{N} %{n} %{r}\
%{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} " VTABLE_VERIFICATION_SPEC " \
%{static:} %{L*} %(mfwrap) %(link_libgcc) " SANITIZER_EARLY_SPEC " %o\
- %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+ " CHKP_SPEC " \
+ %{fopenacc|fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
%{fcilkplus:%:include(libcilkrts.spec)%(link_cilkrts)}\
%{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
%(mflib) " STACK_SPLIT_SPEC "\
/* Linking to libgomp implies pthreads. This is particularly important
for targets that use different start files and suchlike. */
#ifndef GOMP_SELF_SPECS
-#define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
+#define GOMP_SELF_SPECS "%{fopenacc|fopenmp|ftree-parallelize-loops=*: " \
+ "-pthread}"
#endif
/* Likewise for -fgnu-tm. */
%(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
%(cc1_options)\
- %{!fdump-ada-spec*:-o %g.s %{!o*:--output-pch=%i.gch}\
- %W{o*:--output-pch=%*}}%V}\
+ %{!fsyntax-only:-o %g.s \
+ %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}\
+ %W{o*:--output-pch=%*}}%V}}\
%{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
cc1 %(cpp_unique_options) %(cc1_options)\
- %{!fdump-ada-spec*:-o %g.s %{!o*:--output-pch=%i.gch}\
- %W{o*:--output-pch=%*}}%V}}}}}}", 0, 0, 0},
+ %{!fsyntax-only:-o %g.s \
+ %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}\
+ %W{o*:--output-pch=%*}}%V}}}}}}}", 0, 0, 0},
{".i", "@cpp-output", 0, 0, 0},
{"@cpp-output",
"%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
relative to the driver. */
static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
+/* A prefix to be used when this is an accelerator compiler. */
+static const char *const accel_dir_suffix = ACCEL_DIR_SUFFIX;
+
/* Subdirectory to use for locating libraries. Set by
set_multilib_dir based on the compilation options. */
static vec<const_char_p> argbuf;
-/* Position in the argbuf vector containing the name of the output file
- (the value associated with the "-o" flag). */
-
-static int have_o_argbuf_index = 0;
-
/* Were the options -c, -S or -E passed. */
static int have_c = 0;
/* Was the option -o passed. */
static int have_o = 0;
+/* Pointer to output file name passed in with -o. */
+static const char *output_file = 0;
+
/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for
it here. */
{
argbuf.safe_push (arg);
- if (strcmp (arg, "-o") == 0)
- have_o_argbuf_index = argbuf.length ();
if (delete_always || delete_failure)
{
const char *p;
p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal_error ("specs %%include syntax malformed after "
+ fatal_error (input_location,
+ "specs %%include syntax malformed after "
"%ld characters",
(long) (p1 - buffer + 1));
p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal_error ("specs %%include syntax malformed after "
+ fatal_error (input_location,
+ "specs %%include syntax malformed after "
"%ld characters",
(long) (p1 - buffer + 1));
p1++;
if (! ISALPHA ((unsigned char) *p1))
- fatal_error ("specs %%rename syntax malformed after "
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
"%ld characters",
(long) (p1 - buffer));
p2++;
if (*p2 != ' ' && *p2 != '\t')
- fatal_error ("specs %%rename syntax malformed after "
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
"%ld characters",
(long) (p2 - buffer));
p2++;
if (! ISALPHA ((unsigned char) *p2))
- fatal_error ("specs %%rename syntax malformed after "
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
"%ld characters",
(long) (p2 - buffer));
p3++;
if (p3 != p - 1)
- fatal_error ("specs %%rename syntax malformed after "
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
"%ld characters",
(long) (p3 - buffer));
*p3 = '\0';
break;
if (!sl)
- fatal_error ("specs %s spec was not found to be renamed", p1);
+ fatal_error (input_location,
+ "specs %s spec was not found to be renamed", p1);
if (strcmp (p1, p2) == 0)
continue;
for (newsl = specs; newsl; newsl = newsl->next)
if (strcmp (newsl->name, p2) == 0)
- fatal_error ("%s: attempt to rename spec %qs to "
+ fatal_error (input_location,
+ "%s: attempt to rename spec %qs to "
"already defined spec %qs",
filename, p1, p2);
continue;
}
else
- fatal_error ("specs unknown %% command after %ld characters",
+ fatal_error (input_location,
+ "specs unknown %% command after %ld characters",
(long) (p1 - buffer));
}
/* The colon shouldn't be missing. */
if (*p1 != ':')
- fatal_error ("specs file malformed after %ld characters",
+ fatal_error (input_location,
+ "specs file malformed after %ld characters",
(long) (p1 - buffer));
/* Skip back over trailing whitespace. */
/* Find the next line. */
p = skip_whitespace (p1 + 1);
if (p[1] == 0)
- fatal_error ("specs file malformed after %ld characters",
+ fatal_error (input_location,
+ "specs file malformed after %ld characters",
(long) (p - buffer));
p1 = p;
}
if (link_command_spec == 0)
- fatal_error ("spec file has no spec for linking");
+ fatal_error (input_location, "spec file has no spec for linking");
}
\f
/* Record the names of temporary files we tell compilers to write,
int require_machine_suffix, int os_multilib)
{
if (!IS_ABSOLUTE_PATH (prefix))
- fatal_error ("system path %qs is not absolute", prefix);
+ fatal_error (input_location, "system path %qs is not absolute", prefix);
if (target_system_root)
{
if (arg && strcmp (arg, "|") == 0)
{ /* each command. */
#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
- fatal_error ("-pipe not supported");
+ fatal_error (input_location, "-pipe not supported");
#endif
argbuf[i] = 0; /* Termination of
command args. */
? PEX_RECORD_TIMES : 0),
progname, temp_filename);
if (pex == NULL)
- fatal_error ("pex_init failed: %m");
+ fatal_error (input_location, "pex_init failed: %m");
for (i = 0; i < n_commands; i++)
{
if (errmsg != NULL)
{
if (err == 0)
- fatal_error (errmsg);
+ fatal_error (input_location, errmsg);
else
{
errno = err;
statuses = (int *) alloca (n_commands * sizeof (int));
if (!pex_get_status (pex, n_commands, statuses))
- fatal_error ("failed to get exit status: %m");
+ 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));
if (!pex_get_times (pex, n_commands, times))
- fatal_error ("failed to get process times: %m");
+ fatal_error (input_location, "failed to get process times: %m");
}
pex_free (pex);
}
else
#endif
- internal_error ("%s (program %s)",
- strsignal (WTERMSIG (status)), commands[i].prog);
+ internal_error_no_backtrace ("%s (program %s)",
+ strsignal (WTERMSIG (status)),
+ commands[i].prog);
}
else if (WIFEXITED (status)
&& WEXITSTATUS (status) >= MIN_FATAL_STATUS)
static const char *spec_lang = 0;
static int last_language_n_infiles;
+/* Parse -foffload option argument. */
+
+static void
+handle_foffload_option (const char *arg)
+{
+ const char *c, *cur, *n, *next, *end;
+ char *target;
+
+ /* 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)
+ end = strchr (arg, '\0');
+ cur = arg;
+
+ while (cur < end)
+ {
+ next = strchr (cur, ',');
+ if (next == NULL)
+ next = end;
+ next = (next > end) ? end : next;
+
+ target = XNEWVEC (char, next - cur + 1);
+ 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)
+ {
+ free (offload_targets);
+ offload_targets = xstrdup ("");
+ break;
+ }
+
+ /* Check that GCC is configured to support the offload target. */
+ c = OFFLOAD_TARGETS;
+ while (c)
+ {
+ 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;
+ }
+
+ if (!c)
+ fatal_error (input_location,
+ "GCC is not configured to support %s as offload target",
+ target);
+
+ if (!offload_targets)
+ {
+ offload_targets = target;
+ target = NULL;
+ }
+ else
+ {
+ /* Check that the target hasn't already presented in the list. */
+ c = offload_targets;
+ do
+ {
+ n = strchr (c, ':');
+ if (n == NULL)
+ n = strchr (c, '\0');
+
+ if (next - cur == n - c && strncmp (c, target, n - c) == 0)
+ break;
+
+ c = n + 1;
+ }
+ while (*n);
+
+ /* If duplicate is not found, append the target to the list. */
+ if (c > n)
+ {
+ size_t offload_targets_len = strlen (offload_targets);
+ offload_targets
+ = XRESIZEVEC (char, offload_targets,
+ offload_targets_len + next - cur + 2);
+ if (offload_targets_len)
+ offload_targets[offload_targets_len++] = ':';
+ memcpy (offload_targets + offload_targets_len, target, next - cur);
+ }
+ }
+
+ cur = next + 1;
+ XDELETEVEC (target);
+ }
+}
+
/* Handle a driver option; arguments and return value as for
handle_option. */
save_switch (compare_debug_replacement_opt, 0, NULL, validated, true);
return true;
+ case OPT_fdiagnostics_color_:
+ diagnostic_color_init (dc, value);
+ break;
+
case OPT_Wa_:
{
int prev, j;
|| strcmp (arg, "object") == 0)
save_temps_flag = SAVE_TEMPS_OBJ;
else
- fatal_error ("%qs is an unknown -save-temps option",
+ fatal_error (input_location, "%qs is an unknown -save-temps option",
decoded->orig_option_with_args_text);
break;
#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
arg = convert_filename (arg, ! have_c, 0);
#endif
+ output_file = arg;
/* Save the output name in case -save-temps=obj was used. */
save_temps_prefix = xstrdup (arg);
/* On some systems, ld cannot handle "-o" without a space. So
save_switch ("-o", 1, &arg, validated, true);
return true;
+#ifdef ENABLE_DEFAULT_PIE
+ case OPT_pie:
+ /* -pie is turned on by default. */
+#endif
+
case OPT_static_libgcc:
case OPT_shared_libgcc:
case OPT_static_libgfortran:
flag_wpa = "";
break;
+ case OPT_foffload_:
+ handle_foffload_option (arg);
+ break;
+
default:
/* Various driver options need no special processing at this
point, having been handled in a prescan above or being
CL_DRIVER, &handlers, global_dc);
}
+ if (output_file
+ && strcmp (output_file, "-") != 0
+ && strcmp (output_file, HOST_BIT_BUCKET) != 0)
+ {
+ int i;
+ for (i = 0; i < n_infiles; i++)
+ if ((!infiles[i].language || infiles[i].language[0] != '*')
+ && canonical_filename_eq (infiles[i].name, output_file))
+ fatal_error (input_location,
+ "input file %qs is the same as output file",
+ output_file);
+ }
+
/* If -save-temps=obj and -o name, create the prefix to use for %b.
Otherwise just make -save-temps=obj the same as -save-temps=cwd. */
if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
}
gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
- tooldir_prefix2 = concat (tooldir_base_prefix, spec_machine,
+ tooldir_prefix2 = concat (tooldir_base_prefix, spec_host_machine,
dir_separator_str, NULL);
/* Look for tools relative to the location from which the driver is
running, or, if that is not available, the configured prefix. */
tooldir_prefix
= concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
- spec_machine, dir_separator_str,
- spec_version, dir_separator_str, tooldir_prefix2, NULL);
+ spec_host_machine, dir_separator_str, spec_version,
+ accel_dir_suffix, dir_separator_str, tooldir_prefix2, NULL);
free (tooldir_prefix2);
add_prefix (&exec_prefixes,
/* Specs should only generate options, not input
files. */
if (strcmp (decoded_options[j].arg, "-") != 0)
- fatal_error ("switch %qs does not start with %<-%>",
+ fatal_error (input_location,
+ "switch %qs does not start with %<-%>",
decoded_options[j].arg);
else
- fatal_error ("spec-generated switch is just %<-%>");
+ fatal_error (input_location,
+ "spec-generated switch is just %<-%>");
break;
case OPT_fcompare_debug_second:
}
}
+ free (decoded_options);
+
alloc_switch ();
switches[n_switches].part1 = 0;
}
int status;
if (f == NULL)
- fatal_error ("could not open temporary response file %s",
+ fatal_error (input_location, "could not open temporary response file %s",
temp_file);
status = writeargv (argv, f);
if (status)
- fatal_error ("could not write to temporary response file %s",
+ fatal_error (input_location,
+ "could not write to temporary response file %s",
temp_file);
status = fclose (f);
if (EOF == status)
- fatal_error ("could not close temporary response file %s",
+ fatal_error (input_location, "could not close temporary response file %s",
temp_file);
store_arg (at_argument, 0, 0);
switch (c = *p++)
{
case 0:
- fatal_error ("spec %qs invalid", spec);
+ fatal_error (input_location, "spec %qs invalid", spec);
case 'b':
if (save_temps_length)
p += 2;
/* We don't support extra suffix characters after %O. */
if (*p == '.' || ISALNUM ((unsigned char) *p))
- fatal_error ("spec %qs has invalid %<%%0%c%>", spec, *p);
+ fatal_error (input_location,
+ "spec %qs has invalid %<%%0%c%>", spec, *p);
if (suffix_length == 0)
suffix = TARGET_OBJECT_SUFFIX;
else
unsigned int cur_index = argbuf.length ();
/* Handle the {...} following the %W. */
if (*p != '{')
- fatal_error ("spec %qs has invalid %<%%W%c%>", spec, *p);
+ fatal_error (input_location,
+ "spec %qs has invalid %<%%W%c%>", spec, *p);
p = handle_braces (p + 1);
if (p == 0)
return -1;
/* Skip past the option value and make a copy. */
if (*p != '{')
- fatal_error ("spec %qs has invalid %<%%x%c%>", spec, *p);
+ fatal_error (input_location,
+ "spec %qs has invalid %<%%x%c%>", spec, *p);
while (*p++ != '}')
;
string = save_string (p1 + 1, p - p1 - 2);
sf = lookup_spec_function (func);
if (sf == NULL)
- fatal_error ("unknown spec function %qs", func);
+ fatal_error (input_location, "unknown spec function %qs", func);
/* Push the spec processing context. */
save_argbuf = argbuf;
alloc_args ();
if (do_spec_2 (args) < 0)
- fatal_error ("error in args to spec function %qs", func);
+ fatal_error (input_location, "error in args to spec function %qs", func);
/* argbuf_index is an index for the next argument to be inserted, and
so contains the count of the args already inserted. */
break;
/* Only allow [A-Za-z0-9], -, and _ in function names. */
if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
- fatal_error ("malformed spec function name");
+ fatal_error (input_location, "malformed spec function name");
}
if (*endp != '(') /* ) */
- fatal_error ("no arguments for spec function");
+ fatal_error (input_location, "no arguments for spec function");
func = save_string (p, endp - p);
p = ++endp;
}
/* ( */
if (*endp != ')')
- fatal_error ("malformed spec function arguments");
+ fatal_error (input_location, "malformed spec function arguments");
args = save_string (p, endp - p);
p = ++endp;
return p;
invalid:
- fatal_error ("braced spec %qs is invalid at %qc", orig, *p);
+ fatal_error (input_location, "braced spec %qs is invalid at %qc", orig, *p);
#undef SKIP_WHITE
}
return p;
invalid:
- fatal_error ("braced spec body %qs is invalid", body);
+ fatal_error (input_location, "braced spec body %qs is invalid", body);
}
\f
/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
if (! strncmp (version_string, compiler_version, n)
&& compiler_version[n] == 0)
- fnotice (file, "gcc version %s %s\n\n", version_string,
+ fnotice (file, "gcc version %s %s\n", version_string,
pkgversion_string);
else
- fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n",
+ fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n",
version_string, pkgversion_string, compiler_version);
}
{
FILE *file_out = fopen (err_temp, "a");
print_configuration (file_out);
+ fputs ("\n", file_out);
fclose (file_out);
}
pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
if (!pex)
- fatal_error ("pex_init failed: %m");
+ fatal_error (input_location, "pex_init failed: %m");
errmsg = pex_run (pex, pex_flags, new_argv[0],
CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
if (errmsg != NULL)
{
if (err == 0)
- fatal_error (errmsg);
+ fatal_error (input_location, errmsg);
else
{
errno = err;
return status;
}
+/* This routine reads lines from IN file, adds C++ style comments
+ at the begining of each line and writes result into OUT. */
+
+static void
+insert_comments (const char *file_in, const char *file_out)
+{
+ FILE *in = fopen (file_in, "rb");
+ FILE *out = fopen (file_out, "wb");
+ char line[256];
+
+ bool add_comment = true;
+ while (fgets (line, sizeof (line), in))
+ {
+ if (add_comment)
+ fputs ("// ", out);
+ fputs (line, out);
+ add_comment = strchr (line, '\n') != NULL;
+ }
+
+ fclose (in);
+ fclose (out);
+}
+
/* This routine adds preprocessed source code into the given ERR_FILE.
To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to
add information in report file. RUN_ATTEMPT should return
}
}
-/* Append string STR to file FILE. */
-
-static void
-append_text (char *file, const char *str)
-{
- int fd = open (file, O_RDWR | O_APPEND);
- if (fd < 0)
- return;
-
- write (fd, str, strlen (str));
- close (fd);
-}
-
/* Try to reproduce ICE. If bug is reproducible, generate report .err file
containing GCC configuration, backtrace, compiler's command line options
and preprocessed source code. */
emit_system_info = 1;
}
- if (emit_system_info)
- append_text (temp_stderr_files[attempt], "/*\n");
-
status = run_attempt (new_argv, temp_stdout_files[attempt],
temp_stderr_files[attempt], emit_system_info,
append);
- if (emit_system_info)
- append_text (temp_stderr_files[attempt], "*/\n");
-
if (status != ATTEMPT_STATUS_ICE)
{
fnotice (stderr, "The bug is not reproducible, so it is"
if (!check_repro (temp_stdout_files, temp_stderr_files))
goto out;
- /* In final attempt we append compiler options and preprocesssed code to last
- generated .err file with configuration and backtrace. */
- do_report_bug (new_argv, nargs,
- &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
- &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+ {
+ /* Insert commented out backtrace into report file. */
+ char **stderr_commented = &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1];
+ insert_comments (temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+ *stderr_commented);
+
+ /* In final attempt we append compiler options and preprocesssed code to last
+ generated .out file with configuration and backtrace. */
+ char **output = &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1];
+ do_report_bug (new_argv, nargs, stderr_commented, output);
+ }
out:
for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
return ret;
}
-/* The top-level "main" within the driver would be ~1000 lines long.
- This class breaks it up into smaller functions and contains some
- state shared by them. */
-
-class driver
-{
- public:
- int main (int argc, char **argv);
-
- private:
- void set_progname (const char *argv0) const;
- void expand_at_files (int *argc, char ***argv) const;
- void decode_argv (int argc, const char **argv);
- void global_initializations () const;
- void build_multilib_strings () const;
- void set_up_specs () const;
- void putenv_COLLECT_GCC (const char *argv0) const;
- void maybe_putenv_COLLECT_LTO_WRAPPER () const;
- void handle_unrecognized_options () const;
- int maybe_print_and_exit () const;
- bool prepare_infiles ();
- void do_spec_on_infiles () const;
- void maybe_run_linker (const char *argv0) const;
- void final_actions () const;
- int get_exit_code () const;
-
- private:
- char *explicit_link_files;
- struct cl_decoded_option *decoded_options;
- unsigned int decoded_options_count;
-};
-
-/* Implement the top-level "main" within the driver in terms of
- driver::main. */
-
-extern int main (int, char **);
-
-int
-main (int argc, char **argv)
-{
- driver d;
-
- return d.main (argc, argv);
-}
-
/* driver::main is implemented as a series of driver:: method calls. */
int
set_up_specs ();
putenv_COLLECT_GCC (argv[0]);
maybe_putenv_COLLECT_LTO_WRAPPER ();
+ maybe_putenv_OFFLOAD_TARGETS ();
handle_unrecognized_options ();
if (!maybe_print_and_exit ())
/* Perform various initializations and setup. */
void
-driver::global_initializations () const
+driver::global_initializations ()
{
/* Unlock the stdio streams. */
unlock_std_streams ();
gcc_init_libintl ();
diagnostic_initialize (global_dc, 0);
+ diagnostic_color_init (global_dc);
#ifdef GCC_DRIVER_HOST_INITIALIZATION
/* Perform host dependent initialization when needed. */
#endif
if (atexit (delete_temp_files) != 0)
- fatal_error ("atexit failed");
+ fatal_error (input_location, "atexit failed");
if (signal (SIGINT, SIG_IGN) != SIG_IGN)
signal (SIGINT, fatal_signal);
void
driver::set_up_specs () const
{
+ const char *spec_machine_suffix;
char *specs_file;
size_t i;
/* Read specs from a file if there is one. */
- machine_suffix = concat (spec_machine, dir_separator_str,
- spec_version, dir_separator_str, NULL);
+ machine_suffix = concat (spec_host_machine, dir_separator_str, spec_version,
+ accel_dir_suffix, dir_separator_str, NULL);
just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
else
init_spec ();
- /* We need to check standard_exec_prefix/just_machine_suffix/specs
+#ifdef ACCEL_COMPILER
+ spec_machine_suffix = machine_suffix;
+#else
+ spec_machine_suffix = just_machine_suffix;
+#endif
+
+ /* We need to check standard_exec_prefix/spec_machine_suffix/specs
for any override of as, ld and libraries. */
specs_file = (char *) alloca (strlen (standard_exec_prefix)
- + strlen (just_machine_suffix) + sizeof ("specs"));
-
+ + strlen (spec_machine_suffix) + sizeof ("specs"));
strcpy (specs_file, standard_exec_prefix);
- strcat (specs_file, just_machine_suffix);
+ strcat (specs_file, spec_machine_suffix);
strcat (specs_file, "specs");
if (access (specs_file, R_OK) == 0)
read_specs (specs_file, true, false);
/* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
if (gcc_exec_prefix)
- gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
- spec_version, dir_separator_str, NULL);
+ gcc_exec_prefix = concat (gcc_exec_prefix, spec_host_machine,
+ dir_separator_str, spec_version,
+ accel_dir_suffix, dir_separator_str, NULL);
/* Now we have the specs.
Set the `valid' bits for switches that match anything in any spec. */
}
+/* Set up to remember the names of offload targets. */
+
+void
+driver::maybe_putenv_OFFLOAD_TARGETS () const
+{
+ const char *targets = offload_targets;
+
+ /* If no targets specified by -foffload, use all available targets. */
+ if (!targets)
+ targets = OFFLOAD_TARGETS;
+
+ if (strlen (targets) > 0)
+ {
+ obstack_grow (&collect_obstack, "OFFLOAD_TARGET_NAMES=",
+ sizeof ("OFFLOAD_TARGET_NAMES=") - 1);
+ obstack_grow (&collect_obstack, targets,
+ strlen (targets) + 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
+ }
+
+ free (offload_targets);
+}
+
/* Reject switches that no pass was interested in. */
void
else
/* The error status indicates that only one set of fixed
headers should be built. */
- fatal_error ("not configured with sysroot headers suffix");
+ fatal_error (input_location,
+ "not configured with sysroot headers suffix");
}
if (print_help_list)
{
printf (_("%s %s%s\n"), progname, pkgversion_string,
version_string);
- printf ("Copyright %s 2014 Free Software Foundation, Inc.\n",
+ printf ("Copyright %s 2015 Free Software Foundation, Inc.\n",
_("(C)"));
fputs (_("This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
int lang_n_infiles = 0;
if (n_infiles == added_libraries)
- fatal_error ("no input files");
+ fatal_error (input_location, "no input files");
if (seen_error ())
/* Early exit needed from main. */
}
if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
- fatal_error ("cannot specify -o with -c, -S or -E with multiple files");
+ fatal_error (input_location,
+ "cannot specify -o with -c, -S or -E with multiple files");
/* No early exit needed from main; we can continue. */
return false;
LTOPLUGINSONAME, R_OK,
false);
if (!temp_spec)
- fatal_error ("-fuse-linker-plugin, but %s not found",
+ fatal_error (input_location,
+ "-fuse-linker-plugin, but %s not found",
LTOPLUGINSONAME);
linker_plugin_file_spec = convert_white_space (temp_spec);
}
if (*q == '\0')
{
invalid_matches:
- fatal_error ("multilib spec %qs is invalid",
+ fatal_error (input_location, "multilib spec %qs is invalid",
multilib_matches);
}
q++;
if (*p == '\0')
{
invalid_exclusions:
- fatal_error ("multilib exclusions %qs is invalid",
+ fatal_error (input_location, "multilib exclusions %qs is invalid",
multilib_exclusions);
}
if (*p == '\0')
{
invalid_select:
- fatal_error ("multilib select %qs %qs is invalid",
+ fatal_error (input_location, "multilib select %qs %qs is invalid",
multilib_select, multilib_reuse);
}
++p;
if (*p == '\0')
{
invalid_select:
- fatal_error ("multilib select %qs is invalid", multilib_select);
+ fatal_error (input_location,
+ "multilib select %qs is invalid", multilib_select);
}
++p;
if (*e == '\0')
{
invalid_exclusion:
- fatal_error ("multilib exclusion %qs is invalid",
+ fatal_error (input_location,
+ "multilib exclusion %qs is invalid",
multilib_exclusions);
}
value = getenv (argv[0]);
if (!value)
- fatal_error ("environment variable %qs not defined", argv[0]);
+ fatal_error (input_location,
+ "environment variable %qs not defined", argv[0]);
/* We have to escape every character of the environment variable so
they are not interpreted as active spec characters. A
abort ();
rresult = regexec (&r, v1, 0, NULL, 0);
if (rresult == REG_NOMATCH)
- fatal_error ("invalid version number %qs", v1);
+ fatal_error (input_location, "invalid version number %qs", v1);
else if (rresult != 0)
abort ();
rresult = regexec (&r, v2, 0, NULL, 0);
if (rresult == REG_NOMATCH)
- fatal_error ("invalid version number %qs", v2);
+ fatal_error (input_location, "invalid version number %qs", v2);
else if (rresult != 0)
abort ();
bool result;
if (argc < 3)
- fatal_error ("too few arguments to %%:version-compare");
+ fatal_error (input_location, "too few arguments to %%:version-compare");
if (argv[0][0] == '\0')
abort ();
if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!')
nargs = 2;
if (argc != nargs + 3)
- fatal_error ("too many arguments to %%:version-compare");
+ fatal_error (input_location, "too many arguments to %%:version-compare");
switch_len = strlen (argv[nargs + 1]);
for (i = 0; i < n_switches; i++)
break;
default:
- fatal_error ("unknown operator %qs in %%:version-compare", argv[0]);
+ fatal_error (input_location,
+ "unknown operator %qs in %%:version-compare", argv[0]);
}
if (! result)
return NULL;
static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
if (arg != 0)
- fatal_error ("too many arguments to %%:compare-debug-dump-opt");
+ fatal_error (input_location,
+ "too many arguments to %%:compare-debug-dump-opt");
do_spec_2 ("%{fdump-final-insns=*:%*}");
do_spec_1 (" ", 0, NULL);
const char **argv ATTRIBUTE_UNUSED)
{
if (arg != 0)
- fatal_error ("too many arguments to %%:compare-debug-self-opt");
+ fatal_error (input_location,
+ "too many arguments to %%:compare-debug-self-opt");
if (compare_debug >= 0)
return NULL;
int len;
if (arg == 0)
- fatal_error ("too few arguments to %%:compare-debug-auxbase-opt");
+ fatal_error (input_location,
+ "too few arguments to %%:compare-debug-auxbase-opt");
if (arg != 1)
- fatal_error ("too many arguments to %%:compare-debug-auxbase-opt");
+ fatal_error (input_location,
+ "too many arguments to %%:compare-debug-auxbase-opt");
if (compare_debug >= 0)
return NULL;
len = strlen (argv[0]);
if (len < 3 || strcmp (argv[0] + len - 3, ".gk") != 0)
- fatal_error ("argument to %%:compare-debug-auxbase-opt "
+ fatal_error (input_location, "argument to %%:compare-debug-auxbase-opt "
"does not end in .gk");
if (debug_auxbase_opt)
int i;
if (argc != 2)
- fatal_error ("too few arguments to %%:replace-extension");
+ fatal_error (input_location, "too few arguments to %%:replace-extension");
name = xstrdup (argv[0]);
else
return orig;
}
+
+/* PR jit/64810.
+ Targets can provide configure-time default options in
+ OPTION_DEFAULT_SPECS. The jit needs to access these, but
+ they are expressed in the spec language.
+
+ Run just enough of the driver to be able to expand these
+ specs, and then call the callback CB on each
+ such option. The options strings are *without* a leading
+ '-' character e.g. ("march=x86-64"). Finally, clean up. */
+
+void
+driver_get_configure_time_options (void (*cb) (const char *option,
+ void *user_data),
+ void *user_data)
+{
+ size_t i;
+
+ obstack_init (&obstack);
+ gcc_obstack_init (&opts_obstack);
+ n_switches = 0;
+
+ for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
+ do_option_spec (option_default_specs[i].name,
+ option_default_specs[i].spec);
+
+ for (i = 0; (int) i < n_switches; i++)
+ {
+ gcc_assert (switches[i].part1);
+ (*cb) (switches[i].part1, user_data);
+ }
+
+ obstack_free (&opts_obstack, NULL);
+ obstack_free (&obstack, NULL);
+ n_switches = 0;
+}