This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][gomp4] Offloading patches (3/3): Add invocation of target compiler


Hi everybody,

Here is a patch 3/3: Add invocation of target compiler.

With this patch lto-wrapper performs invocation of target compilers and embeds
the resultant target images into the host binary.  The targets and the
corresponding compilers are supposed to be specified in a special environment
variables (that works well with the recent Andrey's patch).  For now, we need
'-flto' options for the infrastructure to run - but I think we could remove this
requirement in future.

We generate C-files which are used for creating symbols for descriptor header
and descriptor end.  With this and after some manipulations with symbols (we
need to call objcopy a couple of times for this) all files: i.e. target images,
descriptor-header and descriptor-end - are linked together into a new object
file which is passed to the linker as an output of lto-wrapper.

Thanks,
Michael

---
 gcc/lto-wrapper.c |  560 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 560 insertions(+), 0 deletions(-)

diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 335ec8f..a9085b5 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -52,6 +52,11 @@ along with GCC; see the file COPYING3.  If not see
 
 #define LTO_SECTION_NAME_PREFIX         ".gnu.lto_"
 
+#define OFFLOAD_FUNC_TABLE_SECTION_NAME ".offload_func_table_section"
+#define OFFLOAD_IMAGE_SECTION_NAME	".offload_image_section"
+#define OFFLOAD_TARGET_NAMES_ENV	"OFFLOAD_TARGET_NAMES"
+#define OFFLOAD_TARGET_COMPILERS_ENV	"OFFLOAD_TARGET_COMPILERS"
+
 /* End of lto-streamer.h copy.  */
 
 int debug;				/* true if -save-temps.  */
@@ -447,6 +452,540 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
     }
 }
 
