From f1a681a174cdfb82e62c246d6f4add9a25fc2e43 Mon Sep 17 00:00:00 2001 From: Prathamesh Kulkarni Date: Mon, 24 Feb 2020 11:55:45 +0530 Subject: [PATCH] PR47785: Add support for handling Xassembler/Wa options with LTO. 2020-02-24 Prathamesh Kulkarni Kugan Vivekandarajah 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. --- gcc/ChangeLog | 22 +++++ gcc/doc/invoke.texi | 6 ++ gcc/gcc.c | 29 +++++++ gcc/lto-opts.c | 6 ++ gcc/lto-wrapper.c | 103 ++++++++++++++++------- gcc/opts-common.c | 66 +++++++++++++++ gcc/opts.h | 5 ++ gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/gcc.target/arm/pr78353-1.c | 8 ++ gcc/testsuite/gcc.target/arm/pr78353-2.c | 9 ++ 10 files changed, 230 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr78353-1.c create mode 100644 gcc/testsuite/gcc.target/arm/pr78353-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 49986c0e10d..b5fc309ce84 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2020-02-24 Prathamesh Kulkarni + Kugan Vivekandarajah + + 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 * config/riscv/riscv.c (riscv_emit_float_compare): Change the code gen diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 54017dfce8f..d4fe9a4d9d4 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 diff --git a/gcc/gcc.c b/gcc/gcc.c index effc384f3ef..9f790db0daf 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -5242,6 +5242,34 @@ do_specs_vec (vec vec) } } +/* Add options passed via -Xassembler or -Wa to COLLECT_AS_OPTIONS. */ + +static void +putenv_COLLECT_AS_OPTIONS (vec 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 (); diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c index 90bfde5a8fd..87e916a2741 100644 --- a/gcc/lto-opts.c +++ b/gcc/lto-opts.c @@ -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); diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index fe8f292f877..6e3f294257e 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -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 %"); - 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 % 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); diff --git a/gcc/opts-common.c b/gcc/opts-common.c index 112de159cce..de9510abd64 100644 --- a/gcc/opts-common.c +++ b/gcc/opts-common.c @@ -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 %"); + 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, '\''); + } +} diff --git a/gcc/opts.h b/gcc/opts.h index c6ad6c70464..8f594b46e33 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -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) \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 06d61c7e2ee..13c1a132cc1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2020-02-24 Prathamesh Kulkarni + Kugan Vivekandarajah + + 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 PR fortran/93890 diff --git a/gcc/testsuite/gcc.target/arm/pr78353-1.c b/gcc/testsuite/gcc.target/arm/pr78353-1.c new file mode 100644 index 00000000000..aec0fb0cbfd --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr78353-1.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/arm/pr78353-2.c b/gcc/testsuite/gcc.target/arm/pr78353-2.c new file mode 100644 index 00000000000..18a90e8834e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr78353-2.c @@ -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; +} + -- 2.30.2