/* Compiler driver program that can handle many languages.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010
Free Software Foundation, Inc.
This file is part of GCC.
#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. */
/* 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%*} \
+ %{m*:-plugin-opt=-m%*} \
+ %{v:-plugin-opt=-v} \
+ } \
+ %{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)\
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;
/* NB: This is shared amongst all front-ends, except for Ada. */
static const char *cc1_options =
"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
+ %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{a*}\
%{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} \
%{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \
%{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
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
static const char *const driver_self_specs[] = {
"%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
- DRIVER_SELF_SPECS, GOMP_SELF_SPECS
+ DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS
};
#ifndef OPTION_DEFAULT_SPECS
#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) \
{"--dependencies", "-M", 0},
{"--dump", "-d", "a"},
{"--dumpbase", "-dumpbase", "a"},
+ {"--dumpdir", "-dumpdir", "a"},
{"--encoding", "-fencoding=", "aj"},
{"--entry", "-e", 0},
{"--extra-warnings", "-W", 0},
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),
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. */
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
-
+
if (!wrapper_string)
{
string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
SWITCH_LIVE to indicate this switch is true in a conditional spec.
SWITCH_FALSE to indicate this switch is overridden by a later switch.
SWITCH_IGNORE to indicate this switch should be ignored (used in %<S).
+ SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored
+ in all do_spec calls afterwards. Used for %<S from self specs.
The `validated' field is nonzero if any spec has looked at this switch;
if it remains zero at the end of the run, it must be meaningless. */
-#define SWITCH_LIVE 0x1
-#define SWITCH_FALSE 0x2
-#define SWITCH_IGNORE 0x4
+#define SWITCH_LIVE 0x1
+#define SWITCH_FALSE 0x2
+#define SWITCH_IGNORE 0x4
+#define SWITCH_IGNORE_PERMANENTLY 0x8
struct switchstr
{
CONST_CAST2 (const char *const **, const char ***,
&argv));
- /* Do language-specific adjustment/addition of flags. */
- lang_specific_driver (&argc,
- CONST_CAST2 (const char *const **, const char ***,
- &argv),
- &added_libraries);
-
/* Handle any -no-canonical-prefixes flag early, to assign the function
that builds relative prefixes. This function creates default search
paths that are needed later in normal option handling. */
is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
or an automatically created GCC_EXEC_PREFIX from argv[0]. */
+ /* Do language-specific adjustment/addition of flags. */
+ lang_specific_driver (&argc,
+ CONST_CAST2 (const char *const **, const char ***,
+ &argv),
+ &added_libraries);
+
if (gcc_exec_prefix)
{
int len = strlen (gcc_exec_prefix);
case 'S':
case 'c':
+ case 'E':
if (p[1] == 0)
{
have_c = 1;
{
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)
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:
/* Set up the search paths. We add directories that we expect to
contain GNU Toolchain components before directories specified by
the machine description so that we will find GNU components (like
- the GNU assembler) before those of the host system. */
+ the GNU assembler) before those of the host system. */
/* If we don't know where the toolchain has been installed, use the
configured-in locations. */
}
else
{
+ const char *p = strrchr (argv[i], '@');
+ char *fname;
+ long offset;
+ int consumed;
#ifdef HAVE_TARGET_OBJECT_SUFFIX
argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
#endif
-
- if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
+ /* For LTO static archive support we handle input file
+ specifications that are composed of a filename and
+ an offset like FNAME@OFFSET. */
+ if (p
+ && p != argv[i]
+ && sscanf (p, "@%li%n", &offset, &consumed) >= 1
+ && strlen (p) == (unsigned int)consumed)
{
- perror_with_name (argv[i]);
- error_count++;
+ fname = (char *)xmalloc (p - argv[i] + 1);
+ memcpy (fname, argv[i], p - argv[i]);
+ fname[p - argv[i]] = '\0';
+ /* Only accept non-stdin and existing FNAME parts, otherwise
+ try with the full name. */
+ if (strcmp (fname, "-") == 0 || access (fname, F_OK) < 0)
+ {
+ free (fname);
+ fname = xstrdup (argv[i]);
+ }
}
else
- {
- infiles[n_infiles].language = spec_lang;
- infiles[n_infiles++].name = argv[i];
- }
+ fname = xstrdup (argv[i]);
+
+ 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];
+ }
+
+ free (fname);
}
}
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, '\'')))
static void
do_self_spec (const char *spec)
{
+ int i;
+
do_spec_2 (spec);
do_spec_1 (" ", 0, NULL);
+ /* Mark %<S switches processed by do_self_spec to be ignored permanently.
+ do_self_specs adds the replacements to switches array, so it shouldn't
+ be processed afterwards. */
+ for (i = 0; i < n_switches; i++)
+ if ((switches[i].live_cond & SWITCH_IGNORE))
+ switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY;
+
if (argbuf_index > 0)
{
- int i;
-
switches = XRESIZEVEC (struct switchstr, switches,
n_switches + argbuf_index + 1);
buf = (char *) alloca (p - q + 1);
strncpy (buf, q, p - q);
buf[p - q] = 0;
- error ("%s", buf);
+ error ("%s", _(buf));
return -1;
}
break;
buf = (char *) alloca (p - q + 1);
strncpy (buf, q, p - q);
buf[p - q] = 0;
- notice ("%s\n", buf);
+ notice ("%s\n", _(buf));
if (*p)
p++;
}
if (atom == end_atom)
{
if (!n_way_choice || disj_matched || *p == '|'
- || a_is_negated || a_is_suffix || a_is_spectype
+ || a_is_negated || a_is_suffix || a_is_spectype
|| a_is_starred)
goto invalid;
if (switches[switchnum].live_cond != 0)
return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
&& (switches[switchnum].live_cond & SWITCH_FALSE) == 0
- && (switches[switchnum].live_cond & SWITCH_IGNORE) == 0);
+ && (switches[switchnum].live_cond & SWITCH_IGNORE_PERMANENTLY)
+ == 0);
/* In the common case of {<at-most-one-letter>*}, a negating
switch would always match, so ignore that case. We will just
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);
else if (*cross_compile == '0')
{
add_prefix (&startfile_prefixes,
- concat (gcc_exec_prefix
- ? gcc_exec_prefix : standard_exec_prefix,
- machine_suffix,
+ concat (gcc_exec_prefix
+ ? gcc_exec_prefix : standard_exec_prefix,
+ machine_suffix,
standard_startfile_prefix, NULL),
NULL, PREFIX_PRIORITY_LAST, 0, 1);
}
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++)
{
printf (_("%s %s%s\n"), programname, pkgversion_string,
version_string);
- printf ("Copyright %s 2009 Free Software Foundation, Inc.\n",
+ printf ("Copyright %s 2010 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"),
}
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)
{
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"))
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);
ptr[0] = '\\';
ptr[1] = *value++;
}
-
+
strcpy (ptr, argv[1]);
-
+
return result;
}