+
+/* Parse STR, saving found tokens into PVALUES and return their number.
+   Tokens are assumed to be delimited by ':'.  */
+
+static unsigned
+parse_env_var (const char *str, char ***pvalues)
+{
+  const char *curval, *nextval;
+  char **values;
+  unsigned num = 1, i;
+
+  curval = strchr (str, ':');
+  while (curval)
+    {
+      num++;
+      curval = strchr (curval + 1, ':');
+    }
+
+  values = (char**) xmalloc (num * sizeof (char*));
+  curval = str;
+  nextval = strchrnul (curval, ':');
+  for (i = 0; i < num; i++)
+    {
+      int l = nextval - curval;
+      values[i] = (char*) xmalloc (l + 1);
+      memcpy (values[i], curval, l);
+      values[i][l] = 0;
+
+      curval = nextval + 1;
+      nextval = strchrnul (curval, ':');
+    }
+  *pvalues = values;
+  return num;
+}
+
+/* Generate openmp-descriptor file.  The function generates source-file and then
+   compiles it with COLLECT_GCC.
+   NAMES are the names of the targets, they are used in names of generated
+   symbols.  NUM is the number of targets.
+   FOR_TARGET specifies whether we generate descriptor for host or for
+   target-side.  We add pointers to images into the table only for host side.
+   Return value is the name of the generated object file.  */
+
+static char*
+generate_descriptor_file (int num, char **names, const char *collect_gcc,
+			  bool for_target = false)
+{
+  const char **target_argv;
+  struct obstack target_argv_obstack;
+  FILE *desc_src_file = NULL;
+  char *desc_src_filename = NULL;
+  char *desc_obj_filename = NULL;
+  int i;
+
+  desc_src_filename = make_temp_file ("_omp_descr.c");
+  desc_src_file = fopen (desc_src_filename, "wb");
+  if (!desc_src_file)
+    {
+      free (desc_src_filename);
+      return NULL;
+    }
+
+  for (i = 0; i < num; i++)
+    {
+      fprintf (desc_src_file, "extern void *_omp_image_%s_start;\n", names[i]);
+      fprintf (desc_src_file, "extern void *_omp_image_%s_end;\n", names[i]);
+    }
+  fprintf (desc_src_file, "extern void *_omp_func_table[];\n");
+  fprintf (desc_src_file, "extern void *_omp_table_end[];\n");
+  fprintf (desc_src_file,
+	   "void *__OPENMP_TARGET__[]\n"
+	   "  __attribute__ ((__used__, visibility (\"protected\"),\n"
+	   "		      section (\"%s\"))) = {\n",
+	   OFFLOAD_IMAGE_SECTION_NAME);
+  /* First two elements describes Openmp Functions/Globals table.
+     Target side descriptor contains nothing else.  Host side descriptor
+     contains pointers to images after that.  */
+  fprintf (desc_src_file, "  &_omp_func_table, &_omp_table_end,\n");
+  if (!for_target)
+    for (i = 0; i < num; i++)
+      fprintf (desc_src_file, "  &_omp_image_%s_start, &_omp_image_%s_end,\n",
+	       names[i], names[i]);
+  fprintf (desc_src_file, "};\n");
+
+  if (!for_target)
+    fprintf (desc_src_file,
+    "void GOMP_register_lib (const void *);\n"
+    "__attribute__((constructor))\n"
+    "static void\n"
+    "init (void)\n"
+    "{\n"
+    "  GOMP_register_lib (__OPENMP_TARGET__);\n"
+    "}\n");
+  else
+    fprintf (desc_src_file,
+    "void target_register_lib (const void *);\n"
+    "__attribute__((constructor))\n"
+    "static void\n"
+    "init (void)\n"
+    "{\n"
+    "  target_register_lib (__OPENMP_TARGET__);\n"
+    "}\n");
+
+  /* Declare symbol for Openmp Functions/Globals table.
+     It is placed in a dedicated section - all objects files have their entries
+     for this table in the same section and during linking its merged into a
+     single table, which could be referred to by this symbol.
+     End of this table is also marked with a symbol, which is linked after all
+     other files.  */
+  fprintf (desc_src_file,
+	   "void *_omp_func_table[0]\n"
+	   "  __attribute__ ((__used__, visibility (\"protected\"),\n"
+	   "		      section (\"%s\"))) = { };\n",
+	   OFFLOAD_FUNC_TABLE_SECTION_NAME);
+  fclose (desc_src_file);
+
+  /* Compile descriptor-file.  */
+  desc_obj_filename = make_temp_file ("_omp_descr.o");
+  obstack_init (&target_argv_obstack);
+  obstack_ptr_grow (&target_argv_obstack, collect_gcc);
+  obstack_ptr_grow (&target_argv_obstack, "-c");
+  obstack_ptr_grow (&target_argv_obstack, desc_src_filename);
+  obstack_ptr_grow (&target_argv_obstack, "-o");
+  obstack_ptr_grow (&target_argv_obstack, desc_obj_filename);
+  obstack_ptr_grow (&target_argv_obstack, "-shared");
+  obstack_ptr_grow (&target_argv_obstack, "-fPIC");
+  obstack_ptr_grow (&target_argv_obstack, NULL);
+
+  target_argv = XOBFINISH (&target_argv_obstack, const char **);
+  fork_execute (CONST_CAST (char **, target_argv));
+  obstack_free (&target_argv_obstack, NULL);
+
+  if (!debug)
+    maybe_unlink_file (desc_src_filename);
+  free (desc_src_filename);
+  return desc_obj_filename;
+}
+
+
+/* Generate object file containing a 0-sized _omp_table_end symbol.
+   The function generates source-file and then compiles it with COLLECT_GCC.
+   Return value is the name of the generated object file.  */
+
+static char*
+generate_omp_table_end_file (const char *collect_gcc)
+{
+  const char **target_argv;
+  struct obstack target_argv_obstack;
+  FILE *desc_src_file = NULL;
+  char *desc_src_filename = NULL;
+  char *desc_obj_filename = NULL;
+
+  desc_src_filename = make_temp_file ("_omp_table_end.c");
+  desc_src_file = fopen (desc_src_filename, "wb");
+  if (!desc_src_file)
+    {
+      free (desc_src_filename);
+      return NULL;
+    }
+
+  fprintf (desc_src_file,
+	   "void *_omp_table_end[0]\n"
+	   "  __attribute__ ((__used__, visibility (\"protected\"),\n"
+	   "		      section (\"%s\"))) = { };\n",
+	   OFFLOAD_FUNC_TABLE_SECTION_NAME);
+  fclose (desc_src_file);
+
+  /* Compile descriptor-file and pass resultant object file to linker.  */
+  desc_obj_filename = make_temp_file ("_omp_table_end.o");
+  obstack_init (&target_argv_obstack);
+  obstack_ptr_grow (&target_argv_obstack, collect_gcc);
+  obstack_ptr_grow (&target_argv_obstack, "-c");
+  obstack_ptr_grow (&target_argv_obstack, desc_src_filename);
+  obstack_ptr_grow (&target_argv_obstack, "-o");
+  obstack_ptr_grow (&target_argv_obstack, desc_obj_filename);
+  obstack_ptr_grow (&target_argv_obstack, "-shared");
+  obstack_ptr_grow (&target_argv_obstack, "-fPIC");
+  obstack_ptr_grow (&target_argv_obstack, NULL);
+
+  target_argv = XOBFINISH (&target_argv_obstack, const char **);
+  fork_execute (CONST_CAST (char **, target_argv));
+  obstack_free (&target_argv_obstack, NULL);
+
+  if (!debug)
+    maybe_unlink_file (desc_src_filename);
+  free (desc_src_filename);
+  return desc_obj_filename;
+}
+
+
+/* Prepare target image for target NAME.
+   Firstly, we execute COMPILER, passing all input files to it to produce DSO.
+   We also use descriptor-file and omp_table_end file at this moment to properly
+   fill all OpenMP tables in the target image.
+   When target DSO is ready, we pass it to objcopy to place its image into a
+   special data section.  After that we rename target image's symbols to values,
+   expected by the host side, and return the name of the resultant file.  */
+
+static char*
+prepare_target_image (char *name, char *compiler, char *desc_filename,
+		      char *omp_table_end_filename,
+		      unsigned in_argc, char *in_argv[], char **symbols)
+{
+  char *option_for_objdump[3];
+  const char **argv;
+  struct obstack argv_obstack;
+  char *target_image_file_name = NULL;
+  char *symbol_name;
+  unsigned i;
+  char *filename;
+  char *buf1 = NULL, *buf2 = NULL;
+
+  /* Generate temp file name.  */
+  target_image_file_name = make_temp_file (".target.so");
+  filename = (char*) xmalloc (strlen (target_image_file_name) + 1);
+  if (!filename)
+    return NULL;
+  strcpy (filename, target_image_file_name);
+
+  /* --------------------------------------  */
+  /* Run gcc for target.  */
+  obstack_init (&argv_obstack);
+  obstack_ptr_grow (&argv_obstack, compiler);
+  obstack_ptr_grow (&argv_obstack, "-shared");
+  obstack_ptr_grow (&argv_obstack, "-fPIC");
+  obstack_ptr_grow (&argv_obstack, "-xlto");
+  obstack_ptr_grow (&argv_obstack, "-fopenmp_target");
+  obstack_ptr_grow (&argv_obstack, "-o");
+  obstack_ptr_grow (&argv_obstack, target_image_file_name);
+
+  /* Append the input objects.  */
+  buf1 = (char*) xmalloc (strlen (desc_filename) + strlen ("-Wl,") + 1);
+  buf2 = (char*) xmalloc (strlen (omp_table_end_filename)
+			  + strlen ("-Wl,") + 1);
+  if (!buf1 || !buf2)
+      return NULL;
+  sprintf (buf1, "-Wl,%s", desc_filename);
+  obstack_ptr_grow (&argv_obstack, buf1);
+  for (i = 1; i < in_argc; ++i)
+    if (strncmp (in_argv[i], "-fresolution=", sizeof ("-fresolution=") - 1))
+      obstack_ptr_grow (&argv_obstack, in_argv[i]);
+  sprintf (buf2, "-Wl,%s", omp_table_end_filename);
+  obstack_ptr_grow (&argv_obstack, buf2);
+  obstack_ptr_grow (&argv_obstack, NULL);
+
+  argv = XOBFINISH (&argv_obstack, const char **);
+  fork_execute (CONST_CAST (char **, argv));
+  obstack_free (&argv_obstack, NULL);
+  free (buf1);
+  free (buf2);
+
+  /* --------------------------------------  */
+  /* Run objcopy on TARGET_IMAGE_FILE_NAME.  */
+  buf1 = (char*) xmalloc (strlen (".data=.")
+			  + strlen (OFFLOAD_IMAGE_SECTION_NAME) + 1);
+  if (!buf1)
+    return NULL;
+  sprintf (buf1, ".data=%s", OFFLOAD_IMAGE_SECTION_NAME);
+  obstack_init (&argv_obstack);
+  obstack_ptr_grow (&argv_obstack, "objcopy");
+  obstack_ptr_grow (&argv_obstack, "-B");
+  obstack_ptr_grow (&argv_obstack, "i386");
+  obstack_ptr_grow (&argv_obstack, "-I");
+  obstack_ptr_grow (&argv_obstack, "binary");
+  obstack_ptr_grow (&argv_obstack, "-O");
+  /* TODO: Properly handle 32-bit mode.  */
+  obstack_ptr_grow (&argv_obstack, "elf64-x86-64");
+  obstack_ptr_grow (&argv_obstack, target_image_file_name);
+  obstack_ptr_grow (&argv_obstack, "--rename-section");
+  obstack_ptr_grow (&argv_obstack, buf1);
+  obstack_ptr_grow (&argv_obstack, NULL);
+
+  argv = XOBFINISH (&argv_obstack, const char **);
+  fork_execute (CONST_CAST (char **, argv));
+  obstack_free (&argv_obstack, NULL);
+  free (buf1);
+
+  /* --------------------------------------  */
+  /* Run objcopy again to rename new symbols.  */
+  obstack_init (&argv_obstack);
+  obstack_ptr_grow (&argv_obstack, "objcopy");
+  obstack_ptr_grow (&argv_obstack, target_image_file_name);
+
+  /* Objcopy has created symbols, containing the input file name with
+     special characters replaced with '_'.  We are going to rename these
+     new symbols, and to do that we need to know their names.  */
+  symbol_name = (char*) xmalloc (strlen (target_image_file_name));
+  if (!symbol_name)
+    return NULL;
+  i = 0;
+  while (target_image_file_name[i])
+    {
+      char c = target_image_file_name[i];
+      if (c == '/' || c == '.')
+	c = '_';
+      symbol_name[i] = c;
+      i++;
+    }
+  symbol_name[i] = 0;
+
+  for (i = 0; i < 3; i++)
+    {
+      option_for_objdump[i]
+	= (char*) xmalloc (strlen (target_image_file_name) * 2 + 1
+			   + strlen ("_binary__start=_omp_image__start"));
+      symbols[i] = (char*) xmalloc (strlen (name) + 1
+				    + strlen ("_omp_image__start"));
+      if (!option_for_objdump[i] || !symbols[i])
+	return NULL;
+    }
+  sprintf (symbols[0], "_omp_image_%s_start", name);
+  sprintf (symbols[1], "_omp_image_%s_size", name);
+  sprintf (symbols[2], "_omp_image_%s_end", name);
+
+  sprintf (option_for_objdump[0], "_binary_%s_start=_omp_image_%s_start",
+      symbol_name, name);
+  sprintf (option_for_objdump[1], "_binary_%s_end=_omp_image_%s_end",
+      symbol_name, name);
+  sprintf (option_for_objdump[2], "_binary_%s_size=_omp_image_%s_size",
+      symbol_name, name);
+  obstack_ptr_grow (&argv_obstack, "--redefine-sym");
+  obstack_ptr_grow (&argv_obstack, option_for_objdump[0]);
+  obstack_ptr_grow (&argv_obstack, "--redefine-sym");
+  obstack_ptr_grow (&argv_obstack, option_for_objdump[1]);
+  obstack_ptr_grow (&argv_obstack, "--redefine-sym");
+  obstack_ptr_grow (&argv_obstack, option_for_objdump[2]);
+  obstack_ptr_grow (&argv_obstack, NULL);
+
+  argv = XOBFINISH (&argv_obstack, const char **);
+  fork_execute (CONST_CAST (char **, argv));
+  obstack_free (&argv_obstack, NULL);
+  free (symbol_name);
+
+  for (i = 0; i < 3; i++)
+    free (option_for_objdump[i]);
+  return filename;
+}
+
+
+/* The routine performs partial linking of all target images (which are already
+   placed in a data section), and localize all symbols except __OPENMP_TARGET__.
+   That is done to prevent overriding of symbols from DSO by symbols from
+   another DSO or executable (here we are talking about symbols
+   _omp_image_<target>_{start,size,end}).
+   DESC_FILENAME is a name of a descriptor file.  The descriptor declares symbol
+   __OPENMP_TARGET__ and refers to symbols _omp_image_<target>_{start,size,end}
+   from object files with target images.
+   NUM_TARGETS is the number of targets (and correspondyngly number of object
+   files).
+   FILENAMES is an array of object filenames, SYMBOLS is an array of the symbols
+   (three symbols per target).
+   Return value is name of object file, containing OpenMP descriptor,
+   function/globals tables and images.  */
+
+static char*
+postprocess_target_images (char *desc_filename, unsigned num_targets,
+			   char **filenames, char **symbols)
+{
+  const char **argv;
+  struct obstack argv_obstack;
+  unsigned i;
+  char *offload_out = make_temp_file (".offload.o");
+  if (!offload_out)
+    return NULL;
+
+  /* Perform partial linking for the target images and descriptor.
+     As a result we'll get a finalized object file with all offload data.  */
+  obstack_init (&argv_obstack);
+  obstack_ptr_grow (&argv_obstack, "ld");
+  obstack_ptr_grow (&argv_obstack, "-r");
+  obstack_ptr_grow (&argv_obstack, desc_filename);
+  for (i = 0; i < num_targets; i++)
+    obstack_ptr_grow (&argv_obstack, filenames[i]);
+  obstack_ptr_grow (&argv_obstack, "-o");
+  obstack_ptr_grow (&argv_obstack, offload_out);
+  obstack_ptr_grow (&argv_obstack, NULL);
+  argv = XOBFINISH (&argv_obstack, const char **);
+  fork_execute (CONST_CAST (char **, argv));
+  obstack_free (&argv_obstack, NULL);
+
+  if (!debug)
+    for (i = 0; i < num_targets; i++)
+      maybe_unlink_file (filenames[i]);
+
+  /* Run objcopy on the resultant object file to localize generated symbols to
+     avoid conflicting between different DSO and executable.  */
+  obstack_init (&argv_obstack);
+  obstack_ptr_grow (&argv_obstack, "objcopy");
+  for (i = 0; i < num_targets*3; i++)
+    {
+      obstack_ptr_grow (&argv_obstack, "-L");
+      obstack_ptr_grow (&argv_obstack, symbols[i]);
+    }
+  obstack_ptr_grow (&argv_obstack, offload_out);
+  obstack_ptr_grow (&argv_obstack, NULL);
+  argv = XOBFINISH (&argv_obstack, const char **);
+  fork_execute (CONST_CAST (char **, argv));
+  obstack_free (&argv_obstack, NULL);
+  return offload_out;
+}
+
+/* Auxiliary function that frees elements of PTR and PTR itself.
+   N is number of elements to be freed.
+   If PTR is NULL, nothing is freed.  If an element is NULL, subsequent elements
+   are not freed.  */
+static void**
+free_array_of_ptrs (void **ptr, unsigned n)
+{
+  unsigned i;
+  if (!ptr)
+    return NULL;
+  for (i = 0; i < n; i++)
+    {
+      if (!ptr[i])
+	break;
+      free (ptr[i]);
+    }
+  free (ptr);
+  return NULL;
+}
+
+/* Replace all special characters in array of strings with '_'.
+   This is needed, e.g., when we want to use a string for a symbol name.  */
+static void
+replace_special_characters (char **ptr, unsigned n)
+{
+  unsigned i, j;
+  const char *special_chars = "-+=/\\~`!@#$%^&*()[]{},;.:\"'";
+  for (i = 0; i < n; i++)
+    {
+      char *str = ptr[i];
+      for (j = 0; j < strlen (str); j++)
+	{
+	  if (strchr (special_chars, str[j]))
+	    str[j] = '_';
+	}
+    }
+}
+
+/* The main routine dealing with openmp offloading.
+   The routine builds a target image for each offloading target, and places all
+   images into a dedicated data-section, adding a descriptor for accessing it.
+   IN_ARGC and IN_ARGV specify input files.  As all of them could contain
+   omp-sections, we pass them all to target compilers.
+   COLLECT_GCC is a host compiler.
+   Env-variable OFFLOAD_TARGET_NAMES_ENV describes for which targets we should
+   build images.
+   Env-variable OFFLOAD_TARGET_COMPILERS_ENV specifies compilers to be used for
+   target image building.
+   Return value is name of object file, containing OpenMP descriptor,
+   function/globals tables and images.  */
+
+static char*
+compile_images_for_openmp_targets (unsigned in_argc, char *in_argv[],
+				   const char *collect_gcc)
+{
+  char *desc_filename = NULL, *offload_out = NULL;
+  char *omp_table_end_filename = NULL, *target_desc_filename = NULL;
+  char *target_names, *target_compilers;
+  char **names, **compilers, **filenames = NULL, **symbols = NULL;
+  unsigned num_targets, num_compilers, i;
+
+  /* Step 1: Obtain names of offload targets and corresponding compilers.  */
+  target_names = getenv (OFFLOAD_TARGET_NAMES_ENV);
+  target_compilers = getenv (OFFLOAD_TARGET_COMPILERS_ENV);
+  if (!target_names || !target_compilers)
+    return NULL;
+
+  num_targets = parse_env_var (target_names, &names);
+  replace_special_characters (names, num_targets);
+
+  num_compilers = parse_env_var (target_compilers, &compilers);
+  if (num_compilers != num_targets)
+    goto cleanup;
+
+  /* Step 2: Generate a file with omp descriptor table and a file with
+     omp_table_end symbol for target images.  We'll link these files into the
+     images.  */
+  target_desc_filename = generate_descriptor_file (num_targets, names,
+						   collect_gcc, true);
+  omp_table_end_filename = generate_omp_table_end_file (collect_gcc);
+  if (!target_desc_filename || !omp_table_end_filename)
+    fatal_perror ("Problem with building offloading targets.\n");
+
+  /* Step 3: Prepare an image for each target.  A prepared image contains three
+     symbols: _omp_image_<target>_start, _omp_image_<target>_end, and
+     _omp_image_<target>_end.  We save these names in SYMBOLS array.
+     Images filenames are stored in FILENAMES array.  */
+  filenames = (char**) xmalloc (sizeof (char*) * num_targets);
+  symbols = (char**) xmalloc (sizeof (char*) * num_targets * 3);
+  for (i = 0; i < num_targets; i++)
+    {
+      filenames[i] = prepare_target_image (names[i], compilers[i],
+					   target_desc_filename,
+					   omp_table_end_filename,
+					   in_argc, in_argv, &symbols[i*3]);
+      if (!filenames[i])
+	fatal_perror ("Problem with building target image for %s.\n", names[i]);
+    }
+  if (!debug)
+    {
+      maybe_unlink_file (target_desc_filename);
+      maybe_unlink_file (omp_table_end_filename);
+    }
+
+  /* Step 4: Generate a file with omp descriptor table for host binary.  */
+  desc_filename = generate_descriptor_file (num_targets, names, collect_gcc);
+  if (!desc_filename)
+    goto cleanup;
+
+  /* Step 5: Perform partial linking on all generated files, and then localize
+     all generated symbols, except __OPENMP_TARGET__.  */
+  offload_out = postprocess_target_images (desc_filename, num_targets,
+					   filenames, symbols);
+  if (!offload_out)
+    fatal_perror ("Problem with embedding target images for offloading.\n");
+  if (!debug)
+    maybe_unlink_file (desc_filename);
+
+cleanup:
+  names = (char**) free_array_of_ptrs ((void**) names, num_targets);
+  compilers = (char**) free_array_of_ptrs ((void**) compilers, num_compilers);
+  filenames = (char**) free_array_of_ptrs ((void**) filenames, num_targets);
+  symbols = (char**) free_array_of_ptrs ((void**) symbols, num_targets);
+  if (omp_table_end_filename)
+    free (omp_table_end_filename);
+  if (target_desc_filename)
+    free (target_desc_filename);
+  if (desc_filename)
+    free (desc_filename);
+  return offload_out;
+}
+
+
 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
 
 static void
