Home | History | Annotate | Line # | Download | only in i386
      1  1.1  mrg /* Offload image generation tool for Intel MIC devices.
      2  1.1  mrg 
      3  1.1  mrg    Copyright (C) 2014-2022 Free Software Foundation, Inc.
      4  1.1  mrg 
      5  1.1  mrg    Contributed by Ilya Verbin <ilya.verbin (at) intel.com>.
      6  1.1  mrg 
      7  1.1  mrg    This file is part of GCC.
      8  1.1  mrg 
      9  1.1  mrg    GCC is free software; you can redistribute it and/or modify
     10  1.1  mrg    it under the terms of the GNU General Public License as published by
     11  1.1  mrg    the Free Software Foundation; either version 3, or (at your option)
     12  1.1  mrg    any later version.
     13  1.1  mrg 
     14  1.1  mrg    GCC is distributed in the hope that it will be useful,
     15  1.1  mrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  1.1  mrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  1.1  mrg    GNU General Public License for more details.
     18  1.1  mrg 
     19  1.1  mrg    You should have received a copy of the GNU General Public License
     20  1.1  mrg    along with GCC; see the file COPYING3.  If not see
     21  1.1  mrg    <http://www.gnu.org/licenses/>.  */
     22  1.1  mrg 
     23  1.1  mrg #define IN_TARGET_CODE 1
     24  1.1  mrg 
     25  1.1  mrg #include "config.h"
     26  1.1  mrg #include <libgen.h>
     27  1.1  mrg #include "system.h"
     28  1.1  mrg #include "coretypes.h"
     29  1.1  mrg #include "obstack.h"
     30  1.1  mrg #include "intl.h"
     31  1.1  mrg #include "diagnostic.h"
     32  1.1  mrg #include "collect-utils.h"
     33  1.1  mrg #include "intelmic-offload.h"
     34  1.1  mrg 
     35  1.1  mrg const char tool_name[] = "intelmic mkoffload";
     36  1.1  mrg 
     37  1.1  mrg const char image_section_name[] = ".gnu.offload_images";
     38  1.1  mrg const char *symbols[3] = { "__offload_image_intelmic_start",
     39  1.1  mrg 			   "__offload_image_intelmic_end",
     40  1.1  mrg 			   "__offload_image_intelmic_size" };
     41  1.1  mrg const char *out_obj_filename = NULL;
     42  1.1  mrg 
     43  1.1  mrg int num_temps = 0;
     44  1.1  mrg const int MAX_NUM_TEMPS = 10;
     45  1.1  mrg const char *temp_files[MAX_NUM_TEMPS];
     46  1.1  mrg 
     47  1.1  mrg enum offload_abi offload_abi = OFFLOAD_ABI_UNSET;
     48  1.1  mrg 
     49  1.1  mrg /* Delete tempfiles and exit function.  */
     50  1.1  mrg 
     51  1.1  mrg void
     52  1.1  mrg tool_cleanup (bool from_signal ATTRIBUTE_UNUSED)
     53  1.1  mrg {
     54  1.1  mrg   for (int i = 0; i < num_temps; i++)
     55  1.1  mrg     maybe_unlink (temp_files[i]);
     56  1.1  mrg }
     57  1.1  mrg 
     58  1.1  mrg static void
     59  1.1  mrg mkoffload_cleanup (void)
     60  1.1  mrg {
     61  1.1  mrg   tool_cleanup (false);
     62  1.1  mrg }
     63  1.1  mrg 
     64  1.1  mrg /* Unlink FILE unless requested otherwise.  */
     65  1.1  mrg 
     66  1.1  mrg void
     67  1.1  mrg maybe_unlink (const char *file)
     68  1.1  mrg {
     69  1.1  mrg   if (!save_temps)
     70  1.1  mrg     {
     71  1.1  mrg       if (unlink_if_ordinary (file)
     72  1.1  mrg 	  && errno != ENOENT)
     73  1.1  mrg 	fatal_error (input_location, "deleting file %s: %m", file);
     74  1.1  mrg     }
     75  1.1  mrg   else if (verbose)
     76  1.1  mrg     fprintf (stderr, "[Leaving %s]\n", file);
     77  1.1  mrg }
     78  1.1  mrg 
     79  1.1  mrg /* Add or change the value of an environment variable, outputting the
     80  1.1  mrg    change to standard error if in verbose mode.  */
     81  1.1  mrg static void
     82  1.1  mrg xputenv (const char *string)
     83  1.1  mrg {
     84  1.1  mrg   if (verbose)
     85  1.1  mrg     fprintf (stderr, "%s\n", string);
     86  1.1  mrg   putenv (CONST_CAST (char *, string));
     87  1.1  mrg }
     88  1.1  mrg 
     89  1.1  mrg /* Parse STR, saving found tokens into PVALUES and return their number.
     90  1.1  mrg    Tokens are assumed to be delimited by ':'.  */
     91  1.1  mrg static unsigned
     92  1.1  mrg parse_env_var (const char *str, char ***pvalues)
     93  1.1  mrg {
     94  1.1  mrg   const char *curval, *nextval;
     95  1.1  mrg   char **values;
     96  1.1  mrg   unsigned num = 1, i;
     97  1.1  mrg 
     98  1.1  mrg   curval = strchr (str, ':');
     99  1.1  mrg   while (curval)
    100  1.1  mrg     {
    101  1.1  mrg       num++;
    102  1.1  mrg       curval = strchr (curval + 1, ':');
    103  1.1  mrg     }
    104  1.1  mrg 
    105  1.1  mrg   values = (char **) xmalloc (num * sizeof (char *));
    106  1.1  mrg   curval = str;
    107  1.1  mrg   nextval = strchr (curval, ':');
    108  1.1  mrg   if (nextval == NULL)
    109  1.1  mrg     nextval = strchr (curval, '\0');
    110  1.1  mrg 
    111  1.1  mrg   for (i = 0; i < num; i++)
    112  1.1  mrg     {
    113  1.1  mrg       int l = nextval - curval;
    114  1.1  mrg       values[i] = (char *) xmalloc (l + 1);
    115  1.1  mrg       memcpy (values[i], curval, l);
    116  1.1  mrg       values[i][l] = 0;
    117  1.1  mrg       curval = nextval + 1;
    118  1.1  mrg       nextval = strchr (curval, ':');
    119  1.1  mrg       if (nextval == NULL)
    120  1.1  mrg 	nextval = strchr (curval, '\0');
    121  1.1  mrg     }
    122  1.1  mrg   *pvalues = values;
    123  1.1  mrg   return num;
    124  1.1  mrg }
    125  1.1  mrg 
    126  1.1  mrg /* Auxiliary function that frees elements of PTR and PTR itself.
    127  1.1  mrg    N is number of elements to be freed.  If PTR is NULL, nothing is freed.
    128  1.1  mrg    If an element is NULL, subsequent elements are not freed.  */
    129  1.1  mrg static void
    130  1.1  mrg free_array_of_ptrs (void **ptr, unsigned n)
    131  1.1  mrg {
    132  1.1  mrg   unsigned i;
    133  1.1  mrg   if (!ptr)
    134  1.1  mrg     return;
    135  1.1  mrg   for (i = 0; i < n; i++)
    136  1.1  mrg     {
    137  1.1  mrg       if (!ptr[i])
    138  1.1  mrg 	break;
    139  1.1  mrg       free (ptr[i]);
    140  1.1  mrg     }
    141  1.1  mrg   free (ptr);
    142  1.1  mrg   return;
    143  1.1  mrg }
    144  1.1  mrg 
    145  1.1  mrg /* Check whether NAME can be accessed in MODE.  This is like access,
    146  1.1  mrg    except that it never considers directories to be executable.  */
    147  1.1  mrg static int
    148  1.1  mrg access_check (const char *name, int mode)
    149  1.1  mrg {
    150  1.1  mrg   if (mode == X_OK)
    151  1.1  mrg     {
    152  1.1  mrg       struct stat st;
    153  1.1  mrg 
    154  1.1  mrg       if (stat (name, &st) < 0 || S_ISDIR (st.st_mode))
    155  1.1  mrg 	return -1;
    156  1.1  mrg     }
    157  1.1  mrg 
    158  1.1  mrg   return access (name, mode);
    159  1.1  mrg }
    160  1.1  mrg 
    161  1.1  mrg /* Find target compiler using a path from COLLECT_GCC or COMPILER_PATH.  */
    162  1.1  mrg static char *
    163  1.1  mrg find_target_compiler (const char *name)
    164  1.1  mrg {
    165  1.1  mrg   bool found = false;
    166  1.1  mrg   char **paths = NULL;
    167  1.1  mrg   unsigned n_paths, i;
    168  1.1  mrg   char *target_compiler;
    169  1.1  mrg   const char *collect_gcc = getenv ("COLLECT_GCC");
    170  1.1  mrg   const char *gcc_path = dirname (ASTRDUP (collect_gcc));
    171  1.1  mrg   const char *gcc_exec = basename (ASTRDUP (collect_gcc));
    172  1.1  mrg 
    173  1.1  mrg   if (strcmp (gcc_exec, collect_gcc) == 0)
    174  1.1  mrg     {
    175  1.1  mrg       /* collect_gcc has no path, so it was found in PATH.  Make sure we also
    176  1.1  mrg 	 find accel-gcc in PATH.  */
    177  1.1  mrg       target_compiler = XDUPVEC (char, name, strlen (name) + 1);
    178  1.1  mrg       found = true;
    179  1.1  mrg       goto out;
    180  1.1  mrg     }
    181  1.1  mrg 
    182  1.1  mrg   target_compiler = concat (gcc_path, "/", name, NULL);
    183  1.1  mrg   if (access_check (target_compiler, X_OK) == 0)
    184  1.1  mrg     {
    185  1.1  mrg       found = true;
    186  1.1  mrg       goto out;
    187  1.1  mrg     }
    188  1.1  mrg 
    189  1.1  mrg   n_paths = parse_env_var (getenv ("COMPILER_PATH"), &paths);
    190  1.1  mrg   for (i = 0; i < n_paths; i++)
    191  1.1  mrg     {
    192  1.1  mrg       size_t len = strlen (paths[i]) + 1 + strlen (name) + 1;
    193  1.1  mrg       target_compiler = XRESIZEVEC (char, target_compiler, len);
    194  1.1  mrg       sprintf (target_compiler, "%s/%s", paths[i], name);
    195  1.1  mrg       if (access_check (target_compiler, X_OK) == 0)
    196  1.1  mrg 	{
    197  1.1  mrg 	  found = true;
    198  1.1  mrg 	  break;
    199  1.1  mrg 	}
    200  1.1  mrg     }
    201  1.1  mrg 
    202  1.1  mrg out:
    203  1.1  mrg   free_array_of_ptrs ((void **) paths, n_paths);
    204  1.1  mrg   return found ? target_compiler : NULL;
    205  1.1  mrg }
    206  1.1  mrg 
    207  1.1  mrg static void
    208  1.1  mrg compile_for_target (struct obstack *argv_obstack)
    209  1.1  mrg {
    210  1.1  mrg   switch (offload_abi)
    211  1.1  mrg     {
    212  1.1  mrg     case OFFLOAD_ABI_LP64:
    213  1.1  mrg       obstack_ptr_grow (argv_obstack, "-m64");
    214  1.1  mrg       break;
    215  1.1  mrg     case OFFLOAD_ABI_ILP32:
    216  1.1  mrg       obstack_ptr_grow (argv_obstack, "-m32");
    217  1.1  mrg       break;
    218  1.1  mrg     default:
    219  1.1  mrg       gcc_unreachable ();
    220  1.1  mrg     }
    221  1.1  mrg   obstack_ptr_grow (argv_obstack, NULL);
    222  1.1  mrg   char **argv = XOBFINISH (argv_obstack, char **);
    223  1.1  mrg 
    224  1.1  mrg   /* Save environment variables.  */
    225  1.1  mrg   const char *epath = getenv ("GCC_EXEC_PREFIX");
    226  1.1  mrg   const char *cpath = getenv ("COMPILER_PATH");
    227  1.1  mrg   const char *lpath = getenv ("LIBRARY_PATH");
    228  1.1  mrg   const char *rpath = getenv ("LD_RUN_PATH");
    229  1.1  mrg   unsetenv ("GCC_EXEC_PREFIX");
    230  1.1  mrg   unsetenv ("COMPILER_PATH");
    231  1.1  mrg   unsetenv ("LIBRARY_PATH");
    232  1.1  mrg   unsetenv ("LD_RUN_PATH");
    233  1.1  mrg 
    234  1.1  mrg   fork_execute (argv[0], argv, false, NULL);
    235  1.1  mrg   obstack_free (argv_obstack, NULL);
    236  1.1  mrg 
    237  1.1  mrg   /* Restore environment variables.  */
    238  1.1  mrg   xputenv (concat ("GCC_EXEC_PREFIX=", epath, NULL));
    239  1.1  mrg   xputenv (concat ("COMPILER_PATH=", cpath, NULL));
    240  1.1  mrg   xputenv (concat ("LIBRARY_PATH=", lpath, NULL));
    241  1.1  mrg   xputenv (concat ("LD_RUN_PATH=", rpath, NULL));
    242  1.1  mrg }
    243  1.1  mrg 
    244  1.1  mrg /* Generates object file with the descriptor for the target library.  */
    245  1.1  mrg static const char *
    246  1.1  mrg generate_target_descr_file (const char *target_compiler)
    247  1.1  mrg {
    248  1.1  mrg   char *dump_filename = concat (dumppfx, "_target_descr.c", NULL);
    249  1.1  mrg   const char *src_filename = save_temps
    250  1.1  mrg     ? dump_filename
    251  1.1  mrg     : make_temp_file ("_target_descr.c");
    252  1.1  mrg   const char *obj_filename = save_temps
    253  1.1  mrg     ? concat (dumppfx, "_target_descr.o", NULL)
    254  1.1  mrg     : make_temp_file ("_target_descr.o");
    255  1.1  mrg   temp_files[num_temps++] = src_filename;
    256  1.1  mrg   temp_files[num_temps++] = obj_filename;
    257  1.1  mrg   FILE *src_file = fopen (src_filename, "w");
    258  1.1  mrg 
    259  1.1  mrg   if (!src_file)
    260  1.1  mrg     fatal_error (input_location, "cannot open '%s'", src_filename);
    261  1.1  mrg 
    262  1.1  mrg   fprintf (src_file,
    263  1.1  mrg 	   "extern const void *const __offload_funcs_end[];\n"
    264  1.1  mrg 	   "extern const void *const __offload_vars_end[];\n\n"
    265  1.1  mrg 
    266  1.1  mrg 	   "const void *const __offload_func_table[0]\n"
    267  1.1  mrg 	   "__attribute__ ((__used__, visibility (\"hidden\"),\n"
    268  1.1  mrg 	   "section (\".gnu.offload_funcs\"))) = { };\n\n"
    269  1.1  mrg 
    270  1.1  mrg 	   "const void *const __offload_var_table[0]\n"
    271  1.1  mrg 	   "__attribute__ ((__used__, visibility (\"hidden\"),\n"
    272  1.1  mrg 	   "section (\".gnu.offload_vars\"))) = { };\n\n"
    273  1.1  mrg 
    274  1.1  mrg 	   "const void *const __OFFLOAD_TARGET_TABLE__[]\n"
    275  1.1  mrg 	   "__attribute__ ((__used__, visibility (\"hidden\"))) = {\n"
    276  1.1  mrg 	   "  &__offload_func_table, &__offload_funcs_end,\n"
    277  1.1  mrg 	   "  &__offload_var_table, &__offload_vars_end\n"
    278  1.1  mrg 	   "};\n\n");
    279  1.1  mrg 
    280  1.1  mrg   fprintf (src_file,
    281  1.1  mrg 	   "#ifdef __cplusplus\n"
    282  1.1  mrg 	   "extern \"C\"\n"
    283  1.1  mrg 	   "#endif\n"
    284  1.1  mrg 	   "void target_register_lib (const void *);\n\n"
    285  1.1  mrg 
    286  1.1  mrg 	   "__attribute__((constructor))\n"
    287  1.1  mrg 	   "static void\n"
    288  1.1  mrg 	   "init (void)\n"
    289  1.1  mrg 	   "{\n"
    290  1.1  mrg 	   "  target_register_lib (__OFFLOAD_TARGET_TABLE__);\n"
    291  1.1  mrg 	   "}\n");
    292  1.1  mrg   fclose (src_file);
    293  1.1  mrg 
    294  1.1  mrg   struct obstack argv_obstack;
    295  1.1  mrg   obstack_init (&argv_obstack);
    296  1.1  mrg   obstack_ptr_grow (&argv_obstack, target_compiler);
    297  1.1  mrg   if (save_temps)
    298  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-save-temps");
    299  1.1  mrg   if (verbose)
    300  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-v");
    301  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpdir");
    302  1.1  mrg   obstack_ptr_grow (&argv_obstack, "");
    303  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase");
    304  1.1  mrg   obstack_ptr_grow (&argv_obstack, dump_filename);
    305  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase-ext");
    306  1.1  mrg   obstack_ptr_grow (&argv_obstack, ".c");
    307  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-c");
    308  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-shared");
    309  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-fPIC");
    310  1.1  mrg   obstack_ptr_grow (&argv_obstack, src_filename);
    311  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-o");
    312  1.1  mrg   obstack_ptr_grow (&argv_obstack, obj_filename);
    313  1.1  mrg   compile_for_target (&argv_obstack);
    314  1.1  mrg 
    315  1.1  mrg   return obj_filename;
    316  1.1  mrg }
    317  1.1  mrg 
    318  1.1  mrg /* Generates object file with __offload_*_end symbols for the target
    319  1.1  mrg    library.  */
    320  1.1  mrg static const char *
    321  1.1  mrg generate_target_offloadend_file (const char *target_compiler)
    322  1.1  mrg {
    323  1.1  mrg   char *dump_filename = concat (dumppfx, "_target_offloadend.c", NULL);
    324  1.1  mrg   const char *src_filename = save_temps
    325  1.1  mrg     ? dump_filename
    326  1.1  mrg     : make_temp_file ("_target_offloadend.c");
    327  1.1  mrg   const char *obj_filename = save_temps
    328  1.1  mrg     ? concat (dumppfx, "_target_offloadend.o", NULL)
    329  1.1  mrg     : make_temp_file ("_target_offloadend.o");
    330  1.1  mrg   temp_files[num_temps++] = src_filename;
    331  1.1  mrg   temp_files[num_temps++] = obj_filename;
    332  1.1  mrg   FILE *src_file = fopen (src_filename, "w");
    333  1.1  mrg 
    334  1.1  mrg   if (!src_file)
    335  1.1  mrg     fatal_error (input_location, "cannot open '%s'", src_filename);
    336  1.1  mrg 
    337  1.1  mrg   fprintf (src_file,
    338  1.1  mrg 	   "const void *const __offload_funcs_end[0]\n"
    339  1.1  mrg 	   "__attribute__ ((__used__, visibility (\"hidden\"),\n"
    340  1.1  mrg 	   "section (\".gnu.offload_funcs\"))) = { };\n\n"
    341  1.1  mrg 
    342  1.1  mrg 	   "const void *const __offload_vars_end[0]\n"
    343  1.1  mrg 	   "__attribute__ ((__used__, visibility (\"hidden\"),\n"
    344  1.1  mrg 	   "section (\".gnu.offload_vars\"))) = { };\n");
    345  1.1  mrg   fclose (src_file);
    346  1.1  mrg 
    347  1.1  mrg   struct obstack argv_obstack;
    348  1.1  mrg   obstack_init (&argv_obstack);
    349  1.1  mrg   obstack_ptr_grow (&argv_obstack, target_compiler);
    350  1.1  mrg   if (save_temps)
    351  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-save-temps");
    352  1.1  mrg   if (verbose)
    353  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-v");
    354  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpdir");
    355  1.1  mrg   obstack_ptr_grow (&argv_obstack, "");
    356  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase");
    357  1.1  mrg   obstack_ptr_grow (&argv_obstack, dump_filename);
    358  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase-ext");
    359  1.1  mrg   obstack_ptr_grow (&argv_obstack, ".c");
    360  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-c");
    361  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-shared");
    362  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-fPIC");
    363  1.1  mrg   obstack_ptr_grow (&argv_obstack, src_filename);
    364  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-o");
    365  1.1  mrg   obstack_ptr_grow (&argv_obstack, obj_filename);
    366  1.1  mrg   compile_for_target (&argv_obstack);
    367  1.1  mrg 
    368  1.1  mrg   return obj_filename;
    369  1.1  mrg }
    370  1.1  mrg 
    371  1.1  mrg /* Generates object file with the host side descriptor.  */
    372  1.1  mrg static const char *
    373  1.1  mrg generate_host_descr_file (const char *host_compiler)
    374  1.1  mrg {
    375  1.1  mrg   char *dump_filename = concat (dumppfx, "_host_descr.c", NULL);
    376  1.1  mrg   const char *src_filename = save_temps
    377  1.1  mrg     ? dump_filename
    378  1.1  mrg     : make_temp_file ("_host_descr.c");
    379  1.1  mrg   const char *obj_filename = save_temps
    380  1.1  mrg     ? concat (dumppfx, "_host_descr.o", NULL)
    381  1.1  mrg     : make_temp_file ("_host_descr.o");
    382  1.1  mrg   temp_files[num_temps++] = src_filename;
    383  1.1  mrg   temp_files[num_temps++] = obj_filename;
    384  1.1  mrg   FILE *src_file = fopen (src_filename, "w");
    385  1.1  mrg 
    386  1.1  mrg   if (!src_file)
    387  1.1  mrg     fatal_error (input_location, "cannot open '%s'", src_filename);
    388  1.1  mrg 
    389  1.1  mrg   fprintf (src_file,
    390  1.1  mrg 	   "extern const void *const __OFFLOAD_TABLE__;\n"
    391  1.1  mrg 	   "extern const void *const __offload_image_intelmic_start;\n"
    392  1.1  mrg 	   "extern const void *const __offload_image_intelmic_end;\n\n"
    393  1.1  mrg 
    394  1.1  mrg 	   "static const void *const __offload_target_data[] = {\n"
    395  1.1  mrg 	   "  &__offload_image_intelmic_start, &__offload_image_intelmic_end\n"
    396  1.1  mrg 	   "};\n\n");
    397  1.1  mrg 
    398  1.1  mrg   fprintf (src_file,
    399  1.1  mrg 	   "#ifdef __cplusplus\n"
    400  1.1  mrg 	   "extern \"C\"\n"
    401  1.1  mrg 	   "#endif\n"
    402  1.1  mrg 	   "void GOMP_offload_register (const void *, int, const void *);\n"
    403  1.1  mrg 	   "#ifdef __cplusplus\n"
    404  1.1  mrg 	   "extern \"C\"\n"
    405  1.1  mrg 	   "#endif\n"
    406  1.1  mrg 	   "void GOMP_offload_unregister (const void *, int, const void *);\n\n"
    407  1.1  mrg 
    408  1.1  mrg 	   "__attribute__((constructor))\n"
    409  1.1  mrg 	   "static void\n"
    410  1.1  mrg 	   "init (void)\n"
    411  1.1  mrg 	   "{\n"
    412  1.1  mrg 	   "  GOMP_offload_register (&__OFFLOAD_TABLE__, %d, __offload_target_data);\n"
    413  1.1  mrg 	   "}\n\n", GOMP_DEVICE_INTEL_MIC);
    414  1.1  mrg 
    415  1.1  mrg   fprintf (src_file,
    416  1.1  mrg 	   "__attribute__((destructor))\n"
    417  1.1  mrg 	   "static void\n"
    418  1.1  mrg 	   "fini (void)\n"
    419  1.1  mrg 	   "{\n"
    420  1.1  mrg 	   "  GOMP_offload_unregister (&__OFFLOAD_TABLE__, %d, __offload_target_data);\n"
    421  1.1  mrg 	   "}\n", GOMP_DEVICE_INTEL_MIC);
    422  1.1  mrg 
    423  1.1  mrg   fclose (src_file);
    424  1.1  mrg 
    425  1.1  mrg   struct obstack argv_obstack;
    426  1.1  mrg   obstack_init (&argv_obstack);
    427  1.1  mrg   obstack_ptr_grow (&argv_obstack, host_compiler);
    428  1.1  mrg   if (save_temps)
    429  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-save-temps");
    430  1.1  mrg   if (verbose)
    431  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-v");
    432  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpdir");
    433  1.1  mrg   obstack_ptr_grow (&argv_obstack, "");
    434  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase");
    435  1.1  mrg   obstack_ptr_grow (&argv_obstack, dump_filename);
    436  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase-ext");
    437  1.1  mrg   obstack_ptr_grow (&argv_obstack, ".c");
    438  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-c");
    439  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-fPIC");
    440  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-shared");
    441  1.1  mrg   switch (offload_abi)
    442  1.1  mrg     {
    443  1.1  mrg     case OFFLOAD_ABI_LP64:
    444  1.1  mrg       obstack_ptr_grow (&argv_obstack, "-m64");
    445  1.1  mrg       break;
    446  1.1  mrg     case OFFLOAD_ABI_ILP32:
    447  1.1  mrg       obstack_ptr_grow (&argv_obstack, "-m32");
    448  1.1  mrg       break;
    449  1.1  mrg     default:
    450  1.1  mrg       gcc_unreachable ();
    451  1.1  mrg     }
    452  1.1  mrg   obstack_ptr_grow (&argv_obstack, src_filename);
    453  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-o");
    454  1.1  mrg   obstack_ptr_grow (&argv_obstack, obj_filename);
    455  1.1  mrg   obstack_ptr_grow (&argv_obstack, NULL);
    456  1.1  mrg 
    457  1.1  mrg   char **argv = XOBFINISH (&argv_obstack, char **);
    458  1.1  mrg   fork_execute (argv[0], argv, false, NULL);
    459  1.1  mrg   obstack_free (&argv_obstack, NULL);
    460  1.1  mrg 
    461  1.1  mrg   return obj_filename;
    462  1.1  mrg }
    463  1.1  mrg 
    464  1.1  mrg static const char *
    465  1.1  mrg prepare_target_image (const char *target_compiler, int argc, char **argv)
    466  1.1  mrg {
    467  1.1  mrg   const char *target_descr_filename
    468  1.1  mrg     = generate_target_descr_file (target_compiler);
    469  1.1  mrg   const char *target_offloadend_filename
    470  1.1  mrg     = generate_target_offloadend_file (target_compiler);
    471  1.1  mrg 
    472  1.1  mrg   char *opt1
    473  1.1  mrg     = XALLOCAVEC (char, sizeof ("-Wl,") + strlen (target_descr_filename));
    474  1.1  mrg   char *opt2
    475  1.1  mrg     = XALLOCAVEC (char, sizeof ("-Wl,") + strlen (target_offloadend_filename));
    476  1.1  mrg   sprintf (opt1, "-Wl,%s", target_descr_filename);
    477  1.1  mrg   sprintf (opt2, "-Wl,%s", target_offloadend_filename);
    478  1.1  mrg 
    479  1.1  mrg   char *dump_filename = concat (dumppfx, ".mkoffload", NULL);
    480  1.1  mrg   const char *target_so_filename = save_temps
    481  1.1  mrg     ? concat (dumppfx, "_offload_intelmic.so", NULL)
    482  1.1  mrg     : make_temp_file ("_offload_intelmic.so");
    483  1.1  mrg   temp_files[num_temps++] = target_so_filename;
    484  1.1  mrg   struct obstack argv_obstack;
    485  1.1  mrg   obstack_init (&argv_obstack);
    486  1.1  mrg   obstack_ptr_grow (&argv_obstack, target_compiler);
    487  1.1  mrg   if (save_temps)
    488  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-save-temps");
    489  1.1  mrg   if (verbose)
    490  1.1  mrg     obstack_ptr_grow (&argv_obstack, "-v");
    491  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-xlto");
    492  1.1  mrg   obstack_ptr_grow (&argv_obstack, opt1);
    493  1.1  mrg   for (int i = 1; i < argc; i++)
    494  1.1  mrg     {
    495  1.1  mrg       if (!strcmp (argv[i], "-o") && i + 1 != argc)
    496  1.1  mrg 	++i;
    497  1.1  mrg       else
    498  1.1  mrg 	obstack_ptr_grow (&argv_obstack, argv[i]);
    499  1.1  mrg     }
    500  1.1  mrg   obstack_ptr_grow (&argv_obstack, opt2);
    501  1.1  mrg   /* NB: Put -fPIC and -shared the last to create shared library.  */
    502  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-fPIC");
    503  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-shared");
    504  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpdir");
    505  1.1  mrg   obstack_ptr_grow (&argv_obstack, "");
    506  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase");
    507  1.1  mrg   obstack_ptr_grow (&argv_obstack, dump_filename);
    508  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-dumpbase-ext");
    509  1.1  mrg   obstack_ptr_grow (&argv_obstack, "");
    510  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-o");
    511  1.1  mrg   obstack_ptr_grow (&argv_obstack, target_so_filename);
    512  1.1  mrg   compile_for_target (&argv_obstack);
    513  1.1  mrg 
    514  1.1  mrg   /* Run objcopy.  */
    515  1.1  mrg   char *rename_section_opt
    516  1.1  mrg     = XALLOCAVEC (char, sizeof (".data=") + strlen (image_section_name));
    517  1.1  mrg   sprintf (rename_section_opt, ".data=%s", image_section_name);
    518  1.1  mrg   obstack_init (&argv_obstack);
    519  1.1  mrg   obstack_ptr_grow (&argv_obstack, "objcopy");
    520  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-B");
    521  1.1  mrg   obstack_ptr_grow (&argv_obstack, "i386");
    522  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-I");
    523  1.1  mrg   obstack_ptr_grow (&argv_obstack, "binary");
    524  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-O");
    525  1.1  mrg   switch (offload_abi)
    526  1.1  mrg     {
    527  1.1  mrg     case OFFLOAD_ABI_LP64:
    528  1.1  mrg       obstack_ptr_grow (&argv_obstack, "elf64-x86-64");
    529  1.1  mrg       break;
    530  1.1  mrg     case OFFLOAD_ABI_ILP32:
    531  1.1  mrg       obstack_ptr_grow (&argv_obstack, "elf32-i386");
    532  1.1  mrg       break;
    533  1.1  mrg     default:
    534  1.1  mrg       gcc_unreachable ();
    535  1.1  mrg     }
    536  1.1  mrg   obstack_ptr_grow (&argv_obstack, target_so_filename);
    537  1.1  mrg   obstack_ptr_grow (&argv_obstack, "--rename-section");
    538  1.1  mrg   obstack_ptr_grow (&argv_obstack, rename_section_opt);
    539  1.1  mrg   obstack_ptr_grow (&argv_obstack, NULL);
    540  1.1  mrg   char **new_argv = XOBFINISH (&argv_obstack, char **);
    541  1.1  mrg   fork_execute (new_argv[0], new_argv, false, NULL);
    542  1.1  mrg   obstack_free (&argv_obstack, NULL);
    543  1.1  mrg 
    544  1.1  mrg   /* Objcopy has created symbols, containing the input file name with
    545  1.1  mrg      non-alphanumeric characters replaced by underscores.
    546  1.1  mrg      We are going to rename these new symbols.  */
    547  1.1  mrg   size_t symbol_name_len = strlen (target_so_filename);
    548  1.1  mrg   char *symbol_name = XALLOCAVEC (char, symbol_name_len + 1);
    549  1.1  mrg   for (size_t i = 0; i < symbol_name_len; i++)
    550  1.1  mrg     {
    551  1.1  mrg       char c = target_so_filename[i];
    552  1.1  mrg       if (!ISALNUM (c))
    553  1.1  mrg 	c = '_';
    554  1.1  mrg       symbol_name[i] = c;
    555  1.1  mrg     }
    556  1.1  mrg   symbol_name[symbol_name_len] = '\0';
    557  1.1  mrg 
    558  1.1  mrg   char *opt_for_objcopy[3];
    559  1.1  mrg   opt_for_objcopy[0] = XALLOCAVEC (char, sizeof ("_binary__start=")
    560  1.1  mrg 					 + symbol_name_len
    561  1.1  mrg 					 + strlen (symbols[0]));
    562  1.1  mrg   opt_for_objcopy[1] = XALLOCAVEC (char, sizeof ("_binary__end=")
    563  1.1  mrg 					 + symbol_name_len
    564  1.1  mrg 					 + strlen (symbols[1]));
    565  1.1  mrg   opt_for_objcopy[2] = XALLOCAVEC (char, sizeof ("_binary__size=")
    566  1.1  mrg 					 + symbol_name_len
    567  1.1  mrg 					 + strlen (symbols[2]));
    568  1.1  mrg   sprintf (opt_for_objcopy[0], "_binary_%s_start=%s", symbol_name, symbols[0]);
    569  1.1  mrg   sprintf (opt_for_objcopy[1], "_binary_%s_end=%s", symbol_name, symbols[1]);
    570  1.1  mrg   sprintf (opt_for_objcopy[2], "_binary_%s_size=%s", symbol_name, symbols[2]);
    571  1.1  mrg 
    572  1.1  mrg   obstack_init (&argv_obstack);
    573  1.1  mrg   obstack_ptr_grow (&argv_obstack, "objcopy");
    574  1.1  mrg   obstack_ptr_grow (&argv_obstack, target_so_filename);
    575  1.1  mrg   obstack_ptr_grow (&argv_obstack, "--redefine-sym");
    576  1.1  mrg   obstack_ptr_grow (&argv_obstack, opt_for_objcopy[0]);
    577  1.1  mrg   obstack_ptr_grow (&argv_obstack, "--redefine-sym");
    578  1.1  mrg   obstack_ptr_grow (&argv_obstack, opt_for_objcopy[1]);
    579  1.1  mrg   obstack_ptr_grow (&argv_obstack, "--redefine-sym");
    580  1.1  mrg   obstack_ptr_grow (&argv_obstack, opt_for_objcopy[2]);
    581  1.1  mrg   obstack_ptr_grow (&argv_obstack, NULL);
    582  1.1  mrg   new_argv = XOBFINISH (&argv_obstack, char **);
    583  1.1  mrg   fork_execute (new_argv[0], new_argv, false, NULL);
    584  1.1  mrg   obstack_free (&argv_obstack, NULL);
    585  1.1  mrg 
    586  1.1  mrg   return target_so_filename;
    587  1.1  mrg }
    588  1.1  mrg 
    589  1.1  mrg int
    590  1.1  mrg main (int argc, char **argv)
    591  1.1  mrg {
    592  1.1  mrg   progname = "mkoffload-intelmic";
    593  1.1  mrg   gcc_init_libintl ();
    594  1.1  mrg   diagnostic_initialize (global_dc, 0);
    595  1.1  mrg 
    596  1.1  mrg   if (atexit (mkoffload_cleanup) != 0)
    597  1.1  mrg     fatal_error (input_location, "atexit failed");
    598  1.1  mrg 
    599  1.1  mrg   const char *host_compiler = getenv ("COLLECT_GCC");
    600  1.1  mrg   if (!host_compiler)
    601  1.1  mrg     fatal_error (input_location, "COLLECT_GCC must be set");
    602  1.1  mrg 
    603  1.1  mrg   const char *target_driver_name = GCC_INSTALL_NAME;
    604  1.1  mrg   char *target_compiler = find_target_compiler (target_driver_name);
    605  1.1  mrg   if (target_compiler == NULL)
    606  1.1  mrg     fatal_error (input_location, "offload compiler %s not found",
    607  1.1  mrg 		 target_driver_name);
    608  1.1  mrg 
    609  1.1  mrg   /* We may be called with all the arguments stored in some file and
    610  1.1  mrg      passed with @file.  Expand them into argv before processing.  */
    611  1.1  mrg   expandargv (&argc, &argv);
    612  1.1  mrg 
    613  1.1  mrg   /* Scan the argument vector.  */
    614  1.1  mrg   for (int i = 1; i < argc; i++)
    615  1.1  mrg     {
    616  1.1  mrg #define STR "-foffload-abi="
    617  1.1  mrg       if (startswith (argv[i], STR))
    618  1.1  mrg 	{
    619  1.1  mrg 	  if (strcmp (argv[i] + strlen (STR), "lp64") == 0)
    620  1.1  mrg 	    offload_abi = OFFLOAD_ABI_LP64;
    621  1.1  mrg 	  else if (strcmp (argv[i] + strlen (STR), "ilp32") == 0)
    622  1.1  mrg 	    offload_abi = OFFLOAD_ABI_ILP32;
    623  1.1  mrg 	  else
    624  1.1  mrg 	    fatal_error (input_location,
    625  1.1  mrg 			 "unrecognizable argument of option " STR);
    626  1.1  mrg 	}
    627  1.1  mrg #undef STR
    628  1.1  mrg       else if (strcmp (argv[i], "-save-temps") == 0)
    629  1.1  mrg 	save_temps = true;
    630  1.1  mrg       else if (strcmp (argv[i], "-v") == 0)
    631  1.1  mrg 	verbose = true;
    632  1.1  mrg       else if (strcmp (argv[i], "-dumpbase") == 0
    633  1.1  mrg 	       && i + 1 < argc)
    634  1.1  mrg 	dumppfx = argv[++i];
    635  1.1  mrg       else if (strcmp (argv[i], "-o") == 0
    636  1.1  mrg 	       && i + 1 < argc)
    637  1.1  mrg 	out_obj_filename = argv[++i];
    638  1.1  mrg     }
    639  1.1  mrg 
    640  1.1  mrg   if (!out_obj_filename)
    641  1.1  mrg     fatal_error (input_location, "output file not specified");
    642  1.1  mrg 
    643  1.1  mrg   if (!dumppfx)
    644  1.1  mrg     dumppfx = out_obj_filename;
    645  1.1  mrg 
    646  1.1  mrg   const char *target_so_filename
    647  1.1  mrg     = prepare_target_image (target_compiler, argc, argv);
    648  1.1  mrg 
    649  1.1  mrg   const char *host_descr_filename = generate_host_descr_file (host_compiler);
    650  1.1  mrg 
    651  1.1  mrg   /* Perform partial linking for the target image and host side descriptor.
    652  1.1  mrg      As a result we'll get a finalized object file with all offload data.  */
    653  1.1  mrg   struct obstack argv_obstack;
    654  1.1  mrg   obstack_init (&argv_obstack);
    655  1.1  mrg   obstack_ptr_grow (&argv_obstack, "ld");
    656  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-m");
    657  1.1  mrg   switch (offload_abi)
    658  1.1  mrg     {
    659  1.1  mrg     case OFFLOAD_ABI_LP64:
    660  1.1  mrg       obstack_ptr_grow (&argv_obstack, "elf_x86_64");
    661  1.1  mrg       break;
    662  1.1  mrg     case OFFLOAD_ABI_ILP32:
    663  1.1  mrg       obstack_ptr_grow (&argv_obstack, "elf_i386");
    664  1.1  mrg       break;
    665  1.1  mrg     default:
    666  1.1  mrg       gcc_unreachable ();
    667  1.1  mrg     }
    668  1.1  mrg   obstack_ptr_grow (&argv_obstack, "--relocatable");
    669  1.1  mrg   obstack_ptr_grow (&argv_obstack, host_descr_filename);
    670  1.1  mrg   obstack_ptr_grow (&argv_obstack, target_so_filename);
    671  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-o");
    672  1.1  mrg   obstack_ptr_grow (&argv_obstack, out_obj_filename);
    673  1.1  mrg   obstack_ptr_grow (&argv_obstack, NULL);
    674  1.1  mrg   char **new_argv = XOBFINISH (&argv_obstack, char **);
    675  1.1  mrg   fork_execute (new_argv[0], new_argv, false, NULL);
    676  1.1  mrg   obstack_free (&argv_obstack, NULL);
    677  1.1  mrg 
    678  1.1  mrg   /* Run objcopy on the resultant object file to localize generated symbols
    679  1.1  mrg      to avoid conflicting between different DSO and an executable.  */
    680  1.1  mrg   obstack_init (&argv_obstack);
    681  1.1  mrg   obstack_ptr_grow (&argv_obstack, "objcopy");
    682  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-L");
    683  1.1  mrg   obstack_ptr_grow (&argv_obstack, symbols[0]);
    684  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-L");
    685  1.1  mrg   obstack_ptr_grow (&argv_obstack, symbols[1]);
    686  1.1  mrg   obstack_ptr_grow (&argv_obstack, "-L");
    687  1.1  mrg   obstack_ptr_grow (&argv_obstack, symbols[2]);
    688  1.1  mrg   obstack_ptr_grow (&argv_obstack, out_obj_filename);
    689  1.1  mrg   obstack_ptr_grow (&argv_obstack, NULL);
    690  1.1  mrg   new_argv = XOBFINISH (&argv_obstack, char **);
    691  1.1  mrg   fork_execute (new_argv[0], new_argv, false, NULL);
    692  1.1  mrg   obstack_free (&argv_obstack, NULL);
    693  1.1  mrg 
    694  1.1  mrg   return 0;
    695  1.1  mrg }
    696