On Fri, 15 Jan 2016, Ilya Verbin wrote:

> Hi!
> 
> Here is my attempt to fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68463
> 
> This patch does 2 things:
> 
> I) lto-plugin doesn't claim files which contain offload sections, but don't
> contain LTO sections.  Instead, it writes names of files with offloading to 
> the
> temporary file and passes it to lto-wrapper as -foffload-objects=/tmp/cc...
> The order of these files in the list is very important, because ld will link
> host objects (and therefore host tables) in the following order:
>   1. Non-LTO files before the first claimed LTO file;
>   2. LTO files, after WPA-partitioning-recompilation;
>   3. Non-LTO files after the first claimed LTO file.
> To get the correct matching between host and target tables, the offload 
> objects
> need to be reordered correspondingly before passing to the target compiler.

I think that's reasonable.

> II) The __offload_func_table, __offload_funcs_end, __offload_var_table,
> __offload_vars_end are now provided by the linker script, instead of
> crtoffload{begin,end}.o, this allows to surround all offload objects, even
> those that are not claimed by lto-plugin.
> Unfortunately it works only with ld, but doen't work with gold, because
> https://sourceware.org/bugzilla/show_bug.cgi?id=15373
> Any thoughts how to enable this linker script for gold?

The easiest way would probably to add this handling to the default
"linker script" in gold.  I don't see an easy way around requiring
changes to gold here - maybe dumping the default linker script from
bfd and injecting the rules with some scripting so you have a complete
script.  Though likely gold won't grok that result.

Really a question for Ian though.

> I used the following testcase:
> $ cat main.c
> void foo1 ();
> void foo2 ();
> void foo3 ();
> void foo4 ();
> 
> int main ()
> {
>   foo1 ();
>   foo2 ();
>   foo3 ();
>   foo4 ();
>   return 0;
> }
> 
> $ cat test.c
> #include <stdio.h>
> #include <omp.h>
> #define MAKE_FN_NAME(x) foo ## x
> #define FN_NAME(x) MAKE_FN_NAME(x)
> void FN_NAME(NUM) ()
> {
>   int x, d;
>   #pragma omp target map(from: x, d)
>     {
>       x = NUM;
>       d = omp_is_initial_device ();
>     }
>   printf ("%s:\t%s ()\tx = %d\n", d ? "HOST" : "TARGET", __FUNCTION__, x);
>   if (x != NUM)
>     printf ("--------^\n");
> }
> 
> $ gcc -DNUM=1 -c -flto test.c -o obj1.o
> $ gcc -DNUM=2 -c -fopenmp test.c -o obj2.o
> $ gcc -DNUM=3 -c test.c -o obj3.o
> $ gcc -DNUM=4 -c -flto -fopenmp test.c -o obj4.o
> $ gcc -c main.c -o main.o
> $ gcc -fopenmp obj1.o obj2.o obj3.o obj4.o main.o && ./a.out
> $ gcc -fopenmp obj2.o obj3.o obj4.o obj1.o main.o && ./a.out
> $ gcc -fopenmp obj3.o obj1.o obj2.o obj4.o main.o && ./a.out

Did you try linking an archive with both offload-but-no-LTO and
offload-and-LTO objects inside?

Thanks,
Richard.

