On 4/29/21 2:22 PM, Richard Biener wrote:
On Wed, Apr 21, 2021 at 11:12 AM Martin Liška <mli...@suse.cz> wrote:

Now living in the 21st century, we don't longer need using the following tuple:
cl_decoded_option **decoded_options,
  unsigned int *decoded_options_count)
but we can rather use a standard (our) vector.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin

gcc/ChangeLog:

         * lto-wrapper.c (get_options_from_collect_gcc_options): Change
         return type.
         (append_option): Remove.
         (find_option): Rework to use the vector type.
         (remove_option): Remove.
         (merge_and_complain): Use vectors for cl_decoded_option data
         type arguments.
         (append_compiler_options): Likewise.
         (append_diag_options): Likewise.
         (append_linker_options): Likewise.
         (append_offload_options): Likewise.
         (compile_offload_image): Likewise.
         (compile_images_for_offload_targets): Likewise.
         (find_and_merge_options): Likewise.
         (run_gcc): Likewise.
---
  gcc/lto-wrapper.c | 384 ++++++++++++++++++++--------------------------
  1 file changed, 165 insertions(+), 219 deletions(-)

diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 03a5922f8ea..5ccf729b249 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -138,12 +138,12 @@ maybe_unlink (const char *file)
  /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
     environment.  */

-static void
+static vec<cl_decoded_option>

bonus points for handling ownership transfer via returning an
auto_vec<> (not sure if possible, but maybe it is).

Heh, about the bonus points: changing return type of 
get_options_from_collect_gcc_options to auto_vec<...>
leads to:

==26737== Invalid read of size 4

==26737==    at 0x406969: length (vec.h:589)

==26737==    by 0x406969: length (vec.h:1439)

==26737==    by 0x406969: append_compiler_options(obstack*, vec<cl_decoded_option, 
va_heap, vl_ptr>) (lto-wrapper.c:649)

==26737==    by 0x408E35: run_gcc(unsigned int, char**) (lto-wrapper.c:1470)

==26737==    by 0x406565: main (lto-wrapper.c:2070)

==26737==  Address 0x57838a4 is 4 bytes inside a block of size 1,152 free'd

==26737==    at 0x483FEC0: free (vg_replace_malloc.c:755)

==26737==    by 0x4078B5: release<cl_decoded_option> (vec.h:316)

==26737==    by 0x4078B5: release (vec.h:1832)

==26737==    by 0x4078B5: ~auto_vec (vec.h:1552)

==26737==    by 0x4078B5: find_and_merge_options(int, long, char const*, 
vec<cl_decoded_option, va_heap, vl_ptr>, vec<cl_decoded_option, va_heap, 
vl_ptr>*, char const*) (lto-wrapper.c:1100)

==26737==    by 0x408D0E: run_gcc(unsigned int, char**) (lto-wrapper.c:1454)

==26737==    by 0x406565: main (lto-wrapper.c:2070)

==26737==  Block was alloc'd at

==26737==    at 0x483D70F: malloc (vg_replace_malloc.c:380)

==26737==    by 0x49554F: xrealloc (xmalloc.c:177)

==26737==    by 0x4076CC: reserve<cl_decoded_option> (vec.h:290)

==26737==    by 0x4076CC: reserve (vec.h:1778)

==26737==    by 0x4076CC: reserve_exact (vec.h:1798)

==26737==    by 0x4076CC: create (vec.h:1813)

==26737==    by 0x4076CC: get_options_from_collect_gcc_options(char const*, 
char const*) (lto-wrapper.c:162)

==26737==    by 0x4078FC: find_and_merge_options(int, long, char const*, 
vec<cl_decoded_option, va_heap, vl_ptr>, vec<cl_decoded_option, va_heap, 
vl_ptr>*, char const*) (lto-wrapper.c:1100)

==26737==    by 0x408D0E: run_gcc(unsigned int, char**) (lto-wrapper.c:1454)

==26737==    by 0x406565: main (lto-wrapper.c:2070)



  get_options_from_collect_gcc_options (const char *collect_gcc,
-                                     const char *collect_gcc_options,
-                                     struct cl_decoded_option 
**decoded_options,
-                                     unsigned int *decoded_options_count)
+                                     const char *collect_gcc_options)
  {
+  cl_decoded_option *decoded_options;
+  unsigned int decoded_options_count;
    struct obstack argv_obstack;
    const char **argv;
    int argc;
@@ -156,57 +156,49 @@ get_options_from_collect_gcc_options (const char 
*collect_gcc,
    argv = XOBFINISH (&argv_obstack, const char **);

    decode_cmdline_options_to_array (argc, (const char **)argv, CL_DRIVER,
-                                  decoded_options, decoded_options_count);
+                                  &decoded_options, &decoded_options_count);
+  vec<cl_decoded_option> decoded;
+  decoded.create (decoded_options_count);
+  for (unsigned i = 0; i < decoded_options_count; ++i)
+    decoded.quick_push (decoded_options[i]);
+  free (decoded_options);
+
    obstack_free (&argv_obstack, NULL);
+
+  return decoded;
  }

-/* Append OPTION to the options array DECODED_OPTIONS with size
-   DECODED_OPTIONS_COUNT.  */
+/* Find option in OPTIONS based on OPT_INDEX.  NULL value is returned
+   if the option is not present.  */

-static void
-append_option (struct cl_decoded_option **decoded_options,
-              unsigned int *decoded_options_count,
-              struct cl_decoded_option *option)
+static cl_decoded_option *
+find_option (vec<cl_decoded_option> &options, size_t opt_index)
  {
-  ++*decoded_options_count;
-  *decoded_options
-    = (struct cl_decoded_option *)
-       xrealloc (*decoded_options,
-                 (*decoded_options_count
-                  * sizeof (struct cl_decoded_option)));
-  memcpy (&(*decoded_options)[*decoded_options_count - 1], option,
-         sizeof (struct cl_decoded_option));
-}
+  for (unsigned i = 0; i < options.length (); ++i)
+    if (options[i].opt_index == opt_index)
+      return &options[i];

You're returning a pointer into the vector here...

-/* Remove option number INDEX from DECODED_OPTIONS, update
-   DECODED_OPTIONS_COUNT.  */
+  return NULL;
+}

-static void
-remove_option (struct cl_decoded_option **decoded_options,
-              int index, unsigned int *decoded_options_count)
+static cl_decoded_option *
+find_option (vec<cl_decoded_option> &options, cl_decoded_option *option)
  {
-  --*decoded_options_count;
-  memmove (&(*decoded_options)[index + 1],
-          &(*decoded_options)[index],
-          sizeof (struct cl_decoded_option)
-          * (*decoded_options_count - index));
+  return find_option (options, option->opt_index);
  }

  /* Try to merge and complain about options FDECODED_OPTIONS when applied
     ontop of DECODED_OPTIONS.  */

  static void