@@ -768,6 +1307,7 @@ run_gcc (unsigned argc, char *argv[])
       FILE *stream = fopen (ltrans_output_file, "r");
       FILE *mstream = NULL;
       struct obstack env_obstack;
+      char *offload_output_name, *offload_table_end_name;
 
       if (!stream)
 	fatal_perror ("fopen: %s", ltrans_output_file);
@@ -906,12 +1446,32 @@ cont:
 	  for (i = 0; i < nr; ++i)
 	    maybe_unlink_file (input_names[i]);
 	}
+
+      offload_output_name = compile_images_for_openmp_targets (argc, argv,
+							       collect_gcc);
+      if (offload_output_name)
+	{
+	  fputs (offload_output_name, stdout);
+	  putc ('\n', stdout);
+	  free (offload_output_name);
+	}
       for (i = 0; i < nr; ++i)
 	{
 	  fputs (output_names[i], stdout);
 	  putc ('\n', stdout);
 	  free (input_names[i]);
 	}
+
+      /* Generate a file with omp descriptor table and pass its name to
+	 linker.  */
+      offload_table_end_name = generate_omp_table_end_file (collect_gcc);
+      if (offload_table_end_name)
+	{
+	  fputs (offload_table_end_name, stdout);
+	  putc ('\n', stdout);
+	  free (offload_table_end_name);
+	}
+
       nr = 0;
       free (output_names);
       free (input_names);
-- 
1.7.1



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]