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