-merge_and_complain (struct cl_decoded_option **decoded_options,
-                   unsigned int *decoded_options_count,
-                   struct cl_decoded_option *fdecoded_options,
-                   unsigned int fdecoded_options_count,
-                   struct cl_decoded_option *decoded_cl_options,
-                   unsigned int decoded_cl_options_count)
+merge_and_complain (vec<cl_decoded_option> decoded_options,
+                   vec<cl_decoded_option> fdecoded_options,
+                   vec<cl_decoded_option> decoded_cl_options)
  {
    unsigned int i, j;
-  struct cl_decoded_option *pic_option = NULL;
-  struct cl_decoded_option *pie_option = NULL;
-  struct cl_decoded_option *cf_protection_option = NULL;
+  cl_decoded_option *pic_option = NULL;
+  cl_decoded_option *pie_option = NULL;
+  cl_decoded_option *cf_protection_option = NULL;

    /* ???  Merge options from files.  Most cases can be
       handled by either unioning or intersecting
@@ -223,9 +215,9 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,

    /* Look for a -fcf-protection option in the link-time options
       which overrides any -fcf-protection from the lto sections.  */
-  for (i = 0; i < decoded_cl_options_count; ++i)
+  for (i = 0; i < decoded_cl_options.length (); ++i)
      {
-      struct cl_decoded_option *foption = &decoded_cl_options[i];
+      cl_decoded_option *foption = &decoded_cl_options[i];
        if (foption->opt_index == OPT_fcf_protection_)
         {
           cf_protection_option = foption;
@@ -234,9 +226,10 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,

    /* The following does what the old LTO option code did,
       union all target and a selected set of common options.  */
-  for (i = 0; i < fdecoded_options_count; ++i)
+  for (i = 0; i < fdecoded_options.length (); ++i)
      {
-      struct cl_decoded_option *foption = &fdecoded_options[i];
+      cl_decoded_option *foption = &fdecoded_options[i];
+      cl_decoded_option *existing_opt = find_option (decoded_options, foption);
        switch (foption->opt_index)
         {
         case OPT_SPECIAL_unknown:
@@ -264,11 +257,8 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
              setting per OPT code, we pick the first we encounter.
              ???  This doesn't make too much sense, but when it doesn't
              then we should complain.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
+         if (existing_opt == NULL)
+           decoded_options.safe_push (*foption);

and you end up re-allocating that here.  That's an eventually dangerous
pattern ... please consider to instead returning an index from find()
(and -1 for not found or so).

You are right. I've done that in the patch and it survives regression tests.
May I install it? The auto_vec can be done incrementally I guess.

Martin


           break;

         /* Figure out what PIC/PIE level wins and merge the results.  */
@@ -284,25 +274,19 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
         case OPT_fopenmp:
         case OPT_fopenacc:
           /* For selected options we can merge conservatively.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
+         if (existing_opt == NULL)
+           decoded_options.safe_push (*foption);
           /* -fopenmp > -fno-openmp,
              -fopenacc > -fno-openacc  */
-         else if (foption->value > (*decoded_options)[j].value)
-           (*decoded_options)[j] = *foption;
+         else if (foption->value > existing_opt->value)
+           *existing_opt = *foption;
           break;

         case OPT_fopenacc_dim_:
           /* Append or check identical.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if (strcmp ((*decoded_options)[j].arg, foption->arg))
+         if (existing_opt == NULL)
+           decoded_options.safe_push (*foption);
+         else if (strcmp (existing_opt->arg, foption->arg))
             fatal_error (input_location,
                          "option %s with different values",
                          foption->orig_option_with_args_text);
@@ -313,12 +297,9 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
           if (!cf_protection_option
               || cf_protection_option->value == CF_CHECK)
             {
-             for (j = 0; j < *decoded_options_count; ++j)
-               if ((*decoded_options)[j].opt_index == foption->opt_index)
-                 break;
-             if (j == *decoded_options_count)
-               append_option (decoded_options, decoded_options_count, foption);
-             else if ((*decoded_options)[j].value != foption->value)
+             if (existing_opt == NULL)
+               decoded_options.safe_push (*foption);
+             else if (existing_opt->value != foption->value)
                 {
                   if (cf_protection_option
                       && cf_protection_option->value == CF_CHECK)
@@ -326,22 +307,21 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
                                  "option %qs with mismatching values"
                                  " (%s, %s)",
                                  "-fcf-protection",
-                                (*decoded_options)[j].arg, foption->arg);
+                                existing_opt->arg, foption->arg);
                   else
                     {
                       /* Merge and update the -fcf-protection option.  */
-                     (*decoded_options)[j].value &= (foption->value
-                                                     & CF_FULL);
-                     switch ((*decoded_options)[j].value)
+                     existing_opt->value &= (foption->value & CF_FULL);
+                     switch (existing_opt->value)
                         {
                         case CF_NONE:
-                         (*decoded_options)[j].arg = "none";
+                         existing_opt->arg = "none";
                           break;
                         case CF_BRANCH:
-                         (*decoded_options)[j].arg = "branch";
+                         existing_opt->arg = "branch";
                           break;
                         case CF_RETURN:
-                         (*decoded_options)[j].arg = "return";
+                         existing_opt->arg = "return";
                           break;
                         default:
                           gcc_unreachable ();
@@ -355,15 +335,19 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
         case OPT_Ofast:
         case OPT_Og:
         case OPT_Os:
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == OPT_O
-               || (*decoded_options)[j].opt_index == OPT_Ofast
-               || (*decoded_options)[j].opt_index == OPT_Og
-               || (*decoded_options)[j].opt_index == OPT_Os)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if ((*decoded_options)[j].opt_index == foption->opt_index
+         existing_opt = NULL;
+         for (j = 0; j < decoded_options.length (); ++j)
+           if (decoded_options[j].opt_index == OPT_O
+               || decoded_options[j].opt_index == OPT_Ofast
+               || decoded_options[j].opt_index == OPT_Og
+               || decoded_options[j].opt_index == OPT_Os)
+             {
+               existing_opt = &decoded_options[j];
+               break;
+             }
+         if (existing_opt == NULL)
+           decoded_options.safe_push (*foption);
+         else if (existing_opt->opt_index == foption->opt_index
                    && foption->opt_index != OPT_O)
             /* Exact same options get merged.  */
             ;
@@ -393,13 +377,13 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
                 default:
                   gcc_unreachable ();
                 }
-             switch ((*decoded_options)[j].opt_index)
+             switch (existing_opt->opt_index)
                 {
                 case OPT_O:
-                 if ((*decoded_options)[j].arg[0] == '\0')
+                 if (existing_opt->arg[0] == '\0')
                     level = MAX (level, 1);
                   else
-                   level = MAX (level, atoi ((*decoded_options)[j].arg));
+                   level = MAX (level, atoi (existing_opt->arg));
                   break;
                 case OPT_Ofast:
                   level = MAX (level, 3);
@@ -413,23 +397,20 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
                 default:
                   gcc_unreachable ();
                 }
-             (*decoded_options)[j].opt_index = OPT_O;
+             existing_opt->opt_index = OPT_O;
               char *tem;
               tem = xasprintf ("-O%d", level);
-             (*decoded_options)[j].arg = &tem[2];
-             (*decoded_options)[j].canonical_option[0] = tem;
-             (*decoded_options)[j].value = 1;
+             existing_opt->arg = &tem[2];
+             existing_opt->canonical_option[0] = tem;
+             existing_opt->value = 1;
             }
           break;


         case OPT_foffload_abi_:
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if (foption->value != (*decoded_options)[j].value)
+         if (existing_opt == NULL)
+           decoded_options.safe_push (*foption);
+         else if (foption->value != existing_opt->value)
             fatal_error (input_location,
                          "option %s not used consistently in all LTO input"
                          " files", foption->orig_option_with_args_text);
@@ -437,7 +418,7 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,


         case OPT_foffload_:
-         append_option (decoded_options, decoded_options_count, foption);
+         decoded_options.safe_push (*foption);
           break;
         }
      }
@@ -457,12 +438,12 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
       It would be good to warn on mismatches, but it is bit hard to do as
       we do not know what nothing translates to.  */

-  for (unsigned int j = 0; j < *decoded_options_count;)
-    if ((*decoded_options)[j].opt_index == OPT_fPIC
-        || (*decoded_options)[j].opt_index == OPT_fpic)
+  for (unsigned int j = 0; j < decoded_options.length ();)
+    if (decoded_options[j].opt_index == OPT_fPIC
+       || decoded_options[j].opt_index == OPT_fpic)
        {
         /* -fno-pic in one unit implies -fno-pic everywhere.  */
-       if ((*decoded_options)[j].value == 0)
+       if (decoded_options[j].value == 0)
           j++;
         /* If we have no pic option or merge in -fno-pic, we still may turn
            existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present.  */
@@ -471,41 +452,41 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
           {
             if (pie_option)
               {
-               bool big = (*decoded_options)[j].opt_index == OPT_fPIC
+               bool big = decoded_options[j].opt_index == OPT_fPIC
                            && pie_option->opt_index == OPT_fPIE;
-               (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie;
+               decoded_options[j].opt_index = big ? OPT_fPIE : OPT_fpie;
                 if (pie_option->value)
-                 (*decoded_options)[j].canonical_option[0]
+                 decoded_options[j].canonical_option[0]
                     = big ? "-fPIE" : "-fpie";
                 else
-                 (*decoded_options)[j].canonical_option[0] = "-fno-pie";
-               (*decoded_options)[j].value = pie_option->value;
-               j++;
+                 decoded_options[j].canonical_option[0] = "-fno-pie";
+               decoded_options[j].value = pie_option->value;
+               j++;
               }
             else if (pic_option)
               {
-               (*decoded_options)[j] = *pic_option;
-               j++;
+               decoded_options[j] = *pic_option;
+               j++;
               }
             /* We do not know if target defaults to pic or not, so just remove
                option if it is missing in one unit but enabled in other.  */
             else
-             remove_option (decoded_options, j, decoded_options_count);
+             decoded_options.ordered_remove (j);
           }
         else if (pic_option->opt_index == OPT_fpic
-                && (*decoded_options)[j].opt_index == OPT_fPIC)
+                && decoded_options[j].opt_index == OPT_fPIC)
           {
-           (*decoded_options)[j] = *pic_option;
+           decoded_options[j] = *pic_option;
             j++;
           }
         else
           j++;
        }
-   else if ((*decoded_options)[j].opt_index == OPT_fPIE
-            || (*decoded_options)[j].opt_index == OPT_fpie)
+   else if (decoded_options[j].opt_index == OPT_fPIE
+           || decoded_options[j].opt_index == OPT_fpie)
        {
         /* -fno-pie in one unit implies -fno-pie everywhere.  */
-       if ((*decoded_options)[j].value == 0)
+       if (decoded_options[j].value == 0)
           j++;
         /* If we have no pie option or merge in -fno-pie, we still preserve
            PIE/pie if pic/PIC is present.  */
@@ -516,32 +497,32 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
             if (pic_option)
               {
                 if (pic_option->opt_index == OPT_fpic
-                   && (*decoded_options)[j].opt_index == OPT_fPIE)
+                   && decoded_options[j].opt_index == OPT_fPIE)
                   {
-                   (*decoded_options)[j].opt_index = OPT_fpie;
-                   (*decoded_options)[j].canonical_option[0]
+                   decoded_options[j].opt_index = OPT_fpie;
+                   decoded_options[j].canonical_option[0]
                       = pic_option->value ? "-fpie" : "-fno-pie";
                   }
                 else if (!pic_option->value)
-                 (*decoded_options)[j].canonical_option[0] = "-fno-pie";
-               (*decoded_options)[j].value = pic_option->value;
+                 decoded_options[j].canonical_option[0] = "-fno-pie";
+               decoded_options[j].value = pic_option->value;
                 j++;
               }
             else if (pie_option)
               {
-               (*decoded_options)[j] = *pie_option;
+               decoded_options[j] = *pie_option;
                 j++;
               }
             /* Because we always append pic/PIE options this code path should
                not happen unless the LTO object was built by old lto1 which
                did not contain that logic yet.  */
             else
-             remove_option (decoded_options, j, decoded_options_count);
+             decoded_options.ordered_remove (j);
           }
         else if (pie_option->opt_index == OPT_fpie
-                && (*decoded_options)[j].opt_index == OPT_fPIE)
+                && decoded_options[j].opt_index == OPT_fPIE)
           {
-           (*decoded_options)[j] = *pie_option;
+           decoded_options[j] = *pie_option;
             j++;
           }
         else