> 
> gcc/
>       PR driver/68463
>       * config/i386/intelmic-mkoffload.c (generate_target_descr_file): Don't
>       define __offload_func_table and __offload_var_table.
>       (generate_target_offloadend_file): Remove function.
>       (prepare_target_image): Don't call generate_target_offloadend_file.
>       * lto-wrapper.c (offloadbegin, offloadend): Remove static vars.
>       (offload_objects_file_name): New static var.
>       (tool_cleanup): Remove offload_objects_file_name file.
>       (find_offloadbeginend): Rename to ...
>       (find_crtoffload): ... this.  Locate crtoffload.o instead of
>       crtoffloadbegin.o and crtoffloadend.o.
>       (run_gcc): Remove offload_argc and offload_argv.
>       Get offload_objects_file_name from -foffload-objects=... option.
>       Read names of object files with offload from this file, pass them to
>       compile_images_for_offload_targets.  Call find_crtoffload instead of
>       find_offloadbeginend.  Don't give offload files to the linker when LTO
>       is disabled, because now they're not claimed, therefore not discarded.
> libgcc/
>       PR driver/68463
>       * Makefile.in (crtoffloadbegin$(objext)): Remove rule.
>       (crtoffloadend$(objext)): Likewise.
>       (crtoffload$(objext), link-offload-tables.x): New rules.
>       * configure: Regenerate.
>       * configure.ac (extra_parts): Add link-offload-tables.x if offloading is
>       enabled, or if this is an accel compiler for intelmic.
>       * link-offload-tables.x: New file.
>       * offloadstuff.c: Do not define __offload_func_table,
>       __offload_var_table, __offload_funcs_end, __offload_vars_end.
> libgomp/
>       PR driver/68463
>       * Makefile.in: Regenerate.
>       * configure: Regenerate.
>       * configure.ac (link_offload_tables): New output variable.  Set to
>       "%Tlink-offload-tables.x" if offloading is enabled, or if this is an
>       accel compiler for intelmic.
>       * libgomp.spec.in (*link_gomp): Add @link_offload_tables@.
>       * testsuite/Makefile.in: Regenerate.
> lto-plugin/
>       PR driver/68463
>       * lto-plugin.c (offload_files): Replace with ...
>       (offload_files_1, offload_files_2, offload_files_3): ... this.
>       (num_offload_files): Replace with ...
>       (num_offload_files_1, num_offload_files_2, num_offload_files_3): ..this.
>       (free_2): Adjust accordingly.
>       (all_symbols_read_handler): Don't add offload files to lto_arg_ptr.
>       Don't call free_1 for offload_files.  Write names of object files with
>       offloading to the temporary file.  Add new option to lto_arg_ptr.
>       (claim_file_handler): Don't claim file if it contains offload sections
>       without LTO sections, add it to offload_files_1 or to offload_files_3.
>       Add files with offload and LTO sections to offload_files_2.
> 
> 
> diff --git a/gcc/config/i386/intelmic-mkoffload.c 
> b/gcc/config/i386/intelmic-mkoffload.c
> index 6a09641..82e94f1 100644
> --- a/gcc/config/i386/intelmic-mkoffload.c
> +++ b/gcc/config/i386/intelmic-mkoffload.c
> @@ -295,17 +295,12 @@ generate_target_descr_file (const char *target_compiler)
>      fatal_error (input_location, "cannot open '%s'", src_filename);
>  
>    fprintf (src_file,
> +        "/* These symbols are provided by the linker script.  */\n"
> +        "extern const void *const __offload_func_table[];\n"
>          "extern const void *const __offload_funcs_end[];\n"
> +        "extern const void *const __offload_var_table[];\n"
>          "extern const void *const __offload_vars_end[];\n\n"
>  
> -        "const void *const __offload_func_table[0]\n"
> -        "__attribute__ ((__used__, visibility (\"hidden\"),\n"
> -        "section (\".gnu.offload_funcs\"))) = { };\n\n"
> -
> -        "const void *const __offload_var_table[0]\n"
> -        "__attribute__ ((__used__, visibility (\"hidden\"),\n"
> -        "section (\".gnu.offload_vars\"))) = { };\n\n"
> -
>          "const void *const __OFFLOAD_TARGET_TABLE__[]\n"
>          "__attribute__ ((__used__, visibility (\"hidden\"))) = {\n"
>          "  &__offload_func_table, &__offload_funcs_end,\n"
> @@ -342,46 +337,6 @@ generate_target_descr_file (const char *target_compiler)
>    return obj_filename;
>  }
>  
> -/* Generates object file with __offload_*_end symbols for the target
> -   library.  */
> -static const char *
> -generate_target_offloadend_file (const char *target_compiler)
> -{
> -  const char *src_filename = make_temp_file ("_target_offloadend.c");
> -  const char *obj_filename = make_temp_file ("_target_offloadend.o");
> -  temp_files[num_temps++] = src_filename;
> -  temp_files[num_temps++] = obj_filename;
> -  FILE *src_file = fopen (src_filename, "w");
> -
> -  if (!src_file)
> -    fatal_error (input_location, "cannot open '%s'", src_filename);
> -
> -  fprintf (src_file,
> -        "const void *const __offload_funcs_end[0]\n"
> -        "__attribute__ ((__used__, visibility (\"hidden\"),\n"
> -        "section (\".gnu.offload_funcs\"))) = { };\n\n"
> -
> -        "const void *const __offload_vars_end[0]\n"
> -        "__attribute__ ((__used__, visibility (\"hidden\"),\n"
> -        "section (\".gnu.offload_vars\"))) = { };\n");
> -  fclose (src_file);
> -
> -  struct obstack argv_obstack;
> -  obstack_init (&argv_obstack);
> -  obstack_ptr_grow (&argv_obstack, target_compiler);
> -  if (save_temps)
> -    obstack_ptr_grow (&argv_obstack, "-save-temps");
> -  if (verbose)
> -    obstack_ptr_grow (&argv_obstack, "-v");
> -  obstack_ptr_grow (&argv_obstack, "-c");
> -  obstack_ptr_grow (&argv_obstack, "-shared");
> -  obstack_ptr_grow (&argv_obstack, "-fPIC");
> -  obstack_ptr_grow (&argv_obstack, src_filename);
> -  compile_for_target (&argv_obstack, obj_filename);
> -
> -  return obj_filename;
> -}
> -
>  /* Generates object file with the host side descriptor.  */
>  static const char *
>  generate_host_descr_file (const char *host_compiler)
> @@ -469,15 +424,10 @@ prepare_target_image (const char *target_compiler, int 
> argc, char **argv)
>  {
>    const char *target_descr_filename
>      = generate_target_descr_file (target_compiler);
> -  const char *target_offloadend_filename
> -    = generate_target_offloadend_file (target_compiler);
>  
>    char *opt1
>      = XALLOCAVEC (char, sizeof ("-Wl,") + strlen (target_descr_filename));
> -  char *opt2
> -    = XALLOCAVEC (char, sizeof ("-Wl,") + strlen 
> (target_offloadend_filename));
>    sprintf (opt1, "-Wl,%s", target_descr_filename);
> -  sprintf (opt2, "-Wl,%s", target_offloadend_filename);
>  
>    const char *target_so_filename = make_temp_file ("_offload_intelmic.so");
>    temp_files[num_temps++] = target_so_filename;
> @@ -501,7 +451,6 @@ prepare_target_image (const char *target_compiler, int 
> argc, char **argv)
>      }
>    if (!out_obj_filename)
>      fatal_error (input_location, "output file not specified");
> -  obstack_ptr_grow (&argv_obstack, opt2);
>    compile_for_target (&argv_obstack, target_so_filename);
>  
>    /* Run objcopy.  */
> diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
> index bedcb79..e1d7738 100644
> --- a/gcc/lto-wrapper.c
> +++ b/gcc/lto-wrapper.c
> @@ -69,7 +69,7 @@ static char **input_names;
>  static char **output_names;
>  static char **offload_names;
>  static unsigned num_offload_targets;
> -static const char *offloadbegin, *offloadend;
> +static char *offload_objects_file_name;
>  static char *makefile;
>  
>  const char tool_name[] = "lto-wrapper";
> @@ -85,6 +85,8 @@ tool_cleanup (bool)
>      maybe_unlink (ltrans_output_file);
>    if (flto_out)
>      maybe_unlink (flto_out);
> +  if (offload_objects_file_name)
> +    maybe_unlink (offload_objects_file_name);
>    if (makefile)
>      maybe_unlink (makefile);
>    for (i = 0; i < nr; ++i)
> @@ -788,42 +790,34 @@ copy_file (const char *dest, const char *src)
>      }
>  }
>  
> -/* Find the crtoffloadbegin.o and crtoffloadend.o files in LIBRARY_PATH, make
> -   copies and store the names of the copies in offloadbegin and offloadend.  
> */
> +/* Find the crtoffload.o file in LIBRARY_PATH, make copy and give its name to
> +   the linker.  */
>  
>  static void
> -find_offloadbeginend (void)
> +find_crtoffload (void)
>  {
>    char **paths = NULL;
> +  const char *crtoffload;
>    const char *library_path = getenv ("LIBRARY_PATH");
>    if (!library_path)
>      return;
> -  unsigned n_paths = parse_env_var (library_path, &paths, 
> "/crtoffloadbegin.o");
> +  unsigned n_paths = parse_env_var (library_path, &paths, "/crtoffload.o");
>  
>    unsigned i;
>    for (i = 0; i < n_paths; i++)
>      if (access_check (paths[i], R_OK) == 0)
>        {
> -     size_t len = strlen (paths[i]);
> -     char *tmp = xstrdup (paths[i]);
> -     strcpy (paths[i] + len - strlen ("begin.o"), "end.o");
> -     if (access_check (paths[i], R_OK) != 0)
> -       fatal_error (input_location,
> -                    "installation error, can't find crtoffloadend.o");
> -     /* The linker will delete the filenames we give it, so make
> -        copies.  */
> -     offloadbegin = make_temp_file (".o");
> -     offloadend = make_temp_file (".o");
> -     copy_file (offloadbegin, tmp);
> -     copy_file (offloadend, paths[i]);
> -     free (tmp);
> +     /* The linker will delete the filename we give it, so make a copy.  */
> +     crtoffload = make_temp_file (".crtoffload.o");
> +     copy_file (crtoffload, paths[i]);
>       break;
>        }
>    if (i == n_paths)
> -    fatal_error (input_location,
> -              "installation error, can't find crtoffloadbegin.o");
> +    fatal_error (input_location, "installation error, can't find 
> crtoffload.o");
>  
>    free_array_of_ptrs ((void **) paths, n_paths);
> +
> +  printf ("%s\n", crtoffload);
>  }
>  
>  /* A subroutine of run_gcc.  Examine the open file FD for lto sections with
> @@ -918,8 +912,8 @@ run_gcc (unsigned argc, char *argv[])
>    int new_head_argc;
>    bool have_lto = false;
>    bool have_offload = false;
> -  unsigned lto_argc = 0, offload_argc = 0;
> -  char **lto_argv, **offload_argv;
> +  unsigned lto_argc = 0;
> +  char **lto_argv;
>  
>    /* Get the driver and options.  */
>    collect_gcc = getenv ("COLLECT_GCC");
> @@ -935,10 +929,9 @@ run_gcc (unsigned argc, char *argv[])
>                                       &decoded_options,
>                                       &decoded_options_count);
>  
> -  /* Allocate arrays for input object files with LTO or offload IL,
> +  /* Allocate array for input object files with LTO IL,
>       and for possible preceding arguments.  */
>    lto_argv = XNEWVEC (char *, argc);
> -  offload_argv = XNEWVEC (char *, argc);
>  
>    /* Look at saved options in the IL files.  */
>    for (i = 1; i < argc; ++i)
> @@ -950,6 +943,15 @@ run_gcc (unsigned argc, char *argv[])
>        int consumed;
>        char *filename = argv[i];
>  
> +      if (strncmp (argv[i], "-foffload-objects=",
> +                sizeof ("-foffload-objects=") - 1) == 0)
> +     {
> +       have_offload = true;
> +       offload_objects_file_name
> +         = argv[i] + sizeof ("-foffload-objects=") - 1;
> +       continue;
> +     }
> +
>        if ((p = strrchr (argv[i], '@'))
>         && p != argv[i] 
>         && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
> @@ -974,15 +976,6 @@ run_gcc (unsigned argc, char *argv[])
>         have_lto = true;
>         lto_argv[lto_argc++] = argv[i];
>       }
> -
> -      if (find_and_merge_options (fd, file_offset, 
> OFFLOAD_SECTION_NAME_PREFIX,
> -                               &offload_fdecoded_options,
> -                               &offload_fdecoded_options_count, collect_gcc))
> -     {
> -       have_offload = true;
> -       offload_argv[offload_argc++] = argv[i];
> -     }
> -
>        close (fd);
>      }
>  
> @@ -1081,47 +1074,83 @@ run_gcc (unsigned argc, char *argv[])
>  
>    if (have_offload)
>      {
> -      compile_images_for_offload_targets (offload_argc, offload_argv,
> +      unsigned i, num_offload_files;
> +      char **offload_argv;
> +      FILE *f;
> +
> +      f = fopen (offload_objects_file_name, "r");
> +      if (f == NULL)
> +     fatal_error (input_location, "cannot open %s: %m",
> +                  offload_objects_file_name);
> +      if (fscanf (f, "%u ", &num_offload_files) != 1)
> +     fatal_error (input_location, "cannot read %s: %m",
> +                  offload_objects_file_name);
> +      offload_argv = XNEWVEC (char *, num_offload_files);
> +
> +      /* Read names of object files with offload.  */
> +      for (i = 0; i < num_offload_files; i++)
> +     {
> +       const unsigned piece = 32;
> +       char *buf, *filename = XNEWVEC (char, piece);
> +       size_t len;
> +
> +       buf = filename;
> +cont1:
> +       if (!fgets (buf, piece, f))
> +         break;
> +       len = strlen (filename);
> +       if (filename[len - 1] != '\n')
> +         {
> +           filename = XRESIZEVEC (char, filename, len + piece);
> +           buf = filename + len;
> +           goto cont1;
> +         }
> +       filename[len - 1] = '\0';
> +       offload_argv[i] = filename;
> +     }
> +      fclose (f);
> +      maybe_unlink (offload_objects_file_name);
> +      offload_objects_file_name = NULL;
> +
> +      /* Look at saved offload options in files.  */
> +      for (i = 0; i < num_offload_files; i++)
> +     {
> +       int fd;
> +       char *filename = offload_argv[i];
> +
> +       fd = open (filename, O_RDONLY | O_BINARY);
> +       if (fd == -1)
> +         fatal_error (input_location, "cannot open %s: %m", filename);
> +       if (!find_and_merge_options (fd, 0, OFFLOAD_SECTION_NAME_PREFIX,
> +                                    &offload_fdecoded_options,
> +                                    &offload_fdecoded_options_count,
> +                                    collect_gcc))
> +         fatal_error (input_location, "cannot read %s: %m", filename);
> +       close (fd);
> +     }
> +
> +      compile_images_for_offload_targets (num_offload_files, offload_argv,
>                                         offload_fdecoded_options,
>                                         offload_fdecoded_options_count,
>                                         decoded_options,
>                                         decoded_options_count);
> +
> +      free_array_of_ptrs ((void **) offload_argv, num_offload_files);
> +
>        if (offload_names)
>       {
> -       find_offloadbeginend ();
> +       find_crtoffload ();
>         for (i = 0; i < num_offload_targets; i++)
>           if (offload_names[i])
>             printf ("%s\n", offload_names[i]);
>         free_array_of_ptrs ((void **) offload_names, num_offload_targets);
>       }
> -    }
>  
> -  if (offloadbegin)
> -    printf ("%s\n", offloadbegin);
> -
> -  /* If object files contain offload sections, but do not contain LTO 
> sections,
> -     then there is no need to perform a link-time recompilation, i.e.
> -     lto-wrapper is used only for a compilation of offload images.  */
> -  if (have_offload && !have_lto)
> -    {
> -      for (i = 1; i < argc; ++i)
> -     if (strncmp (argv[i], "-fresolution=",
> -                  sizeof ("-fresolution=") - 1) != 0
> -         && strncmp (argv[i], "-flinker-output=",
> -                     sizeof ("-flinker-output=") - 1) != 0)
> -       {
> -         char *out_file;
> -         /* Can be ".o" or ".so".  */
> -         char *ext = strrchr (argv[i], '.');
> -         if (ext == NULL)
> -           out_file = make_temp_file ("");
> -         else
> -           out_file = make_temp_file (ext);
> -         /* The linker will delete the files we give it, so make copies.  */
> -         copy_file (out_file, argv[i]);
> -         printf ("%s\n", out_file);
> -       }
> -      goto finish;
> +      /* If object files contain offload sections, but do not contain LTO
> +      sections, then there is no need to perform a link-time recompilation,
> +      i.e. lto-wrapper is used only for a compilation of offload images.  */
> +      if (!have_lto)
> +     goto finish;
>      }
>  
>    if (lto_mode == LTO_MODE_LTO)
> @@ -1351,11 +1380,7 @@ cont:
>      }
>  
>   finish:
> -  if (offloadend)
> -    printf ("%s\n", offloadend);
> -
>    XDELETE (lto_argv);
> -  XDELETE (offload_argv);
>    obstack_free (&argv_obstack, NULL);
>  }
>  
> diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
> index 570b1a7..1fdd33e 100644
> --- a/libgcc/Makefile.in
> +++ b/libgcc/Makefile.in
> @@ -994,15 +994,17 @@ crtendS$(objext): $(srcdir)/crtstuff.c
>  crtbeginT$(objext): $(srcdir)/crtstuff.c
>       $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN -DCRTSTUFFT_O
>  
> -# crtoffloadbegin and crtoffloadend contain symbols, that mark the begin and
> +# crtoffload contains __OFFLOAD_TABLE__ symbol which points to the begin and
>  # the end of tables with addresses, required for offloading.
> -crtoffloadbegin$(objext): $(srcdir)/offloadstuff.c
> -     $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN
> -
> -crtoffloadend$(objext): $(srcdir)/offloadstuff.c
> -     $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_END
> +crtoffload$(objext): $(srcdir)/offloadstuff.c
> +     $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $<
>  endif
>  
> +# This linker script provides symbols that mark the begin and the end of 
> tables
> +# with addresses, required for offloading.
> +link-offload-tables.x: $(srcdir)/link-offload-tables.x
> +     cp $< $@
> +
>  ifeq ($(enable_vtable_verify),yes)
>  # These are used in vtable verification; see comments in source files for
>  # more details.
> diff --git a/libgcc/configure b/libgcc/configure
> index 7cf6e9b..e94ad59 100644
> --- a/libgcc/configure
> +++ b/libgcc/configure
> @@ -4829,7 +4829,14 @@ fi
>  
>  
>  if test x"$enable_offload_targets" != x; then
> -  extra_parts="${extra_parts} crtoffloadbegin.o crtoffloadend.o"
> +  extra_parts="${extra_parts} crtoffload.o link-offload-tables.x"
> +fi
> +
> +if test x"$enable_as_accelerator_for" != x; then
> +  case "${target}" in
> +    *-intelmic-* | *-intelmicemul-*)
> +      extra_parts="${extra_parts} link-offload-tables.x"
> +  esac
>  fi
>  
>  # Check if Solaris/x86 linker supports ZERO terminator unwind entries.
> diff --git a/libgcc/configure.ac b/libgcc/configure.ac
> index b96d4bc..e394b1c 100644
> --- a/libgcc/configure.ac
> +++ b/libgcc/configure.ac
> @@ -412,7 +412,14 @@ AC_SUBST(accel_dir_suffix)
>  AC_SUBST(real_host_noncanonical)
>  
>  if test x"$enable_offload_targets" != x; then
> -  extra_parts="${extra_parts} crtoffloadbegin.o crtoffloadend.o"
> +  extra_parts="${extra_parts} crtoffload.o link-offload-tables.x"
> +fi
> +
> +if test x"$enable_as_accelerator_for" != x; then
> +  case "${target}" in
> +    *-intelmic-* | *-intelmicemul-*)
> +      extra_parts="${extra_parts} link-offload-tables.x"
> +  esac
>  fi
>  
>  # Check if Solaris/x86 linker supports ZERO terminator unwind entries.
> diff --git a/libgcc/link-offload-tables.x b/libgcc/link-offload-tables.x
> new file mode 100644
> index 0000000..e7b3fb5
> --- /dev/null
> +++ b/libgcc/link-offload-tables.x
> @@ -0,0 +1,17 @@
> +SECTIONS
> +{
> +  .gnu.offload_funcs :
> +  {
> +    PROVIDE_HIDDEN (__offload_func_table = .);
> +    KEEP (*(.gnu.offload_funcs))
> +    PROVIDE_HIDDEN (__offload_funcs_end = .);
> +  }
> +
> +  .gnu.offload_vars :
> +  {
> +    PROVIDE_HIDDEN (__offload_var_table = .);
> +    KEEP (*(.gnu.offload_vars))
> +    PROVIDE_HIDDEN (__offload_vars_end = .);
> +  }
> +}
> +INSERT AFTER .data;
> diff --git a/libgcc/offloadstuff.c b/libgcc/offloadstuff.c
> index 45e89cf..eb955e3 100644
> --- a/libgcc/offloadstuff.c
> +++ b/libgcc/offloadstuff.c
> @@ -40,32 +40,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
> If not, see
>  #include "tm.h"
>  #include "libgcc_tm.h"
>  
> -#define OFFLOAD_FUNC_TABLE_SECTION_NAME ".gnu.offload_funcs"
> -#define OFFLOAD_VAR_TABLE_SECTION_NAME ".gnu.offload_vars"
> -
> -#ifdef CRT_BEGIN
> -
>  #if defined(HAVE_GAS_HIDDEN) && defined(ENABLE_OFFLOADING)
> -const void *const __offload_func_table[0]
> -  __attribute__ ((__used__, visibility ("hidden"),
> -               section (OFFLOAD_FUNC_TABLE_SECTION_NAME))) = { };
> -const void *const __offload_var_table[0]
> -  __attribute__ ((__used__, visibility ("hidden"),
> -               section (OFFLOAD_VAR_TABLE_SECTION_NAME))) = { };
> -#endif
> -
> -#elif defined CRT_END
> -
> -#if defined(HAVE_GAS_HIDDEN) && defined(ENABLE_OFFLOADING)
> -const void *const __offload_funcs_end[0]
> -  __attribute__ ((__used__, visibility ("hidden"),
> -               section (OFFLOAD_FUNC_TABLE_SECTION_NAME))) = { };
> -const void *const __offload_vars_end[0]
> -  __attribute__ ((__used__, visibility ("hidden"),
> -               section (OFFLOAD_VAR_TABLE_SECTION_NAME))) = { };
>  
> +/* These symbols are provided by the linker script.  */
>  extern const void *const __offload_func_table[];
> +extern const void *const __offload_funcs_end[];
>  extern const void *const __offload_var_table[];
> +extern const void *const __offload_vars_end[];
>  
>  const void *const __OFFLOAD_TABLE__[]
>    __attribute__ ((__visibility__ ("hidden"))) =
> @@ -73,8 +54,5 @@ const void *const __OFFLOAD_TABLE__[]
>    &__offload_func_table, &__offload_funcs_end,
>    &__offload_var_table, &__offload_vars_end
>  };
> -#endif
>  
> -#else /* ! CRT_BEGIN && ! CRT_END */
> -#error "One of CRT_BEGIN or CRT_END must be defined."
>  #endif
> diff --git a/libgomp/Makefile.in b/libgomp/Makefile.in
> index 7a1c976..dd0c861 100644
> --- a/libgomp/Makefile.in
> +++ b/libgomp/Makefile.in
> @@ -17,7 +17,7 @@
>  
>  # Plugins for offload execution, Makefile.am fragment.
>  #
> -# Copyright (C) 2014-2015 Free Software Foundation, Inc.
> +# Copyright (C) 2014-2016 Free Software Foundation, Inc.
>  #
>  # Contributed by Mentor Embedded.
>  #
> @@ -352,6 +352,7 @@ libdir = @libdir@
>  libexecdir = @libexecdir@
>  libtool_VERSION = @libtool_VERSION@
>  link_gomp = @link_gomp@
> +link_offload_tables = @link_offload_tables@
>  localedir = @localedir@
>  localstatedir = @localstatedir@
>  lt_host_flags = @lt_host_flags@
> diff --git a/libgomp/configure b/libgomp/configure
> index e2605f0..0d908ff 100755
> --- a/libgomp/configure
> +++ b/libgomp/configure
> @@ -615,6 +615,7 @@ OMP_LOCK_ALIGN
>  OMP_LOCK_SIZE
>  USE_FORTRAN_FALSE
>  USE_FORTRAN_TRUE
> +link_offload_tables
>  link_gomp
>  XLDFLAGS
>  XCFLAGS
> @@ -11121,7 +11122,7 @@ else
>    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>    lt_status=$lt_dlunknown
>    cat > conftest.$ac_ext <<_LT_EOF
> -#line 11124 "configure"
> +#line 11125 "configure"
>  #include "confdefs.h"
>  
>  #if HAVE_DLFCN_H
> @@ -11227,7 +11228,7 @@ else
>    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
>    lt_status=$lt_dlunknown
>    cat > conftest.$ac_ext <<_LT_EOF
> -#line 11230 "configure"
> +#line 11231 "configure"
>  #include "confdefs.h"
>  
>  #if HAVE_DLFCN_H
> @@ -15090,7 +15091,7 @@ esac
>  
>  # Plugins for offload execution, configure.ac fragment.  -*- mode: autoconf 
> -*-
>  #
> -# Copyright (C) 2014-2015 Free Software Foundation, Inc.
> +# Copyright (C) 2014-2016 Free Software Foundation, Inc.
>  #
>  # Contributed by Mentor Embedded.
>  #
> @@ -16478,6 +16479,20 @@ else
>  fi
>  
>  
> +# Pass link-offload-tables.x script to the linker.  It provides symbols that
> +# mark the begin and the end of tables with addresses, required for 
> offloading.
> +link_offload_tables=
> +if test x"$enable_offload_targets" != x; then
> +  link_offload_tables="%Tlink-offload-tables.x"
> +fi
> +if test x"$enable_as_accelerator_for" != x; then
> +  case "${target}" in
> +    *-intelmic-* | *-intelmicemul-*)
> +      link_offload_tables="%Tlink-offload-tables.x"
> +  esac
> +fi
> +
> +
>   if test "$ac_cv_fc_compiler_gnu" = yes; then
>    USE_FORTRAN_TRUE=
>    USE_FORTRAN_FALSE='#'
> diff --git a/libgomp/configure.ac b/libgomp/configure.ac
> index 2e41ca8..9f8a991 100644
> --- a/libgomp/configure.ac
> +++ b/libgomp/configure.ac
> @@ -305,6 +305,20 @@ else
>  fi
>  AC_SUBST(link_gomp)
>  
> +# Pass link-offload-tables.x script to the linker.  It provides symbols that
> +# mark the begin and the end of tables with addresses, required for 
> offloading.
> +link_offload_tables=
> +if test x"$enable_offload_targets" != x; then
> +  link_offload_tables="%Tlink-offload-tables.x"
> +fi
> +if test x"$enable_as_accelerator_for" != x; then
> +  case "${target}" in
> +    *-intelmic-* | *-intelmicemul-*)
> +      link_offload_tables="%Tlink-offload-tables.x"
> +  esac
> +fi
> +AC_SUBST(link_offload_tables)
> +
>  AM_CONDITIONAL([USE_FORTRAN], [test "$ac_cv_fc_compiler_gnu" = yes])
>  
>  # ??? 2006-01-24: Paulo committed to asking autoconf folk to document
> diff --git a/libgomp/libgomp.spec.in b/libgomp/libgomp.spec.in
> index 5651603..6a946c4 100644
> --- a/libgomp/libgomp.spec.in
> +++ b/libgomp/libgomp.spec.in
> @@ -1,3 +1,3 @@
>  # This spec file is read by gcc when linking.  It is used to specify the
>  # standard libraries we need in order to link with libgomp.
> -*link_gomp: @link_gomp@
> +*link_gomp: @link_gomp@ @link_offload_tables@
> diff --git a/libgomp/testsuite/Makefile.in b/libgomp/testsuite/Makefile.in
> index c25d21f..a3982bf 100644
> --- a/libgomp/testsuite/Makefile.in
> +++ b/libgomp/testsuite/Makefile.in
> @@ -208,6 +208,7 @@ libdir = @libdir@
>  libexecdir = @libexecdir@
>  libtool_VERSION = @libtool_VERSION@
>  link_gomp = @link_gomp@
> +link_offload_tables = @link_offload_tables@
>  localedir = @localedir@
>  localstatedir = @localstatedir@
>  lt_host_flags = @lt_host_flags@
> diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
> index 0a6a767..a62c31e 100644
> --- a/lto-plugin/lto-plugin.c
> +++ b/lto-plugin/lto-plugin.c
> @@ -152,8 +152,14 @@ static ld_plugin_add_symbols add_symbols;
>  static struct plugin_file_info *claimed_files = NULL;
>  static unsigned int num_claimed_files = 0;
>  
> -static struct plugin_file_info *offload_files = NULL;
> -static unsigned int num_offload_files = 0;
> +/* Lists of files with offloading.  We need 3 of them to maintain the correct
> +   order, otherwise host and target tables with addresses wouldn't match.  */
> +static char **offload_files_1;
> +static char **offload_files_2;
> +static char **offload_files_3;
> +static unsigned num_offload_files_1;
> +static unsigned num_offload_files_2;
> +static unsigned num_offload_files_3;
>  
>  static char **output_files = NULL;
>  static unsigned int num_output_files = 0;
> @@ -351,14 +357,6 @@ free_2 (void)
>        free (info->name);
>      }
>  
> -  for (i = 0; i < num_offload_files; i++)
> -    {
> -      struct plugin_file_info *info = &offload_files[i];
> -      struct plugin_symtab *symtab = &info->symtab;
> -      free (symtab->aux);
> -      free (info->name);
> -    }
> -
>    for (i = 0; i < num_output_files; i++)
>      free (output_files[i]);
>    free (output_files);
> @@ -367,9 +365,17 @@ free_2 (void)
>    claimed_files = NULL;
>    num_claimed_files = 0;
>  
> -  free (offload_files);
> -  offload_files = NULL;
> -  num_offload_files = 0;
> +  for (i = 0; i < num_offload_files_1; i++)
> +    free (offload_files_1[i]);
> +  for (i = 0; i < num_offload_files_2; i++)
> +    free (offload_files_2[i]);
> +  for (i = 0; i < num_offload_files_3; i++)
> +    free (offload_files_3[i]);
> +  free (offload_files_1);
> +  free (offload_files_2);
> +  free (offload_files_3);
> +  offload_files_1 = offload_files_2 = offload_files_3 = NULL;
> +  num_offload_files_1 = num_offload_files_2 = num_offload_files_3 = 0;
>  
>    free (arguments_file_name);
>    arguments_file_name = NULL;
> @@ -625,11 +631,12 @@ static enum ld_plugin_status
>  all_symbols_read_handler (void)
>  {
>    unsigned i;
> -  unsigned num_lto_args
> -    = num_claimed_files + num_offload_files + lto_wrapper_num_args + 2;
> +  unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 3;
>    char **lto_argv;
>    const char *linker_output_str;
>    const char **lto_arg_ptr;
> +  unsigned num_offload_files
> +    = num_offload_files_1 + num_offload_files_2 + num_offload_files_3;
>    if (num_claimed_files + num_offload_files == 0)
>      return LDPS_OK;
>  
> @@ -646,7 +653,6 @@ all_symbols_read_handler (void)
>    write_resolution ();
>  
>    free_1 (claimed_files, num_claimed_files);
> -  free_1 (offload_files, num_offload_files);
>  
>    for (i = 0; i < lto_wrapper_num_args; i++)
>      *lto_arg_ptr++ = lto_wrapper_argv[i];
> @@ -671,16 +677,40 @@ all_symbols_read_handler (void)
>        break;
>      }
>    *lto_arg_ptr++ = xstrdup (linker_output_str);
> -  for (i = 0; i < num_claimed_files; i++)
> -    {
> -      struct plugin_file_info *info = &claimed_files[i];
>  
> -      *lto_arg_ptr++ = info->name;
> +  if (num_offload_files > 0)
> +    {
> +      FILE *f;
> +      char *arg;
> +      char *offload_objects_file_name;
> +
> +      offload_objects_file_name = make_temp_file ("");
> +      check (offload_objects_file_name, LDPL_FATAL,
> +          "Failed to generate a temporary file name");
> +      f = fopen (offload_objects_file_name, "w");
> +      check (f, LDPL_FATAL, "could not open file with offload objects");
> +      fprintf (f, "%u\n", num_offload_files);
> +
> +      /* Names of files with offloading are written in the following order:
> +      1. Non-LTO files before the first claimed LTO file;
> +      2. LTO files;
> +      3. Non-LTO files after the first claimed LTO file.  */
> +      for (i = 0; i < num_offload_files_1; i++)
> +     fprintf (f, "%s\n", offload_files_1[i]);
> +      for (i = 0; i < num_offload_files_2; i++)
> +     fprintf (f, "%s\n", offload_files_2[i]);
> +      for (i = 0; i < num_offload_files_3; i++)
> +     fprintf (f, "%s\n", offload_files_3[i]);
> +      fclose (f);
> +
> +      arg = concat ("-foffload-objects=", offload_objects_file_name, NULL);
> +      check (arg, LDPL_FATAL, "could not allocate");
> +      *lto_arg_ptr++ = arg;
>      }
>  
> -  for (i = 0; i < num_offload_files; i++)
> +  for (i = 0; i < num_claimed_files; i++)
>      {
> -      struct plugin_file_info *info = &offload_files[i];
> +      struct plugin_file_info *info = &claimed_files[i];
>  
>        *lto_arg_ptr++ = info->name;
>      }
> @@ -1007,18 +1037,37 @@ claim_file_handler (const struct ld_plugin_input_file 
> *file, int *claimed)
>       xrealloc (claimed_files,
>                 num_claimed_files * sizeof (struct plugin_file_info));
>        claimed_files[num_claimed_files - 1] = lto_file;
> +
> +      *claimed = 1;
>      }
>  
> -  if (obj.found == 0 && obj.offload == 1)
> +  if (obj.offload == 1)
>      {
> -      num_offload_files++;
> -      offload_files =
> -     xrealloc (offload_files,
> -               num_offload_files * sizeof (struct plugin_file_info));
> -      offload_files[num_offload_files - 1] = lto_file;
> -    }
> +      char ***arr;
> +      unsigned *num;
> +      if (num_claimed_files == 0)
> +     {
> +       /* Offload Non-LTO file before the first claimed LTO file.  */
> +       arr = &offload_files_1;
> +       num = &num_offload_files_1;
> +     }
> +      else if (*claimed)
> +     {
> +       /* Offload LTO file.  */
> +       arr = &offload_files_2;
> +       num = &num_offload_files_2;
> +     }
> +      else
> +     {
> +       /* Offload Non-LTO file after the first claimed LTO file.  */
> +       arr = &offload_files_3;
> +       num = &num_offload_files_3;
> +     }
>  
> -  *claimed = 1;
> +      (*num)++;
> +      *arr = xrealloc (*arr, *num * sizeof (char *));
> +      (*arr)[*num - 1] = xstrdup (lto_file.name);
> +    }
>  
>    goto cleanup;
> 
> 
> Thanks,
>   -- Ilya
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to