On Tue, 25 Oct 2011, Joseph S. Myers wrote:

> On Tue, 25 Oct 2011, Richard Guenther wrote:
> 
> > Joseph, does this look like a sensible use of the common
> > machinery?  Do we want the init from COLLECT_GCC_OPTIONS
> > in opts-common.c instead?
> 
> Certainly there should be a single function to process COLLECT_GCC_OPTIONS 
> into an array of strings, even if only this one place needs then to 
> convert them to logical options.  And that single function should actually 
> work properly with the quoting logic used in gcc.c to generate 
> COLLECT_GCC_OPTIONS - your code appears to ignore any possibility of '\'' 
> being used for single-quotes in strings, and collect2.c:extract_string, 
> which is rather closer to what I'd expect, fails to reset backquote to 0 
> after processing the \'.

Hm, yeah - the existing logic in lto-wrapper fails to properly handle
any escaping.  I'll see if I can come up with a reasonably clean
interface.

> Note that decode_cmdline_options_to_array expects the array to start with 
> argv[0], the program name (though it's OK to have NULL there).

Ah, ok - fixed.

I'm LTO-bootstrapping and testing the following and will go with
that for now.

Thanks,
Richard.

2011-10-25  Richard Guenther  <rguent...@suse.de>

        PR lto/41844
        * Makefile.in (lto-wrapper): Depend on and link against
        opts-common.o.
        (lto-wrapper.o): Depend on $(OPTS_H) and $(OPTIONS_H).
        * lto-wrapper.c (get_options_from_collect_gcc_options): New function.
        (run_gcc): Use it.  Filter out language specific options.

Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig        2011-10-25 16:07:41.000000000 +0200
--- gcc/Makefile.in     2011-10-25 16:14:18.000000000 +0200
*************** collect2-aix.o : collect2-aix.c $(CONFIG
*** 2069,2080 ****
  tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) 
coretypes.h $(TM_H) \
      $(OBSTACK_H) collect2.h intl.h $(DIAGNOSTIC_CORE_H)
  
! lto-wrapper$(exeext): lto-wrapper.o $(LIBDEPS)
!       +$(LINKER) $(ALL_COMPILERFLAGS) $(LDFLAGS) -o T$@ lto-wrapper.o $(LIBS)
        mv -f T$@ $@
  
  lto-wrapper.o: lto-wrapper.c $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h \
!       $(OBSTACK_H) $(DIAGNOSTIC_H)
  
  # Files used by all variants of C.
  c-family/c-common.o : c-family/c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h 
\
--- 2069,2081 ----
  tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) 
coretypes.h $(TM_H) \
      $(OBSTACK_H) collect2.h intl.h $(DIAGNOSTIC_CORE_H)
  
! lto-wrapper$(exeext): lto-wrapper.o ggc-none.o libcommon-target.a $(LIBDEPS)
!       +$(LINKER) $(ALL_COMPILERFLAGS) $(LDFLAGS) -o T$@ \
!           lto-wrapper.o ggc-none.o libcommon-target.a $(LIBS)
        mv -f T$@ $@
  
  lto-wrapper.o: lto-wrapper.c $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h \
!       $(OBSTACK_H) $(DIAGNOSTIC_H) $(OPTS_H) $(OPTIONS_H)
  
  # Files used by all variants of C.
  c-family/c-common.o : c-family/c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h 
\
Index: gcc/lto-wrapper.c
===================================================================
*** gcc/lto-wrapper.c.orig      2011-10-25 16:07:41.000000000 +0200
--- gcc/lto-wrapper.c   2011-10-26 10:00:50.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 43,48 ****
--- 43,50 ----
  #include "intl.h"
  #include "diagnostic.h"
  #include "obstack.h"
+ #include "opts.h"
+ #include "options.h"
  
  int debug;                            /* true if -save-temps.  */
  int verbose;                          /* true if -v.  */
*************** fork_execute (char **argv)
*** 280,285 ****
--- 282,333 ----
  /* Template of LTRANS dumpbase suffix.  */
  #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
  
+ /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
+    environment according to LANG_MASK.  */
+ 
+ static void
+ get_options_from_collect_gcc_options (const char *collect_gcc,
+                                     const char *collect_gcc_options,
+                                     unsigned int lang_mask,
+                                     struct cl_decoded_option 
**decoded_options,
+                                     unsigned int *decoded_options_count)
+ {
+   char *argv_storage;
+   const char **argv;
+   int i, j, argc;
+ 
+   /* Count arguments.  */
+   argc = 0;
+   for (j = 0; collect_gcc_options[j] != '\0'; ++j)
+     if (collect_gcc_options[j] == '\'')
+       ++argc;
+   if (argc % 2 != 0)
+     fatal ("malformed COLLECT_GCC_OPTIONS");
+ 
+   /* Copy the options to a argv-like array.  */
+   argc /= 2;
+   argv = (const char **) xmalloc ((argc + 2) * sizeof (char *));
+   argv[0] = collect_gcc;
+   argv_storage = xstrdup (collect_gcc_options);
+   for (i = 1, j = 0; argv_storage[j] != '\0'; ++j)
+     {
+       if (argv_storage[j] == '\'')
+       {
+         argv[i++] = &argv_storage[++j];
+         while (argv_storage[j] != '\'')
+           ++j;
+         argv_storage[j] = '\0';
+       }
+     }
+   argv[i] = NULL;
+ 
+   decode_cmdline_options_to_array (argc, (const char **)argv,
+                                  lang_mask,
+                                  decoded_options, decoded_options_count);
+   free (argv);
+ }
+ 
+ 
  /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. 
*/
  
  static void
*************** run_gcc (unsigned argc, char *argv[])
*** 290,388 ****
    const char **argv_ptr;
    char *list_option_full = NULL;
    const char *linker_output = NULL;