@@ -553,37 +534,34 @@ merge_and_complain (struct cl_decoded_option 
**decoded_options,
    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;
+       cl_decoded_option *existing_opt
+         = find_option (decoded_options, OPT_Xassembler);
+       cl_decoded_option *existing_opt2
+         = find_option (fdecoded_options, OPT_Xassembler);

-       if (i == *decoded_options_count && j == fdecoded_options_count)
+       if (existing_opt == NULL && existing_opt2 == NULL)
           break;
-       else if (i < *decoded_options_count && j == fdecoded_options_count)
+       else if (existing_opt != NULL && existing_opt2 == NULL)
           {
             warning (0, "Extra option to %<-Xassembler%>: %s,"
                      " dropping all %<-Xassembler%> and %<-Wa%> options.",
-                    (*decoded_options)[i].arg);
+                    existing_opt->arg);
             xassembler_options_error = true;
             break;
           }
-       else if (i == *decoded_options_count && j < fdecoded_options_count)
+       else if (existing_opt == NULL && existing_opt2 != NULL)
           {
             warning (0, "Extra option to %<-Xassembler%>: %s,"
                      " dropping all %<-Xassembler%> and %<-Wa%> options.",
-                    fdecoded_options[j].arg);
+                    existing_opt2->arg);
             xassembler_options_error = true;
             break;
           }
-       else if (strcmp ((*decoded_options)[i].arg, fdecoded_options[j].arg))
+       else if (strcmp (existing_opt->arg, existing_opt2->arg) != 0)
           {
             warning (0, "Options to %<-Xassembler%> do not match: %s, %s,"
                      " dropping all %<-Xassembler%> and %<-Wa%> options.",
-                    (*decoded_options)[i].arg, fdecoded_options[j].arg);
+                    existing_opt->arg, existing_opt2->arg);
             xassembler_options_error = true;
             break;
           }
@@ -654,13 +632,12 @@ parse_env_var (const char *str, char ***pvalues, const 
char *append)
  /* Append options OPTS from lto or offload_lto sections to ARGV_OBSTACK.  */

  static void
-append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                        unsigned int count)
+append_compiler_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
  {
    /* Append compiler driver arguments as far as they were merged.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts.length (); ++j)
      {
-      struct cl_decoded_option *option = &opts[j];
+      cl_decoded_option *option = &opts[j];

        /* File options have been properly filtered by lto-opts.c.  */
        switch (option->opt_index)
@@ -721,16 +698,15 @@ append_compiler_options (obstack *argv_obstack, struct 
cl_decoded_option *opts,
      }
  }

-/* Append diag options in OPTS with length COUNT to ARGV_OBSTACK.  */
+/* Append diag options in OPTS to ARGV_OBSTACK.  */

  static void
