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