!   const char *collect_gcc_options, *collect_gcc;
    struct obstack env_obstack;
-   bool seen_o = false;
    int parallel = 0;
    int jobserver = 0;
    bool no_partition = false;
  
    /* Get the driver and options.  */
    collect_gcc = getenv ("COLLECT_GCC");
    if (!collect_gcc)
      fatal ("environment variable COLLECT_GCC must be set");
- 
-   /* Set the CFLAGS environment variable.  */
    collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
    if (!collect_gcc_options)
      fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
! 
!   /* Count arguments.  */
!   i = 0;
!   for (j = 0; collect_gcc_options[j] != '\0'; ++j)
!     if (collect_gcc_options[j] == '\'')
!       ++i;
! 
!   if (i % 2 != 0)
!     fatal ("malformed COLLECT_GCC_OPTIONS");
  
    /* Initalize the common arguments for the driver.  */
!   new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
    argv_ptr = new_argv;
    *argv_ptr++ = collect_gcc;
    *argv_ptr++ = "-xlto";
    *argv_ptr++ = "-c";
!   for (j = 0; collect_gcc_options[j] != '\0'; ++j)
!     if (collect_gcc_options[j] == '\'')
!       {
!       char *option;
  
!       ++j;
!       i = j;
!       while (collect_gcc_options[j] != '\'')
!         ++j;
! 
!       obstack_init (&env_obstack);
!       obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
!       obstack_1grow (&env_obstack, 0);
!       option = XOBFINISH (&env_obstack, char *);
!       if (seen_o)
!         {
!           linker_output = option;
!           seen_o = false;
!           continue;
!         }
  
!       /* If we see -o, skip it and skip and record its argument.  */
!       if (option[0] == '-' && option[1] == 'o')
!         {
!           if (option[2] == '\0')
!             seen_o = true;
!           else
!             linker_output = &option[2];
!           continue;
!         }
  
!       if (strcmp (option, "-save-temps") == 0)
          debug = 1;
!       if (strcmp (option, "-v") == 0)
          verbose = 1;
  
!       if (strcmp (option, "-flto-partition=none") == 0)
          no_partition = true;
!       /* We've handled these LTO options, do not pass them on.  */
!       if (strncmp (option, "-flto=", 6) == 0
!           || !strcmp (option, "-flto"))
!         {
!           lto_mode = LTO_MODE_WHOPR;
!           if (option[5] == '=')
!             {
!               if (!strcmp (option + 6, "jobserver"))
!                 {
!                   jobserver = 1;
!                   parallel = 1;
!                 }
!               else
!                 {
!                   parallel = atoi (option + 6);
!                   if (parallel <= 1)
!                     parallel = 0;
!                 }
!             }
!         }
!       else
!         *argv_ptr++ = option;
!       }
    if (no_partition)
      {
        lto_mode = LTO_MODE_LTO;
--- 338,425 ----
    const char **argv_ptr;
    char *list_option_full = NULL;
    const char *linker_output = NULL;
!   const char *collect_gcc, *collect_gcc_options;
    struct obstack env_obstack;
    int parallel = 0;
    int jobserver = 0;
    bool no_partition = false;
+   struct cl_decoded_option *decoded_options;
+   unsigned int decoded_options_count;
  
    /* Get the driver and options.  */
    collect_gcc = getenv ("COLLECT_GCC");
    if (!collect_gcc)
      fatal ("environment variable COLLECT_GCC must be set");
    collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
    if (!collect_gcc_options)
      fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
!   get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
!                                       CL_LANG_ALL,
!                                       &decoded_options,
!                                       &decoded_options_count);
  
    /* Initalize the common arguments for the driver.  */
!   new_argv = (const char **) xmalloc ((15 + decoded_options_count + argc)
!                                     * sizeof (char *));
    argv_ptr = new_argv;
    *argv_ptr++ = collect_gcc;
    *argv_ptr++ = "-xlto";
    *argv_ptr++ = "-c";
!   for (j = 1; j < decoded_options_count; ++j)
!     {
!       struct cl_decoded_option *option = &decoded_options[j];
  
!       /* Do not pass on frontend specific flags.  */
!       if (!(cl_options[option->opt_index].flags
!           & (CL_COMMON|CL_TARGET|CL_DRIVER)))
!       continue;
  
!       switch (option->opt_index)
!       {
!       case OPT_o:
!         linker_output = option->arg;
!         /* We generate new intermediate output, drop this arg.  */
!         continue;
  
!       case OPT_save_temps:
          debug = 1;
!         break;
! 
!       case OPT_v:
          verbose = 1;
+         break;
  
!       case OPT_flto_partition_none:
          no_partition = true;
!         break;
! 
!       case OPT_flto_:
!         if (strcmp (option->arg, "jobserver") == 0)
!           {
!             jobserver = 1;
!             parallel = 1;
!           }
!         else
!           {
!             parallel = atoi (option->arg);
!             if (parallel <= 1)
!               parallel = 0;
!           }
!         /* Fallthru.  */
! 
!       case OPT_flto:
!         lto_mode = LTO_MODE_WHOPR;
!         /* We've handled these LTO options, do not pass them on.  */
!         continue;
! 
!       default:
!         break;
!       }
! 
!       /* Pass the option on.  */
!       *argv_ptr++ = option->orig_option_with_args_text;
!     }
! 
    if (no_partition)
      {
        lto_mode = LTO_MODE_LTO;
*************** main (int argc, char *argv[])
*** 662,667 ****
--- 699,705 ----
    /* We may be called with all the arguments stored in some file and
       passed with @file.  Expand them into argv before processing.  */
    expandargv (&argc, &argv);
+ 
    run_gcc (argc, argv);
  
    return 0;

Reply via email to