-append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                    unsigned int count)
+append_diag_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
  {
    /* Append compiler driver arguments as far as they were merged.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts.length (); ++j)
      {
-      struct cl_decoded_option *option = &opts[j];
+      cl_decoded_option *option = &opts[j];

        switch (option->opt_index)
         {
@@ -757,14 +733,13 @@ append_diag_options (obstack *argv_obstack, struct 
cl_decoded_option *opts,
  /* Append linker options OPTS to ARGV_OBSTACK.  */

  static void
-append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                      unsigned int count)
+append_linker_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
  {
    /* Append linker driver arguments.  Compiler options from the linker
       driver arguments will override / merge with those from the compiler.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts.length (); ++j)
      {
-      struct cl_decoded_option *option = &opts[j];
+      cl_decoded_option *option = &opts[j];

        /* Do not pass on frontend specific flags not suitable for lto.  */
        if (!(cl_options[option->opt_index].flags
@@ -802,15 +777,14 @@ append_linker_options (obstack *argv_obstack, struct 
cl_decoded_option *opts,

  static void
  append_offload_options (obstack *argv_obstack, const char *target,
-                       struct cl_decoded_option *options,
-                       unsigned int options_count)
+                       vec<cl_decoded_option> options)
  {
-  for (unsigned i = 0; i < options_count; i++)
+  for (unsigned i = 0; i < options.length (); i++)
      {
        const char *cur, *next, *opts;
        char **argv;
        unsigned argc;
-      struct cl_decoded_option *option = &options[i];
+      cl_decoded_option *option = &options[i];

        if (option->opt_index != OPT_foffload_)
         continue;
@@ -882,10 +856,8 @@ access_check (const char *name, int mode)
  static char *
  compile_offload_image (const char *target, const char *compiler_path,
                        unsigned in_argc, char *in_argv[],
-                      struct cl_decoded_option *compiler_opts,
-                      unsigned int compiler_opt_count,
-                      struct cl_decoded_option *linker_opts,
-                      unsigned int linker_opt_count)
+                      vec<cl_decoded_option> compiler_opts,
+                      vec<cl_decoded_option> linker_opts)
  {
    char *filename = NULL;
    char *dumpbase;
@@ -935,19 +907,16 @@ compile_offload_image (const char *target, const char 
*compiler_path,
      obstack_ptr_grow (&argv_obstack, in_argv[i]);

    /* Append options from offload_lto sections.  */
-  append_compiler_options (&argv_obstack, compiler_opts,
-                          compiler_opt_count);
-  append_diag_options (&argv_obstack, linker_opts, linker_opt_count);
+  append_compiler_options (&argv_obstack, compiler_opts);
+  append_diag_options (&argv_obstack, linker_opts);

    obstack_ptr_grow (&argv_obstack, "-dumpbase");
    obstack_ptr_grow (&argv_obstack, dumpbase);

    /* Append options specified by -foffload last.  In case of conflicting
       options we expect offload compiler to choose the latest.  */
-  append_offload_options (&argv_obstack, target, compiler_opts,
-                         compiler_opt_count);
-  append_offload_options (&argv_obstack, target, linker_opts,
-                         linker_opt_count);
+  append_offload_options (&argv_obstack, target, compiler_opts);
+  append_offload_options (&argv_obstack, target, linker_opts);

    obstack_ptr_grow (&argv_obstack, NULL);
    argv = XOBFINISH (&argv_obstack, char **);
@@ -966,10 +935,8 @@ compile_offload_image (const char *target, const char 
*compiler_path,

  static void
  compile_images_for_offload_targets (unsigned in_argc, char *in_argv[],
-                                   struct cl_decoded_option *compiler_opts,
-                                   unsigned int compiler_opt_count,
-                                   struct cl_decoded_option *linker_opts,
-                                   unsigned int linker_opt_count)
+                                   vec<cl_decoded_option> compiler_opts,
+                                   vec<cl_decoded_option> linker_opts)
  {
    char **names = NULL;
    const char *target_names = getenv (OFFLOAD_TARGET_NAMES_ENV);
@@ -988,8 +955,7 @@ compile_images_for_offload_targets (unsigned in_argc, char 
*in_argv[],
      {
        offload_names[i]
         = compile_offload_image (names[i], compiler_path, in_argc, in_argv,
-                                compiler_opts, compiler_opt_count,
-                                linker_opts, linker_opt_count);
+                                compiler_opts, linker_opts);
        if (!offload_names[i])
         fatal_error (input_location,
                      "problem with building target image for %s", names[i]);
@@ -1058,25 +1024,22 @@ find_crtoffloadtable (int save_temps, const char 
*dumppfx)
  }

  /* A subroutine of run_gcc.  Examine the open file FD for lto sections with
-   name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS
-   and OPT_COUNT.  Return true if we found a matching section, false
+   name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS.
+   Return true if we found a matching section, false
     otherwise.  COLLECT_GCC holds the value of the environment variable with
     the same name.  */

  static bool
  find_and_merge_options (int fd, off_t file_offset, const char *prefix,
-                       struct cl_decoded_option *decoded_cl_options,
-                       unsigned int decoded_cl_options_count,
-                       struct cl_decoded_option **opts,
-                       unsigned int *opt_count, const char *collect_gcc)
+                       vec<cl_decoded_option> decoded_cl_options,
+                       vec<cl_decoded_option> *opts, const char *collect_gcc)
  {
    off_t offset, length;
    char *data;
    char *fopts;
    const char *errmsg;
    int err;
-  struct cl_decoded_option *fdecoded_options = *opts;
-  unsigned int fdecoded_options_count = *opt_count;
+  vec<cl_decoded_option> fdecoded_options;

    simple_object_read *sobj;
    sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO",
@@ -1098,24 +1061,19 @@ find_and_merge_options (int fd, off_t file_offset, 
const char *prefix,
    data = (char *)xmalloc (length);
    read (fd, data, length);
    fopts = data;
+  bool first = true;
    do
      {
-      struct cl_decoded_option *f2decoded_options;
-      unsigned int f2decoded_options_count;
-      get_options_from_collect_gcc_options (collect_gcc, fopts,
-                                           &f2decoded_options,
-                                           &f2decoded_options_count);
-      if (!fdecoded_options)
-       {
-        fdecoded_options = f2decoded_options;
-        fdecoded_options_count = f2decoded_options_count;
-       }
+      vec<cl_decoded_option> f2decoded_options
+       = get_options_from_collect_gcc_options (collect_gcc, fopts);
+      if (first)
+       {
+         fdecoded_options = f2decoded_options;
+         first = false;
+       }
        else
-       merge_and_complain (&fdecoded_options,
-                           &fdecoded_options_count,
-                           f2decoded_options, f2decoded_options_count,
-                           decoded_cl_options,
-                           decoded_cl_options_count);
+       merge_and_complain (fdecoded_options, f2decoded_options,
+                           decoded_cl_options);

        fopts += strlen (fopts) + 1;
      }
@@ -1124,7 +1082,6 @@ find_and_merge_options (int fd, off_t file_offset, const 
char *prefix,
    free (data);
    simple_object_release_read (sobj);
    *opts = fdecoded_options;
-  *opt_count = fdecoded_options_count;
    return true;
  }

@@ -1371,12 +1328,9 @@ run_gcc (unsigned argc, char *argv[])
    int jobserver = 0;
    int auto_parallel = 0;
    bool no_partition = false;
-  struct cl_decoded_option *fdecoded_options = NULL;
-  struct cl_decoded_option *offload_fdecoded_options = NULL;
-  unsigned int fdecoded_options_count = 0;
-  unsigned int offload_fdecoded_options_count = 0;
-  struct cl_decoded_option *decoded_options;
-  unsigned int decoded_options_count;
+  vec<cl_decoded_option> fdecoded_options;
+  fdecoded_options.create (16);
+  vec<cl_decoded_option> offload_fdecoded_options = vNULL;
    struct obstack argv_obstack;
    int new_head_argc;
    bool have_lto = false;
@@ -1418,9 +1372,8 @@ run_gcc (unsigned argc, char *argv[])
                                     NULL);
      }

-  get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
-                                       &decoded_options,
-                                       &decoded_options_count);
+  vec<cl_decoded_option> decoded_options
+    = get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options);

    /* Allocate array for input object files with LTO IL,
       and for possible preceding arguments.  */
@@ -1470,8 +1423,7 @@ run_gcc (unsigned argc, char *argv[])
         }

        if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX,
-                                 decoded_options, decoded_options_count,
-                                 &fdecoded_options, &fdecoded_options_count,
+                                 decoded_options, &fdecoded_options,
                                   collect_gcc))
         {
           have_lto = true;
@@ -1486,14 +1438,13 @@ run_gcc (unsigned argc, char *argv[])
    obstack_ptr_grow (&argv_obstack, "-xlto");
    obstack_ptr_grow (&argv_obstack, "-c");

-  append_compiler_options (&argv_obstack, fdecoded_options,
-                          fdecoded_options_count);
-  append_linker_options (&argv_obstack, decoded_options, 
decoded_options_count);
+  append_compiler_options (&argv_obstack, fdecoded_options);
+  append_linker_options (&argv_obstack, decoded_options);

    /* Scan linker driver arguments for things that are of relevance to us.  */
-  for (j = 1; j < decoded_options_count; ++j)
+  for (j = 1; j < decoded_options.length (); ++j)
      {
-      struct cl_decoded_option *option = &decoded_options[j];
+      cl_decoded_option *option = &decoded_options[j];
        switch (option->opt_index)
         {
         case OPT_o:
@@ -1711,9 +1662,7 @@ cont1:
             fatal_error (input_location, "cannot open %s: %m", filename);
           if (!find_and_merge_options (fd, file_offset,
                                        OFFLOAD_SECTION_NAME_PREFIX,
-                                      decoded_options, decoded_options_count,
-                                      &offload_fdecoded_options,
-                                      &offload_fdecoded_options_count,
+                                      decoded_options, 
&offload_fdecoded_options,
                                        collect_gcc))
             fatal_error (input_location, "cannot read %s: %m", filename);
           close (fd);
@@ -1722,10 +1671,7 @@ cont1:
         }

        compile_images_for_offload_targets (num_offload_files, offload_argv,
-                                         offload_fdecoded_options,
-                                         offload_fdecoded_options_count,
-                                         decoded_options,
-                                         decoded_options_count);
+                                         offload_fdecoded_options, 
decoded_options);

        free_array_of_ptrs ((void **) offload_argv, num_offload_files);

--
2.31.1



>From 6bfa86b423fd8017a80fd12e609dfee15b0befbe Mon Sep 17 00:00:00 2001
From: Martin Liska <mli...@suse.cz>
Date: Fri, 12 Mar 2021 11:53:47 +0100
Subject: [PATCH] lto-wrapper: Use vec<cl_decoded_option> data type.

gcc/ChangeLog:

	* lto-wrapper.c (get_options_from_collect_gcc_options): Change
	return type.
	(append_option): Remove.
	(find_option): Rework to use the vector type.
	(remove_option): Remove.
	(merge_and_complain): Use vectors for cl_decoded_option data
	type arguments.
	(append_compiler_options): Likewise.
	(append_diag_options): Likewise.
	(append_linker_options): Likewise.
	(append_offload_options): Likewise.
	(compile_offload_image): Likewise.
	(compile_images_for_offload_targets): Likewise.
	(find_and_merge_options): Likewise.
	(run_gcc): Likewise.
---
 gcc/lto-wrapper.c | 396 +++++++++++++++++++++-------------------------
 1 file changed, 176 insertions(+), 220 deletions(-)

diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index d6be7f016bf..11d4d20c494 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -139,12 +139,12 @@ maybe_unlink (const char *file)
 /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
    environment.  */
 
-static void
+static vec<cl_decoded_option>
 get_options_from_collect_gcc_options (const char *collect_gcc,
-				      const char *collect_gcc_options,
-				      struct cl_decoded_option **decoded_options,
-				      unsigned int *decoded_options_count)
+				      const char *collect_gcc_options)
 {
+  cl_decoded_option *decoded_options;
+  unsigned int decoded_options_count;
   struct obstack argv_obstack;
   const char **argv;
   int argc;
@@ -157,57 +157,49 @@ get_options_from_collect_gcc_options (const char *collect_gcc,
   argv = XOBFINISH (&argv_obstack, const char **);
 
   decode_cmdline_options_to_array (argc, (const char **)argv, CL_DRIVER,
-				   decoded_options, decoded_options_count);
+				   &decoded_options, &decoded_options_count);
+  vec<cl_decoded_option> decoded;
+  decoded.create (decoded_options_count);
+  for (unsigned i = 0; i < decoded_options_count; ++i)
+    decoded.quick_push (decoded_options[i]);
+  free (decoded_options);
+
   obstack_free (&argv_obstack, NULL);
+
+  return decoded;
 }
 
-/* Append OPTION to the options array DECODED_OPTIONS with size
-   DECODED_OPTIONS_COUNT.  */
+/* Find option in OPTIONS based on OPT_INDEX.  -1 value is returned
+   if the option is not present.  */
 
-static void
-append_option (struct cl_decoded_option **decoded_options,
-	       unsigned int *decoded_options_count,
-	       struct cl_decoded_option *option)
+static int
+find_option (vec<cl_decoded_option> &options, size_t opt_index)
 {
-  ++*decoded_options_count;
-  *decoded_options
-    = (struct cl_decoded_option *)
-	xrealloc (*decoded_options,
-		  (*decoded_options_count
-		   * sizeof (struct cl_decoded_option)));
-  memcpy (&(*decoded_options)[*decoded_options_count - 1], option,
-	  sizeof (struct cl_decoded_option));
-}
+  for (unsigned i = 0; i < options.length (); ++i)
+    if (options[i].opt_index == opt_index)
+      return i;
 
-/* Remove option number INDEX from DECODED_OPTIONS, update
-   DECODED_OPTIONS_COUNT.  */
+  return -1;
+}
 
-static void
-remove_option (struct cl_decoded_option **decoded_options,
-	       int index, unsigned int *decoded_options_count)
+static int
+find_option (vec<cl_decoded_option> &options, cl_decoded_option *option)
 {
-  --*decoded_options_count;
-  memmove (&(*decoded_options)[index + 1],
-	   &(*decoded_options)[index],
-	   sizeof (struct cl_decoded_option)
-	   * (*decoded_options_count - index));
+  return find_option (options, option->opt_index);
 }
 
 /* Try to merge and complain about options FDECODED_OPTIONS when applied
    ontop of DECODED_OPTIONS.  */
 
 static void
-merge_and_complain (struct cl_decoded_option **decoded_options,
-		    unsigned int *decoded_options_count,
-		    struct cl_decoded_option *fdecoded_options,
-		    unsigned int fdecoded_options_count,
-		    struct cl_decoded_option *decoded_cl_options,
-		    unsigned int decoded_cl_options_count)
+merge_and_complain (vec<cl_decoded_option> decoded_options,
+		    vec<cl_decoded_option> fdecoded_options,
+		    vec<cl_decoded_option> decoded_cl_options)
 {
   unsigned int i, j;
-  struct cl_decoded_option *pic_option = NULL;
-  struct cl_decoded_option *pie_option = NULL;
-  struct cl_decoded_option *cf_protection_option = NULL;
+  cl_decoded_option *pic_option = NULL;
+  cl_decoded_option *pie_option = NULL;
+  cl_decoded_option *cf_protection_option = NULL;
 
   /* ???  Merge options from files.  Most cases can be
      handled by either unioning or intersecting
@@ -224,9 +216,9 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 
   /* Look for a -fcf-protection option in the link-time options
      which overrides any -fcf-protection from the lto sections.  */
-  for (i = 0; i < decoded_cl_options_count; ++i)
+  for (i = 0; i < decoded_cl_options.length (); ++i)
     {
-      struct cl_decoded_option *foption = &decoded_cl_options[i];
+      cl_decoded_option *foption = &decoded_cl_options[i];
       if (foption->opt_index == OPT_fcf_protection_)
 	{
 	  cf_protection_option = foption;
@@ -235,9 +227,10 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
   
   /* The following does what the old LTO option code did,
      union all target and a selected set of common options.  */
-  for (i = 0; i < fdecoded_options_count; ++i)
+  for (i = 0; i < fdecoded_options.length (); ++i)
     {
-      struct cl_decoded_option *foption = &fdecoded_options[i];
+      cl_decoded_option *foption = &fdecoded_options[i];
+      int existing_opt = find_option (decoded_options, foption);
       switch (foption->opt_index)
 	{
 	case OPT_SPECIAL_unknown:
@@ -265,11 +258,8 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 	     setting per OPT code, we pick the first we encounter.
 	     ???  This doesn't make too much sense, but when it doesn't
 	     then we should complain.  */
-	  for (j = 0; j < *decoded_options_count; ++j)
-	    if ((*decoded_options)[j].opt_index == foption->opt_index)
-	      break;
-	  if (j == *decoded_options_count)
-	    append_option (decoded_options, decoded_options_count, foption);
+	  if (existing_opt == -1)
+	    decoded_options.safe_push (*foption);
 	  break;
 
 	/* Figure out what PIC/PIE level wins and merge the results.  */
@@ -285,25 +275,19 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 	case OPT_fopenmp:
 	case OPT_fopenacc:
 	  /* For selected options we can merge conservatively.  */
-	  for (j = 0; j < *decoded_options_count; ++j)
-	    if ((*decoded_options)[j].opt_index == foption->opt_index)
-	      break;
-	  if (j == *decoded_options_count)
-	    append_option (decoded_options, decoded_options_count, foption);
+	  if (existing_opt == -1)
+	    decoded_options.safe_push (*foption);
 	  /* -fopenmp > -fno-openmp,
 	     -fopenacc > -fno-openacc  */
-	  else if (foption->value > (*decoded_options)[j].value)
-	    (*decoded_options)[j] = *foption;
+	  else if (foption->value > decoded_options[existing_opt].value)
+	    decoded_options[existing_opt] = *foption;
 	  break;
 
 	case OPT_fopenacc_dim_:
 	  /* Append or check identical.  */
-	  for (j = 0; j < *decoded_options_count; ++j)
-	    if ((*decoded_options)[j].opt_index == foption->opt_index)
-	      break;
-	  if (j == *decoded_options_count)
-	    append_option (decoded_options, decoded_options_count, foption);
-	  else if (strcmp ((*decoded_options)[j].arg, foption->arg))
+	  if (existing_opt == -1)
+	    decoded_options.safe_push (*foption);
+	  else if (strcmp (decoded_options[existing_opt].arg, foption->arg))
 	    fatal_error (input_location,
 			 "option %s with different values",
 			 foption->orig_option_with_args_text);
@@ -314,12 +298,9 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 	  if (!cf_protection_option
 	      || cf_protection_option->value == CF_CHECK)
 	    {
-	      for (j = 0; j < *decoded_options_count; ++j)
-		if ((*decoded_options)[j].opt_index == foption->opt_index)
-		  break;
-	      if (j == *decoded_options_count)
-		append_option (decoded_options, decoded_options_count, foption);
-	      else if ((*decoded_options)[j].value != foption->value)
+	      if (existing_opt == -1)
+		decoded_options.safe_push (*foption);
+	      else if (decoded_options[existing_opt].value != foption->value)
 		{
 		  if (cf_protection_option
 		      && cf_protection_option->value == CF_CHECK)
@@ -327,22 +308,23 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 				 "option %qs with mismatching values"
 				 " (%s, %s)",
 				 "-fcf-protection",
-				 (*decoded_options)[j].arg, foption->arg);
+				 decoded_options[existing_opt].arg,
+				 foption->arg);
 		  else
 		    {
 		      /* Merge and update the -fcf-protection option.  */
-		      (*decoded_options)[j].value &= (foption->value
-						      & CF_FULL);
-		      switch ((*decoded_options)[j].value)
+		      decoded_options[existing_opt].value
+			&= (foption->value & CF_FULL);
+		      switch (decoded_options[existing_opt].value)
 			{
 			case CF_NONE:
-			  (*decoded_options)[j].arg = "none";
+			  decoded_options[existing_opt].arg = "none";
 			  break;
 			case CF_BRANCH:
-			  (*decoded_options)[j].arg = "branch";
+			  decoded_options[existing_opt].arg = "branch";
 			  break;
 			case CF_RETURN:
-			  (*decoded_options)[j].arg = "return";
+			  decoded_options[existing_opt].arg = "return";
 			  break;
 			default:
 			  gcc_unreachable ();
@@ -356,15 +338,19 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 	case OPT_Ofast:
 	case OPT_Og:
 	case OPT_Os:
-	  for (j = 0; j < *decoded_options_count; ++j)
-	    if ((*decoded_options)[j].opt_index == OPT_O
-		|| (*decoded_options)[j].opt_index == OPT_Ofast
-		|| (*decoded_options)[j].opt_index == OPT_Og
-		|| (*decoded_options)[j].opt_index == OPT_Os)
-	      break;
-	  if (j == *decoded_options_count)
-	    append_option (decoded_options, decoded_options_count, foption);
-	  else if ((*decoded_options)[j].opt_index == foption->opt_index
+	  existing_opt = -1;
+	  for (j = 0; j < decoded_options.length (); ++j)
+	    if (decoded_options[j].opt_index == OPT_O
+		|| decoded_options[j].opt_index == OPT_Ofast
+		|| decoded_options[j].opt_index == OPT_Og
+		|| decoded_options[j].opt_index == OPT_Os)
+	      {
+		existing_opt = j;
+		break;
+	      }
+	  if (existing_opt == -1)
+	    decoded_options.safe_push (*foption);
+	  else if (decoded_options[existing_opt].opt_index == foption->opt_index
 		   && foption->opt_index != OPT_O)
 	    /* Exact same options get merged.  */
 	    ;
@@ -394,13 +380,14 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 		default:
 		  gcc_unreachable ();
 		}
-	      switch ((*decoded_options)[j].opt_index)
+	      switch (decoded_options[existing_opt].opt_index)
 		{
 		case OPT_O:
-		  if ((*decoded_options)[j].arg[0] == '\0')
+		  if (decoded_options[existing_opt].arg[0] == '\0')
 		    level = MAX (level, 1);
 		  else
-		    level = MAX (level, atoi ((*decoded_options)[j].arg));
+		    level = MAX (level,
+				 atoi (decoded_options[existing_opt].arg));
 		  break;
 		case OPT_Ofast:
 		  level = MAX (level, 3);
@@ -414,23 +401,20 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 		default:
 		  gcc_unreachable ();
 		}
-	      (*decoded_options)[j].opt_index = OPT_O;
+	      decoded_options[existing_opt].opt_index = OPT_O;
 	      char *tem;
 	      tem = xasprintf ("-O%d", level);
-	      (*decoded_options)[j].arg = &tem[2];
-	      (*decoded_options)[j].canonical_option[0] = tem;
-	      (*decoded_options)[j].value = 1;
+	      decoded_options[existing_opt].arg = &tem[2];
+	      decoded_options[existing_opt].canonical_option[0] = tem;
+	      decoded_options[existing_opt].value = 1;
 	    }
 	  break;
  
 
 	case OPT_foffload_abi_:
-	  for (j = 0; j < *decoded_options_count; ++j)
-	    if ((*decoded_options)[j].opt_index == foption->opt_index)
-	      break;
-	  if (j == *decoded_options_count)
-	    append_option (decoded_options, decoded_options_count, foption);
-	  else if (foption->value != (*decoded_options)[j].value)
+	  if (existing_opt == -1)
+	    decoded_options.safe_push (*foption);
+	  else if (foption->value != decoded_options[existing_opt].value)
 	    fatal_error (input_location,
 			 "option %s not used consistently in all LTO input"
 			 " files", foption->orig_option_with_args_text);
@@ -438,7 +422,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 
 
 	case OPT_foffload_:
-	  append_option (decoded_options, decoded_options_count, foption);
+	  decoded_options.safe_push (*foption);
 	  break;
 	}
     }
@@ -458,12 +442,12 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
      It would be good to warn on mismatches, but it is bit hard to do as
      we do not know what nothing translates to.  */
     
-  for (unsigned int j = 0; j < *decoded_options_count;)
-    if ((*decoded_options)[j].opt_index == OPT_fPIC
-        || (*decoded_options)[j].opt_index == OPT_fpic)
+  for (unsigned int j = 0; j < decoded_options.length ();)
+    if (decoded_options[j].opt_index == OPT_fPIC
+	|| decoded_options[j].opt_index == OPT_fpic)
       {
 	/* -fno-pic in one unit implies -fno-pic everywhere.  */
-	if ((*decoded_options)[j].value == 0)
+	if (decoded_options[j].value == 0)
 	  j++;
 	/* If we have no pic option or merge in -fno-pic, we still may turn
 	   existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present.  */
@@ -472,41 +456,41 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 	  {
 	    if (pie_option)
 	      {
-		bool big = (*decoded_options)[j].opt_index == OPT_fPIC
+		bool big = decoded_options[j].opt_index == OPT_fPIC
 			   && pie_option->opt_index == OPT_fPIE;
-	        (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie;
+		decoded_options[j].opt_index = big ? OPT_fPIE : OPT_fpie;
 		if (pie_option->value)
-	          (*decoded_options)[j].canonical_option[0]
+		  decoded_options[j].canonical_option[0]
 		    = big ? "-fPIE" : "-fpie";
 		else
-	          (*decoded_options)[j].canonical_option[0] = "-fno-pie";
-		(*decoded_options)[j].value = pie_option->value;
-	        j++;
+		  decoded_options[j].canonical_option[0] = "-fno-pie";
+		decoded_options[j].value = pie_option->value;
+		j++;
 	      }
 	    else if (pic_option)
 	      {
-	        (*decoded_options)[j] = *pic_option;
-	        j++;
+		decoded_options[j] = *pic_option;
+		j++;
 	      }
 	    /* We do not know if target defaults to pic or not, so just remove
 	       option if it is missing in one unit but enabled in other.  */
 	    else
-	      remove_option (decoded_options, j, decoded_options_count);
+	      decoded_options.ordered_remove (j);
 	  }
 	else if (pic_option->opt_index == OPT_fpic
-		 && (*decoded_options)[j].opt_index == OPT_fPIC)
+		 && decoded_options[j].opt_index == OPT_fPIC)
 	  {
-	    (*decoded_options)[j] = *pic_option;
+	    decoded_options[j] = *pic_option;
 	    j++;
 	  }
 	else
 	  j++;
       }
-   else if ((*decoded_options)[j].opt_index == OPT_fPIE
-            || (*decoded_options)[j].opt_index == OPT_fpie)
+   else if (decoded_options[j].opt_index == OPT_fPIE
+	    || decoded_options[j].opt_index == OPT_fpie)
       {
 	/* -fno-pie in one unit implies -fno-pie everywhere.  */
-	if ((*decoded_options)[j].value == 0)
+	if (decoded_options[j].value == 0)
 	  j++;
 	/* If we have no pie option or merge in -fno-pie, we still preserve
 	   PIE/pie if pic/PIC is present.  */
@@ -517,32 +501,32 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 	    if (pic_option)
 	      {
 		if (pic_option->opt_index == OPT_fpic
-		    && (*decoded_options)[j].opt_index == OPT_fPIE)
+		    && decoded_options[j].opt_index == OPT_fPIE)
 		  {
-	            (*decoded_options)[j].opt_index = OPT_fpie;
-	            (*decoded_options)[j].canonical_option[0]
+		    decoded_options[j].opt_index = OPT_fpie;
+		    decoded_options[j].canonical_option[0]
 		      = pic_option->value ? "-fpie" : "-fno-pie";
 		  }
 		else if (!pic_option->value)
-		  (*decoded_options)[j].canonical_option[0] = "-fno-pie";
-		(*decoded_options)[j].value = pic_option->value;
+		  decoded_options[j].canonical_option[0] = "-fno-pie";
+		decoded_options[j].value = pic_option->value;
 		j++;
 	      }
 	    else if (pie_option)
 	      {
-	        (*decoded_options)[j] = *pie_option;
+		decoded_options[j] = *pie_option;
 		j++;
 	      }
 	    /* Because we always append pic/PIE options this code path should
 	       not happen unless the LTO object was built by old lto1 which
 	       did not contain that logic yet.  */
 	    else
-	      remove_option (decoded_options, j, decoded_options_count);
+	      decoded_options.ordered_remove (j);
 	  }
 	else if (pie_option->opt_index == OPT_fpie
-		 && (*decoded_options)[j].opt_index == OPT_fPIE)
+		 && decoded_options[j].opt_index == OPT_fPIE)
 	  {
-	    (*decoded_options)[j] = *pie_option;
+	    decoded_options[j] = *pie_option;
 	    j++;
 	  }
 	else
@@ -554,37 +538,41 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
   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)
+	int existing_opt_index
+	  = find_option (decoded_options, OPT_Xassembler);
+	int existing_opt2_index
+	  = find_option (fdecoded_options, OPT_Xassembler);
+
+	cl_decoded_option *existing_opt = NULL;
+	cl_decoded_option *existing_opt2 = NULL;
+	if (existing_opt_index != -1)
+	  existing_opt = &decoded_options[existing_opt_index];
+	if (existing_opt2_index != -1)
+	  existing_opt2 = &fdecoded_options[existing_opt2_index];
+
+	if (existing_opt == NULL && existing_opt2 == NULL)
 	  break;
-	else if (i < *decoded_options_count && j == fdecoded_options_count)
+	else if (existing_opt != NULL && existing_opt2 == NULL)
 	  {
 	    warning (0, "Extra option to %<-Xassembler%>: %s,"
 		     " dropping all %<-Xassembler%> and %<-Wa%> options.",
-		     (*decoded_options)[i].arg);
+		     existing_opt->arg);
 	    xassembler_options_error = true;
 	    break;
 	  }
-	else if (i == *decoded_options_count && j < fdecoded_options_count)
+	else if (existing_opt == NULL && existing_opt2 != NULL)
 	  {
 	    warning (0, "Extra option to %<-Xassembler%>: %s,"
 		     " dropping all %<-Xassembler%> and %<-Wa%> options.",
-		     fdecoded_options[j].arg);
+		     existing_opt2->arg);
 	    xassembler_options_error = true;
 	    break;
 	  }
-	else if (strcmp ((*decoded_options)[i].arg, fdecoded_options[j].arg))
+	else if (strcmp (existing_opt->arg, existing_opt2->arg) != 0)
 	  {
 	    warning (0, "Options to %<-Xassembler%> do not match: %s, %s,"
 		     " dropping all %<-Xassembler%> and %<-Wa%> options.",
-		     (*decoded_options)[i].arg, fdecoded_options[j].arg);
+		     existing_opt->arg, existing_opt2->arg);
 	    xassembler_options_error = true;
 	    break;
 	  }
@@ -655,13 +643,12 @@ parse_env_var (const char *str, char ***pvalues, const char *append)
 /* Append options OPTS from lto or offload_lto sections to ARGV_OBSTACK.  */
 
 static void
-append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-			 unsigned int count)
+append_compiler_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
 {
   /* Append compiler driver arguments as far as they were merged.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts.length (); ++j)
     {
-      struct cl_decoded_option *option = &opts[j];
+      cl_decoded_option *option = &opts[j];
 
       /* File options have been properly filtered by lto-opts.c.  */
       switch (option->opt_index)
@@ -722,16 +709,15 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
     }
 }
 
-/* Append diag options in OPTS with length COUNT to ARGV_OBSTACK.  */
+/* Append diag options in OPTS to ARGV_OBSTACK.  */
 
 static void
-append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-		     unsigned int count)
+append_diag_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
 {
   /* Append compiler driver arguments as far as they were merged.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts.length (); ++j)
     {
-      struct cl_decoded_option *option = &opts[j];
+      cl_decoded_option *option = &opts[j];
 
       switch (option->opt_index)
 	{
@@ -758,14 +744,13 @@ append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts,
 /* Append linker options OPTS to ARGV_OBSTACK.  */
 
 static void
-append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-		       unsigned int count)
+append_linker_options (obstack *argv_obstack, vec<cl_decoded_option> opts)
 {
   /* Append linker driver arguments.  Compiler options from the linker
      driver arguments will override / merge with those from the compiler.  */
-  for (unsigned int j = 1; j < count; ++j)
+  for (unsigned int j = 1; j < opts.length (); ++j)
     {
-      struct cl_decoded_option *option = &opts[j];
+      cl_decoded_option *option = &opts[j];
 
       /* Do not pass on frontend specific flags not suitable for lto.  */
       if (!(cl_options[option->opt_index].flags
@@ -803,15 +788,14 @@ append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts,
 
 static void
 append_offload_options (obstack *argv_obstack, const char *target,
-			struct cl_decoded_option *options,
-			unsigned int options_count)
+			vec<cl_decoded_option> options)
 {
-  for (unsigned i = 0; i < options_count; i++)
+  for (unsigned i = 0; i < options.length (); i++)
     {
       const char *cur, *next, *opts;
       char **argv;
       unsigned argc;
-      struct cl_decoded_option *option = &options[i];
+      cl_decoded_option *option = &options[i];
 
       if (option->opt_index != OPT_foffload_)
 	continue;
@@ -883,10 +867,8 @@ access_check (const char *name, int mode)
 static char *
 compile_offload_image (const char *target, const char *compiler_path,
 		       unsigned in_argc, char *in_argv[],
-		       struct cl_decoded_option *compiler_opts,
-		       unsigned int compiler_opt_count,
-		       struct cl_decoded_option *linker_opts,
-		       unsigned int linker_opt_count)
+		       vec<cl_decoded_option> compiler_opts,
+		       vec<cl_decoded_option> linker_opts)
 {
   char *filename = NULL;
   char *dumpbase;
@@ -943,19 +925,16 @@ compile_offload_image (const char *target, const char *compiler_path,
     obstack_ptr_grow (&argv_obstack, in_argv[i]);
 
   /* Append options from offload_lto sections.  */
-  append_compiler_options (&argv_obstack, compiler_opts,
-			   compiler_opt_count);
-  append_diag_options (&argv_obstack, linker_opts, linker_opt_count);
+  append_compiler_options (&argv_obstack, compiler_opts);
+  append_diag_options (&argv_obstack, linker_opts);
 
   obstack_ptr_grow (&argv_obstack, "-dumpbase");
   obstack_ptr_grow (&argv_obstack, dumpbase);
 
   /* Append options specified by -foffload last.  In case of conflicting
      options we expect offload compiler to choose the latest.  */
-  append_offload_options (&argv_obstack, target, compiler_opts,
-			  compiler_opt_count);
-  append_offload_options (&argv_obstack, target, linker_opts,
-			  linker_opt_count);
+  append_offload_options (&argv_obstack, target, compiler_opts);
+  append_offload_options (&argv_obstack, target, linker_opts);
 
   obstack_ptr_grow (&argv_obstack, NULL);
   argv = XOBFINISH (&argv_obstack, char **);
@@ -974,10 +953,8 @@ compile_offload_image (const char *target, const char *compiler_path,
 
 static void
 compile_images_for_offload_targets (unsigned in_argc, char *in_argv[],
-				    struct cl_decoded_option *compiler_opts,
-				    unsigned int compiler_opt_count,
-				    struct cl_decoded_option *linker_opts,
-				    unsigned int linker_opt_count)
+				    vec<cl_decoded_option> compiler_opts,
+				    vec<cl_decoded_option> linker_opts)
 {
   char **names = NULL;
   const char *target_names = getenv (OFFLOAD_TARGET_NAMES_ENV);
@@ -997,8 +974,7 @@ compile_images_for_offload_targets (unsigned in_argc, char *in_argv[],
     {
       offload_names[next_name_entry]
 	= compile_offload_image (names[i], compiler_path, in_argc, in_argv,
-				 compiler_opts, compiler_opt_count,
-				 linker_opts, linker_opt_count);
+				 compiler_opts, linker_opts);
       if (!offload_names[next_name_entry])
 #if OFFLOAD_DEFAULTED
 	continue;
@@ -1080,25 +1056,22 @@ find_crtoffloadtable (int save_temps, const char *dumppfx)
 }
 
 /* A subroutine of run_gcc.  Examine the open file FD for lto sections with
-   name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS
-   and OPT_COUNT.  Return true if we found a matching section, false
+   name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS.
+   Return true if we found a matching section, false
    otherwise.  COLLECT_GCC holds the value of the environment variable with
    the same name.  */
 
 static bool
 find_and_merge_options (int fd, off_t file_offset, const char *prefix,
-			struct cl_decoded_option *decoded_cl_options,
-			unsigned int decoded_cl_options_count,
-			struct cl_decoded_option **opts,
-			unsigned int *opt_count, const char *collect_gcc)
+			vec<cl_decoded_option> decoded_cl_options,
+			vec<cl_decoded_option> *opts, const char *collect_gcc)
 {
   off_t offset, length;
   char *data;
   char *fopts;
   const char *errmsg;
   int err;
-  struct cl_decoded_option *fdecoded_options = *opts;
-  unsigned int fdecoded_options_count = *opt_count;
+  vec<cl_decoded_option> fdecoded_options;
 
   simple_object_read *sobj;
   sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO",
@@ -1120,24 +1093,19 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix,
   data = (char *)xmalloc (length);
   read (fd, data, length);
   fopts = data;
+  bool first = true;
   do
     {
-      struct cl_decoded_option *f2decoded_options;
-      unsigned int f2decoded_options_count;
-      get_options_from_collect_gcc_options (collect_gcc, fopts,
-					    &f2decoded_options,
-					    &f2decoded_options_count);
-      if (!fdecoded_options)
-       {
-	 fdecoded_options = f2decoded_options;
-	 fdecoded_options_count = f2decoded_options_count;
-       }
+      vec<cl_decoded_option> f2decoded_options
+	= get_options_from_collect_gcc_options (collect_gcc, fopts);
+      if (first)
+	{
+	  fdecoded_options = f2decoded_options;
+	  first = false;
+	}
       else
-	merge_and_complain (&fdecoded_options,
-			    &fdecoded_options_count,
-			    f2decoded_options, f2decoded_options_count,
-			    decoded_cl_options,
-			    decoded_cl_options_count);
+	merge_and_complain (fdecoded_options, f2decoded_options,
+			    decoded_cl_options);
 
       fopts += strlen (fopts) + 1;
     }
@@ -1146,7 +1114,6 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix,
   free (data);
   simple_object_release_read (sobj);
   *opts = fdecoded_options;
-  *opt_count = fdecoded_options_count;
   return true;
 }
 
@@ -1391,12 +1358,9 @@ run_gcc (unsigned argc, char *argv[])
   int jobserver = 0;
   int auto_parallel = 0;
   bool no_partition = false;
-  struct cl_decoded_option *fdecoded_options = NULL;
-  struct cl_decoded_option *offload_fdecoded_options = NULL;
-  unsigned int fdecoded_options_count = 0;
-  unsigned int offload_fdecoded_options_count = 0;
-  struct cl_decoded_option *decoded_options;
-  unsigned int decoded_options_count;
+  vec<cl_decoded_option> fdecoded_options;
+  fdecoded_options.create (16);
+  vec<cl_decoded_option> offload_fdecoded_options = vNULL;
   struct obstack argv_obstack;
   int new_head_argc;
   bool have_lto = false;
@@ -1438,9 +1402,8 @@ run_gcc (unsigned argc, char *argv[])
 				    NULL);
     }
 
-  get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
-					&decoded_options,
-					&decoded_options_count);
+  vec<cl_decoded_option> decoded_options
+    = get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options);
 
   /* Allocate array for input object files with LTO IL,
      and for possible preceding arguments.  */
@@ -1489,8 +1452,7 @@ run_gcc (unsigned argc, char *argv[])
 	}
 
       if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX,
-				  decoded_options, decoded_options_count,
-				  &fdecoded_options, &fdecoded_options_count,
+				  decoded_options, &fdecoded_options,
 				  collect_gcc))
 	{
 	  have_lto = true;
@@ -1505,14 +1467,13 @@ run_gcc (unsigned argc, char *argv[])
   obstack_ptr_grow (&argv_obstack, "-xlto");
   obstack_ptr_grow (&argv_obstack, "-c");
 
-  append_compiler_options (&argv_obstack, fdecoded_options,
-			   fdecoded_options_count);
-  append_linker_options (&argv_obstack, decoded_options, decoded_options_count);
+  append_compiler_options (&argv_obstack, fdecoded_options);
+  append_linker_options (&argv_obstack, decoded_options);
 
   /* Scan linker driver arguments for things that are of relevance to us.  */
-  for (j = 1; j < decoded_options_count; ++j)
+  for (j = 1; j < decoded_options.length (); ++j)
     {
-      struct cl_decoded_option *option = &decoded_options[j];
+      cl_decoded_option *option = &decoded_options[j];
       switch (option->opt_index)
 	{
 	case OPT_o:
@@ -1731,9 +1692,7 @@ cont1:
 	    fatal_error (input_location, "cannot open %s: %m", filename);
 	  if (!find_and_merge_options (fd, file_offset,
 				       OFFLOAD_SECTION_NAME_PREFIX,
-				       decoded_options, decoded_options_count,
-				       &offload_fdecoded_options,
-				       &offload_fdecoded_options_count,
+				       decoded_options, &offload_fdecoded_options,
 				       collect_gcc))
 	    fatal_error (input_location, "cannot read %s: %m", filename);
 	  close (fd);
@@ -1742,10 +1701,7 @@ cont1:
 	}
 
       compile_images_for_offload_targets (num_offload_files, offload_argv,
-					  offload_fdecoded_options,
-					  offload_fdecoded_options_count,
-					  decoded_options,
-					  decoded_options_count);
+					  offload_fdecoded_options, decoded_options);
 
       free_array_of_ptrs ((void **) offload_argv, num_offload_files);
 
-- 
2.31.1

Reply via email to