PR47785: Add support for handling Xassembler/Wa options with LTO.
2020-02-24 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> Kugan Vivekandarajah <kugan.vivekanandarajah@linaro.org> PR driver/47785 * gcc.c (putenv_COLLECT_AS_OPTIONS): New function. (driver::main): Call putenv_COLLECT_AS_OPTIONS. * opts-common.c (parse_options_from_collect_gcc_options): New function. (prepend_xassembler_to_collect_as_options): Likewise. * opts.h (parse_options_from_collect_gcc_options): Declare prototype. (prepend_xassembler_to_collect_as_options): Likewise. * lto-opts.c (lto_write_options): Stream assembler options in COLLECT_AS_OPTIONS. * lto-wrapper.c (xassembler_options_error): New static variable. (get_options_from_collect_gcc_options): Move parsing options code to parse_options_from_collect_gcc_options and call it. (merge_and_complain): Validate -Xassembler options. (append_compiler_options): Handle OPT_Xassembler. (run_gcc): Append command line -Xassembler options to collect_gcc_options. * doc/invoke.texi: Add documentation about using Xassembler options with LTO. testsuite/ * gcc.target/arm/pr78353-1.c: New test. * gcc.target/arm/pr78353-2.c: Likewise.
This commit is contained in:
parent
9069e9484c
commit
f1a681a174
10 changed files with 230 additions and 32 deletions
|
@ -1,3 +1,25 @@
|
|||
2020-02-24 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
|
||||
Kugan Vivekandarajah <kugan.vivekanandarajah@linaro.org>
|
||||
|
||||
PR driver/47785
|
||||
* gcc.c (putenv_COLLECT_AS_OPTIONS): New function.
|
||||
(driver::main): Call putenv_COLLECT_AS_OPTIONS.
|
||||
* opts-common.c (parse_options_from_collect_gcc_options): New function.
|
||||
(prepend_xassembler_to_collect_as_options): Likewise.
|
||||
* opts.h (parse_options_from_collect_gcc_options): Declare prototype.
|
||||
(prepend_xassembler_to_collect_as_options): Likewise.
|
||||
* lto-opts.c (lto_write_options): Stream assembler options
|
||||
in COLLECT_AS_OPTIONS.
|
||||
* lto-wrapper.c (xassembler_options_error): New static variable.
|
||||
(get_options_from_collect_gcc_options): Move parsing options code to
|
||||
parse_options_from_collect_gcc_options and call it.
|
||||
(merge_and_complain): Validate -Xassembler options.
|
||||
(append_compiler_options): Handle OPT_Xassembler.
|
||||
(run_gcc): Append command line -Xassembler options to
|
||||
collect_gcc_options.
|
||||
* doc/invoke.texi: Add documentation about using Xassembler
|
||||
options with LTO.
|
||||
|
||||
2020-02-24 Kito Cheng <kito.cheng@sifive.com>
|
||||
|
||||
* config/riscv/riscv.c (riscv_emit_float_compare): Change the code gen
|
||||
|
|
|
@ -11159,6 +11159,12 @@ conflicting translation units. Specifically
|
|||
precedence; and for example @option{-ffp-contract=off} takes precedence
|
||||
over @option{-ffp-contract=fast}. You can override them at link time.
|
||||
|
||||
When you need to pass options to the assembler via @option{-Wa} or
|
||||
@option{-Xassembler} make sure to either compile such translation
|
||||
units with @option{-fno-lto} or consistently use the same assembler
|
||||
options on all translation units. You can alternatively also
|
||||
specify assembler options at LTO link time.
|
||||
|
||||
To enable debug info generation you need to supply @option{-g} at
|
||||
compile time. If any of the input files at link time were built
|
||||
with debug info generation enabled the link will enable debug info
|
||||
|
|
29
gcc/gcc.c
29
gcc/gcc.c
|
@ -5242,6 +5242,34 @@ do_specs_vec (vec<char_p> vec)
|
|||
}
|
||||
}
|
||||
|
||||
/* Add options passed via -Xassembler or -Wa to COLLECT_AS_OPTIONS. */
|
||||
|
||||
static void
|
||||
putenv_COLLECT_AS_OPTIONS (vec<char_p> vec)
|
||||
{
|
||||
if (vec.is_empty ())
|
||||
return;
|
||||
|
||||
obstack_init (&collect_obstack);
|
||||
obstack_grow (&collect_obstack, "COLLECT_AS_OPTIONS=",
|
||||
strlen ("COLLECT_AS_OPTIONS="));
|
||||
|
||||
char *opt;
|
||||
unsigned ix;
|
||||
|
||||
FOR_EACH_VEC_ELT (vec, ix, opt)
|
||||
{
|
||||
obstack_1grow (&collect_obstack, '\'');
|
||||
obstack_grow (&collect_obstack, opt, strlen (opt));
|
||||
obstack_1grow (&collect_obstack, '\'');
|
||||
if (ix < vec.length () - 1)
|
||||
obstack_1grow(&collect_obstack, ' ');
|
||||
}
|
||||
|
||||
obstack_1grow (&collect_obstack, '\0');
|
||||
xputenv (XOBFINISH (&collect_obstack, char *));
|
||||
}
|
||||
|
||||
/* Process the sub-spec SPEC as a portion of a larger spec.
|
||||
This is like processing a whole spec except that we do
|
||||
not initialize at the beginning and we do not supply a
|
||||
|
@ -7363,6 +7391,7 @@ driver::main (int argc, char **argv)
|
|||
global_initializations ();
|
||||
build_multilib_strings ();
|
||||
set_up_specs ();
|
||||
putenv_COLLECT_AS_OPTIONS (assembler_options);
|
||||
putenv_COLLECT_GCC (argv[0]);
|
||||
maybe_putenv_COLLECT_LTO_WRAPPER ();
|
||||
maybe_putenv_OFFLOAD_TARGETS ();
|
||||
|
|
|
@ -163,6 +163,12 @@ lto_write_options (void)
|
|||
append_to_collect_gcc_options (&temporary_obstack, &first_p,
|
||||
option->canonical_option[j]);
|
||||
}
|
||||
|
||||
const char *collect_as_options = getenv ("COLLECT_AS_OPTIONS");
|
||||
if (collect_as_options)
|
||||
prepend_xassembler_to_collect_as_options (collect_as_options,
|
||||
&temporary_obstack);
|
||||
|
||||
obstack_grow (&temporary_obstack, "\0", 1);
|
||||
args = XOBFINISH (&temporary_obstack, char *);
|
||||
lto_write_data (args, strlen (args) + 1);
|
||||
|
|
|
@ -73,6 +73,7 @@ static char *offload_objects_file_name;
|
|||
static char *makefile;
|
||||
static unsigned int num_deb_objs;
|
||||
static const char **early_debug_object_names;
|
||||
static bool xassembler_options_error = false;
|
||||
|
||||
const char tool_name[] = "lto-wrapper";
|
||||
|
||||
|
@ -137,42 +138,14 @@ get_options_from_collect_gcc_options (const char *collect_gcc,
|
|||
unsigned int *decoded_options_count)
|
||||
{
|
||||
struct obstack argv_obstack;
|
||||
char *argv_storage;
|
||||
const char **argv;
|
||||
int j, k, argc;
|
||||
int argc;
|
||||
|
||||
argv_storage = xstrdup (collect_gcc_options);
|
||||
obstack_init (&argv_obstack);
|
||||
obstack_ptr_grow (&argv_obstack, collect_gcc);
|
||||
|
||||
for (j = 0, k = 0; argv_storage[j] != '\0'; ++j)
|
||||
{
|
||||
if (argv_storage[j] == '\'')
|
||||
{
|
||||
obstack_ptr_grow (&argv_obstack, &argv_storage[k]);
|
||||
++j;
|
||||
do
|
||||
{
|
||||
if (argv_storage[j] == '\0')
|
||||
fatal_error (input_location,
|
||||
"malformed %<COLLECT_GCC_OPTIONS%>");
|
||||
else if (strncmp (&argv_storage[j], "'\\''", 4) == 0)
|
||||
{
|
||||
argv_storage[k++] = '\'';
|
||||
j += 4;
|
||||
}
|
||||
else if (argv_storage[j] == '\'')
|
||||
break;
|
||||
else
|
||||
argv_storage[k++] = argv_storage[j++];
|
||||
}
|
||||
while (1);
|
||||
argv_storage[k++] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
obstack_ptr_grow (&argv_obstack, NULL);
|
||||
argc = obstack_object_size (&argv_obstack) / sizeof (void *) - 1;
|
||||
parse_options_from_collect_gcc_options (collect_gcc_options,
|
||||
&argv_obstack, &argc);
|
||||
argv = XOBFINISH (&argv_obstack, const char **);
|
||||
|
||||
decode_cmdline_options_to_array (argc, (const char **)argv, CL_DRIVER,
|
||||
|
@ -512,6 +485,45 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
|
|||
}
|
||||
else
|
||||
j++;
|
||||
|
||||
if (!xassembler_options_error)
|
||||
for (i = j = 0; ; i++, j++)
|
||||
{
|
||||
for (; i < *decoded_options_count; i++)
|
||||
if ((*decoded_options)[i].opt_index == OPT_Xassembler)
|
||||
break;
|
||||
|
||||
for (; j < fdecoded_options_count; j++)
|
||||
if (fdecoded_options[j].opt_index == OPT_Xassembler)
|
||||
break;
|
||||
|
||||
if (i == *decoded_options_count && j == fdecoded_options_count)
|
||||
break;
|
||||
else if (i < *decoded_options_count && j == fdecoded_options_count)
|
||||
{
|
||||
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.",
|
||||
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.",
|
||||
(*decoded_options)[i].arg, fdecoded_options[j].arg);
|
||||
xassembler_options_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Auxiliary function that frees elements of PTR and PTR itself.
|
||||
|
@ -626,6 +638,13 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
|
|||
case OPT_Os:
|
||||
break;
|
||||
|
||||
case OPT_Xassembler:
|
||||
/* When we detected a mismatch in assembler options between
|
||||
the input TU's fall back to previous behavior of ignoring them. */
|
||||
if (xassembler_options_error)
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!(cl_options[option->opt_index].flags & CL_TARGET))
|
||||
continue;
|
||||
|
@ -1251,7 +1270,8 @@ run_gcc (unsigned argc, char *argv[])
|
|||
const char **argv_ptr;
|
||||
char *list_option_full = NULL;
|
||||
const char *linker_output = NULL;
|
||||
const char *collect_gcc, *collect_gcc_options;
|
||||
const char *collect_gcc;
|
||||
char *collect_gcc_options;
|
||||
int parallel = 0;
|
||||
int jobserver = 0;
|
||||
int auto_parallel = 0;
|
||||
|
@ -1281,6 +1301,25 @@ run_gcc (unsigned argc, char *argv[])
|
|||
if (!collect_gcc_options)
|
||||
fatal_error (input_location,
|
||||
"environment variable %<COLLECT_GCC_OPTIONS%> must be set");
|
||||
|
||||
char *collect_as_options = getenv ("COLLECT_AS_OPTIONS");
|
||||
|
||||
/* Prepend -Xassembler to each option, and append the string
|
||||
to collect_gcc_options. */
|
||||
if (collect_as_options)
|
||||
{
|
||||
obstack temporary_obstack;
|
||||
obstack_init (&temporary_obstack);
|
||||
|
||||
prepend_xassembler_to_collect_as_options (collect_as_options,
|
||||
&temporary_obstack);
|
||||
obstack_1grow (&temporary_obstack, '\0');
|
||||
|
||||
char *xassembler_opts_string
|
||||
= XOBFINISH (&temporary_obstack, char *);
|
||||
strcat (collect_gcc_options, xassembler_opts_string);
|
||||
}
|
||||
|
||||
get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
|
||||
&decoded_options,
|
||||
&decoded_options_count);
|
||||
|
|
|
@ -1739,3 +1739,69 @@ control_warning_option (unsigned int opt_index, int kind, const char *arg,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse options in COLLECT_GCC_OPTIONS and push them on ARGV_OBSTACK.
|
||||
Store number of arguments into ARGC_P. */
|
||||
|
||||
void
|
||||
parse_options_from_collect_gcc_options (const char *collect_gcc_options,
|
||||
obstack *argv_obstack,
|
||||
int *argc_p)
|
||||
{
|
||||
char *argv_storage = xstrdup (collect_gcc_options);
|
||||
int j, k;
|
||||
|
||||
for (j = 0, k = 0; argv_storage[j] != '\0'; ++j)
|
||||
{
|
||||
if (argv_storage[j] == '\'')
|
||||
{
|
||||
obstack_ptr_grow (argv_obstack, &argv_storage[k]);
|
||||
++j;
|
||||
do
|
||||
{
|
||||
if (argv_storage[j] == '\0')
|
||||
fatal_error (input_location,
|
||||
"malformed %<COLLECT_GCC_OPTIONS%>");
|
||||
else if (strncmp (&argv_storage[j], "'\\''", 4) == 0)
|
||||
{
|
||||
argv_storage[k++] = '\'';
|
||||
j += 4;
|
||||
}
|
||||
else if (argv_storage[j] == '\'')
|
||||
break;
|
||||
else
|
||||
argv_storage[k++] = argv_storage[j++];
|
||||
}
|
||||
while (1);
|
||||
argv_storage[k++] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
obstack_ptr_grow (argv_obstack, NULL);
|
||||
*argc_p = obstack_object_size (argv_obstack) / sizeof (void *) - 1;
|
||||
}
|
||||
|
||||
/* Prepend -Xassembler for each option in COLLECT_AS_OPTIONS,
|
||||
and push on O. */
|
||||
|
||||
void prepend_xassembler_to_collect_as_options (const char *collect_as_options,
|
||||
obstack *o)
|
||||
{
|
||||
obstack opts_obstack;
|
||||
int opts_count;
|
||||
|
||||
obstack_init (&opts_obstack);
|
||||
parse_options_from_collect_gcc_options (collect_as_options,
|
||||
&opts_obstack, &opts_count);
|
||||
const char **assembler_opts = XOBFINISH (&opts_obstack, const char **);
|
||||
|
||||
for (int i = 0; i < opts_count; i++)
|
||||
{
|
||||
obstack_grow (o, " '-Xassembler' ",
|
||||
strlen (" '-Xassembler' "));
|
||||
const char *opt = assembler_opts[i];
|
||||
obstack_1grow (o, '\'');
|
||||
obstack_grow (o, opt, strlen (opt));
|
||||
obstack_1grow (o, '\'');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -460,6 +460,11 @@ extern bool parse_and_check_align_values (const char *flag,
|
|||
bool report_error,
|
||||
location_t loc);
|
||||
|
||||
extern void parse_options_from_collect_gcc_options (const char *, obstack *,
|
||||
int *);
|
||||
|
||||
extern void prepend_xassembler_to_collect_as_options (const char *, obstack *);
|
||||
|
||||
/* Set OPTION in OPTS to VALUE if the option is not set in OPTS_SET. */
|
||||
|
||||
#define SET_OPTION_IF_UNSET(OPTS, OPTS_SET, OPTION, VALUE) \
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2020-02-24 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
|
||||
Kugan Vivekandarajah <kugan.vivekanandarajah@linaro.org>
|
||||
|
||||
PR driver/47785
|
||||
PR lto/78353
|
||||
* gcc.target/arm/pr78353-1.c: New test.
|
||||
* gcc.target/arm/pr78353-2.c: Likewise.
|
||||
|
||||
2020-02-23 Thomas Koenig <tkoenig@gcc.gnu.org>
|
||||
|
||||
PR fortran/93890
|
||||
|
|
8
gcc/testsuite/gcc.target/arm/pr78353-1.c
Normal file
8
gcc/testsuite/gcc.target/arm/pr78353-1.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* { dg-do link } */
|
||||
/* { dg-options "-march=armv7-a -mthumb -O2 -flto -Wa,-mimplicit-it=always" } */
|
||||
|
||||
int main(int x)
|
||||
{
|
||||
asm("teq %0, #0; addne %0, %0, #1" : "=r" (x));
|
||||
return x;
|
||||
}
|
9
gcc/testsuite/gcc.target/arm/pr78353-2.c
Normal file
9
gcc/testsuite/gcc.target/arm/pr78353-2.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* { dg-do link } */
|
||||
/* { dg-options "-march=armv7-a -mthumb -O2 -flto -Wa,-mimplicit-it=always,-mthumb" } */
|
||||
|
||||
int main(int x)
|
||||
{
|
||||
asm("teq %0, #0; addne %0, %0, #1" : "=r" (x));
|
||||
return x;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue