]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/gcn/mkoffload.cc
Daily bump.
[thirdparty/gcc.git] / gcc / config / gcn / mkoffload.cc
1 /* Offload image generation tool for AMD GCN.
2
3 Copyright (C) 2014-2024 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 /* Munges GCN assembly into a C source file defining the GCN code as a
22 string.
23
24 This is not a complete assembler. We presume the source is well
25 formed from the compiler and can die horribly if it is not. */
26
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "obstack.h"
31 #include "diagnostic.h"
32 #include "intl.h"
33 #include <libgen.h>
34 #include "collect-utils.h"
35 #include "gomp-constants.h"
36 #include "simple-object.h"
37 #include "elf.h"
38 #include "configargs.h" /* For configure_default_options. */
39 #include "multilib.h" /* For multilib_options. */
40
41 /* These probably won't (all) be in elf.h for a while. */
42 #undef EM_AMDGPU
43 #define EM_AMDGPU 0xe0;
44
45 #undef ELFOSABI_AMDGPU_HSA
46 #define ELFOSABI_AMDGPU_HSA 64
47 #undef ELFABIVERSION_AMDGPU_HSA_V3
48 #define ELFABIVERSION_AMDGPU_HSA_V3 1
49 #undef ELFABIVERSION_AMDGPU_HSA_V4
50 #define ELFABIVERSION_AMDGPU_HSA_V4 2
51
52 #undef EF_AMDGPU_MACH_AMDGCN_GFX803
53 #define EF_AMDGPU_MACH_AMDGCN_GFX803 0x2a
54 #undef EF_AMDGPU_MACH_AMDGCN_GFX900
55 #define EF_AMDGPU_MACH_AMDGCN_GFX900 0x2c
56 #undef EF_AMDGPU_MACH_AMDGCN_GFX906
57 #define EF_AMDGPU_MACH_AMDGCN_GFX906 0x2f
58 #undef EF_AMDGPU_MACH_AMDGCN_GFX908
59 #define EF_AMDGPU_MACH_AMDGCN_GFX908 0x30
60 #undef EF_AMDGPU_MACH_AMDGCN_GFX90a
61 #define EF_AMDGPU_MACH_AMDGCN_GFX90a 0x3f
62 #undef EF_AMDGPU_MACH_AMDGCN_GFX90c
63 #define EF_AMDGPU_MACH_AMDGCN_GFX90c 0x32
64 #undef EF_AMDGPU_MACH_AMDGCN_GFX1030
65 #define EF_AMDGPU_MACH_AMDGCN_GFX1030 0x36
66 #undef EF_AMDGPU_MACH_AMDGCN_GFX1036
67 #define EF_AMDGPU_MACH_AMDGCN_GFX1036 0x45
68 #undef EF_AMDGPU_MACH_AMDGCN_GFX1100
69 #define EF_AMDGPU_MACH_AMDGCN_GFX1100 0x41
70 #undef EF_AMDGPU_MACH_AMDGCN_GFX1103
71 #define EF_AMDGPU_MACH_AMDGCN_GFX1103 0x44
72
73 #define EF_AMDGPU_FEATURE_XNACK_V4 0x300 /* Mask. */
74 #define EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 0x000
75 #define EF_AMDGPU_FEATURE_XNACK_ANY_V4 0x100
76 #define EF_AMDGPU_FEATURE_XNACK_OFF_V4 0x200
77 #define EF_AMDGPU_FEATURE_XNACK_ON_V4 0x300
78
79 #define EF_AMDGPU_FEATURE_SRAMECC_V4 0xc00 /* Mask. */
80 #define EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 0x000
81 #define EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 0x400
82 #define EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 0x800
83 #define EF_AMDGPU_FEATURE_SRAMECC_ON_V4 0xc00
84
85 #define SET_XNACK_ON(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
86 | EF_AMDGPU_FEATURE_XNACK_ON_V4)
87 #define SET_XNACK_ANY(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
88 | EF_AMDGPU_FEATURE_XNACK_ANY_V4)
89 #define SET_XNACK_OFF(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
90 | EF_AMDGPU_FEATURE_XNACK_OFF_V4)
91 #define SET_XNACK_UNSET(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_XNACK_V4) \
92 | EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4)
93 #define TEST_XNACK_ANY(VAR) ((VAR & EF_AMDGPU_FEATURE_XNACK_V4) \
94 == EF_AMDGPU_FEATURE_XNACK_ANY_V4)
95 #define TEST_XNACK_ON(VAR) ((VAR & EF_AMDGPU_FEATURE_XNACK_V4) \
96 == EF_AMDGPU_FEATURE_XNACK_ON_V4)
97 #define TEST_XNACK_OFF(VAR) ((VAR & EF_AMDGPU_FEATURE_XNACK_V4) \
98 == EF_AMDGPU_FEATURE_XNACK_OFF_V4)
99 #define TEST_XNACK_UNSET(VAR) ((VAR & EF_AMDGPU_FEATURE_XNACK_V4) == 0)
100
101 #define SET_SRAM_ECC_ON(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
102 | EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
103 #define SET_SRAM_ECC_ANY(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
104 | EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
105 #define SET_SRAM_ECC_OFF(VAR) VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
106 | EF_AMDGPU_FEATURE_SRAMECC_OFF_V4)
107 #define SET_SRAM_ECC_UNSET(VAR) \
108 VAR = ((VAR & ~EF_AMDGPU_FEATURE_SRAMECC_V4) \
109 | EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4)
110 #define TEST_SRAM_ECC_ANY(VAR) ((VAR & EF_AMDGPU_FEATURE_SRAMECC_V4) \
111 == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
112 #define TEST_SRAM_ECC_ON(VAR) ((VAR & EF_AMDGPU_FEATURE_SRAMECC_V4) \
113 == EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
114 #define TEST_SRAM_ECC_UNSET(VAR) ((VAR & EF_AMDGPU_FEATURE_SRAMECC_V4) == 0)
115
116 #ifndef R_AMDGPU_NONE
117 #define R_AMDGPU_NONE 0
118 #define R_AMDGPU_ABS32_LO 1 /* (S + A) & 0xFFFFFFFF */
119 #define R_AMDGPU_ABS32_HI 2 /* (S + A) >> 32 */
120 #define R_AMDGPU_ABS64 3 /* S + A */
121 #define R_AMDGPU_REL32 4 /* S + A - P */
122 #define R_AMDGPU_REL64 5 /* S + A - P */
123 #define R_AMDGPU_ABS32 6 /* S + A */
124 #define R_AMDGPU_GOTPCREL 7 /* G + GOT + A - P */
125 #define R_AMDGPU_GOTPCREL32_LO 8 /* (G + GOT + A - P) & 0xFFFFFFFF */
126 #define R_AMDGPU_GOTPCREL32_HI 9 /* (G + GOT + A - P) >> 32 */
127 #define R_AMDGPU_REL32_LO 10 /* (S + A - P) & 0xFFFFFFFF */
128 #define R_AMDGPU_REL32_HI 11 /* (S + A - P) >> 32 */
129 #define R_AMDGPU_RELATIVE64 13 /* B + A */
130 #endif
131
132 const char tool_name[] = "gcn mkoffload";
133
134 static const char *gcn_dumpbase;
135 static struct obstack files_to_cleanup;
136
137 enum offload_abi offload_abi = OFFLOAD_ABI_UNSET;
138 uint32_t elf_arch = EF_AMDGPU_MACH_AMDGCN_GFX900; // Default GPU architecture.
139 uint32_t elf_flags = EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4;
140
141 static int gcn_stack_size = 0; /* Zero means use default. */
142
143 /* Delete tempfiles. */
144
145 void
146 tool_cleanup (bool from_signal ATTRIBUTE_UNUSED)
147 {
148 obstack_ptr_grow (&files_to_cleanup, NULL);
149 const char **files = XOBFINISH (&files_to_cleanup, const char **);
150 for (int i = 0; files[i]; i++)
151 maybe_unlink (files[i]);
152 }
153
154 static void
155 mkoffload_cleanup (void)
156 {
157 tool_cleanup (false);
158 }
159
160 /* Unlink FILE unless requested otherwise. */
161
162 void
163 maybe_unlink (const char *file)
164 {
165 if (!save_temps)
166 {
167 if (unlink_if_ordinary (file) && errno != ENOENT)
168 fatal_error (input_location, "deleting file %qs: %m", file);
169 }
170 else if (verbose)
171 fprintf (stderr, "[Leaving %s]\n", file);
172 }
173
174 /* Add or change the value of an environment variable, outputting the
175 change to standard error if in verbose mode. */
176
177 static void
178 xputenv (const char *string)
179 {
180 if (verbose)
181 fprintf (stderr, "%s\n", string);
182 putenv (CONST_CAST (char *, string));
183 }
184
185 /* Read the whole input file. It will be NUL terminated (but
186 remember, there could be a NUL in the file itself. */
187
188 static const char *
189 read_file (FILE *stream, size_t *plen)
190 {
191 size_t alloc = 16384;
192 size_t base = 0;
193 char *buffer;
194
195 if (!fseek (stream, 0, SEEK_END))
196 {
197 /* Get the file size. */
198 long s = ftell (stream);
199 if (s >= 0)
200 alloc = s + 100;
201 fseek (stream, 0, SEEK_SET);
202 }
203 buffer = XNEWVEC (char, alloc);
204
205 for (;;)
206 {
207 size_t n = fread (buffer + base, 1, alloc - base - 1, stream);
208
209 if (!n)
210 break;
211 base += n;
212 if (base + 1 == alloc)
213 {
214 alloc *= 2;
215 buffer = XRESIZEVEC (char, buffer, alloc);
216 }
217 }
218 buffer[base] = 0;
219 *plen = base;
220 return buffer;
221 }
222
223 /* Parse STR, saving found tokens into PVALUES and return their number.
224 Tokens are assumed to be delimited by ':'. */
225
226 static unsigned
227 parse_env_var (const char *str, char ***pvalues)
228 {
229 const char *curval, *nextval;
230 char **values;
231 unsigned num = 1, i;
232
233 curval = strchr (str, ':');
234 while (curval)
235 {
236 num++;
237 curval = strchr (curval + 1, ':');
238 }
239
240 values = (char **) xmalloc (num * sizeof (char *));
241 curval = str;
242 nextval = strchr (curval, ':');
243 if (nextval == NULL)
244 nextval = strchr (curval, '\0');
245
246 for (i = 0; i < num; i++)
247 {
248 int l = nextval - curval;
249 values[i] = (char *) xmalloc (l + 1);
250 memcpy (values[i], curval, l);
251 values[i][l] = 0;
252 curval = nextval + 1;
253 nextval = strchr (curval, ':');
254 if (nextval == NULL)
255 nextval = strchr (curval, '\0');
256 }
257 *pvalues = values;
258 return num;
259 }
260
261 /* Auxiliary function that frees elements of PTR and PTR itself.
262 N is number of elements to be freed. If PTR is NULL, nothing is freed.
263 If an element is NULL, subsequent elements are not freed. */
264
265 static void
266 free_array_of_ptrs (void **ptr, unsigned n)
267 {
268 unsigned i;
269 if (!ptr)
270 return;
271 for (i = 0; i < n; i++)
272 {
273 if (!ptr[i])
274 break;
275 free (ptr[i]);
276 }
277 free (ptr);
278 return;
279 }
280
281 /* Check whether NAME can be accessed in MODE. This is like access,
282 except that it never considers directories to be executable. */
283
284 static int
285 access_check (const char *name, int mode)
286 {
287 if (mode == X_OK)
288 {
289 struct stat st;
290
291 if (stat (name, &st) < 0 || S_ISDIR (st.st_mode))
292 return -1;
293 }
294
295 return access (name, mode);
296 }
297
298 /* Copy the early-debug-info from the incoming LTO object to a new object
299 that will be linked into the output HSACO file. The host relocations
300 must be translated into GCN relocations, and any global undefined symbols
301 must be weakened (so as not to have the debug info try to pull in host
302 junk).
303
304 Returns true if the file was created, false otherwise. */
305
306 static bool
307 copy_early_debug_info (const char *infile, const char *outfile)
308 {
309 const char *errmsg;
310 int err;
311
312 /* The simple_object code can handle extracting the debug sections.
313 This code is based on that in lto-wrapper.cc. */
314 int infd = open (infile, O_RDONLY | O_BINARY);
315 if (infd == -1)
316 return false;
317 simple_object_read *inobj = simple_object_start_read (infd, 0,
318 "__GNU_LTO",
319 &errmsg, &err);
320 if (!inobj)
321 return false;
322
323 off_t off, len;
324 if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
325 &off, &len, &errmsg, &err) != 1)
326 {
327 simple_object_release_read (inobj);
328 close (infd);
329 return false;
330 }
331
332 errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err, true);
333 if (errmsg)
334 return false;
335
336 simple_object_release_read (inobj);
337 close (infd);
338
339 /* Open the file we just created for some adjustments.
340 The simple_object code can't do this, so we do it manually. */
341 FILE *outfd = fopen (outfile, "r+b");
342 if (!outfd)
343 return false;
344
345 Elf64_Ehdr ehdr;
346 if (fread (&ehdr, sizeof (ehdr), 1, outfd) != 1)
347 {
348 fclose (outfd);
349 return true;
350 }
351
352 /* We only support host relocations of x86_64, for now. */
353 gcc_assert (ehdr.e_machine == EM_X86_64);
354
355 /* Fiji devices use HSACOv3 regardless of the assembler. */
356 uint32_t elf_flags_actual = (elf_arch == EF_AMDGPU_MACH_AMDGCN_GFX803
357 ? 0 : elf_flags);
358
359 /* Patch the correct elf architecture flag into the file. */
360 ehdr.e_ident[7] = ELFOSABI_AMDGPU_HSA;
361 ehdr.e_ident[8] = (elf_arch == EF_AMDGPU_MACH_AMDGCN_GFX803
362 ? ELFABIVERSION_AMDGPU_HSA_V3
363 : ELFABIVERSION_AMDGPU_HSA_V4);
364 ehdr.e_type = ET_REL;
365 ehdr.e_machine = EM_AMDGPU;
366 ehdr.e_flags = elf_arch | elf_flags_actual;
367
368 /* Load the section headers so we can walk them later. */
369 Elf64_Shdr *sections = (Elf64_Shdr *)xmalloc (sizeof (Elf64_Shdr)
370 * ehdr.e_shnum);
371 if (fseek (outfd, ehdr.e_shoff, SEEK_SET) == -1
372 || fread (sections, sizeof (Elf64_Shdr), ehdr.e_shnum,
373 outfd) != ehdr.e_shnum)
374 {
375 free (sections);
376 fclose (outfd);
377 return true;
378 }
379
380 /* Convert the host relocations to target relocations. */
381 for (int i = 0; i < ehdr.e_shnum; i++)
382 {
383 if (sections[i].sh_type != SHT_RELA)
384 continue;
385
386 char *data = (char *)xmalloc (sections[i].sh_size);
387 if (fseek (outfd, sections[i].sh_offset, SEEK_SET) == -1
388 || fread (data, sections[i].sh_size, 1, outfd) != 1)
389 {
390 free (data);
391 continue;
392 }
393
394 for (size_t offset = 0;
395 offset < sections[i].sh_size;
396 offset += sections[i].sh_entsize)
397 {
398 Elf64_Rela *reloc = (Elf64_Rela *) (data + offset);
399
400 /* Map the host relocations to GCN relocations.
401 Only relocations that can appear in DWARF need be handled. */
402 switch (ELF64_R_TYPE (reloc->r_info))
403 {
404 case R_X86_64_32:
405 case R_X86_64_32S:
406 reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
407 R_AMDGPU_ABS32);
408 break;
409 case R_X86_64_PC32:
410 reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
411 R_AMDGPU_REL32);
412 break;
413 case R_X86_64_PC64:
414 reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
415 R_AMDGPU_REL64);
416 break;
417 case R_X86_64_64:
418 reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
419 R_AMDGPU_ABS64);
420 break;
421 case R_X86_64_RELATIVE:
422 reloc->r_info = ELF32_R_INFO(ELF32_R_SYM(reloc->r_info),
423 R_AMDGPU_RELATIVE64);
424 break;
425 default:
426 gcc_unreachable ();
427 }
428 }
429
430 /* Write back our relocation changes. */
431 if (fseek (outfd, sections[i].sh_offset, SEEK_SET) != -1)
432 fwrite (data, sections[i].sh_size, 1, outfd);
433
434 free (data);
435 }
436
437 /* Weaken any global undefined symbols that would pull in unwanted
438 objects. */
439 for (int i = 0; i < ehdr.e_shnum; i++)
440 {
441 if (sections[i].sh_type != SHT_SYMTAB)
442 continue;
443
444 char *data = (char *)xmalloc (sections[i].sh_size);
445 if (fseek (outfd, sections[i].sh_offset, SEEK_SET) == -1
446 || fread (data, sections[i].sh_size, 1, outfd) != 1)
447 {
448 free (data);
449 continue;
450 }
451
452 for (size_t offset = 0;
453 offset < sections[i].sh_size;
454 offset += sections[i].sh_entsize)
455 {
456 Elf64_Sym *sym = (Elf64_Sym *) (data + offset);
457 int type = ELF64_ST_TYPE (sym->st_info);
458 int bind = ELF64_ST_BIND (sym->st_info);
459
460 if (bind == STB_GLOBAL && sym->st_shndx == 0)
461 sym->st_info = ELF64_ST_INFO (STB_WEAK, type);
462 }
463
464 /* Write back our symbol changes. */
465 if (fseek (outfd, sections[i].sh_offset, SEEK_SET) != -1)
466 fwrite (data, sections[i].sh_size, 1, outfd);
467
468 free (data);
469 }
470 free (sections);
471
472 /* Write back our header changes. */
473 rewind (outfd);
474 fwrite (&ehdr, sizeof (ehdr), 1, outfd);
475
476 fclose (outfd);
477 return true;
478 }
479
480 /* Parse an input assembler file, extract the offload tables etc.,
481 and output (1) the assembler code, minus the tables (which can contain
482 problematic relocations), and (2) a C file with the offload tables
483 encoded as structured data. */
484
485 static void
486 process_asm (FILE *in, FILE *out, FILE *cfile)
487 {
488 int fn_count = 0, var_count = 0, ind_fn_count = 0;
489 int dims_count = 0, regcount_count = 0;
490 struct obstack fns_os, dims_os, regcounts_os;
491 obstack_init (&fns_os);
492 obstack_init (&dims_os);
493 obstack_init (&regcounts_os);
494
495 struct oaccdims
496 {
497 int d[3];
498 char *name;
499 } dim;
500
501 struct regcount
502 {
503 int sgpr_count;
504 int vgpr_count;
505 char *kernel_name;
506 } regcount = { -1, -1, NULL };
507
508 /* Always add _init_array and _fini_array as kernels. */
509 obstack_ptr_grow (&fns_os, xstrdup ("_init_array"));
510 obstack_ptr_grow (&fns_os, xstrdup ("_fini_array"));
511 fn_count += 2;
512
513 char buf[1000];
514 enum
515 { IN_CODE,
516 IN_METADATA,
517 IN_VARS,
518 IN_FUNCS,
519 IN_IND_FUNCS,
520 } state = IN_CODE;
521 while (fgets (buf, sizeof (buf), in))
522 {
523 switch (state)
524 {
525 case IN_CODE:
526 {
527 if (sscanf (buf, " ;; OPENACC-DIMS: %d, %d, %d : %ms\n",
528 &dim.d[0], &dim.d[1], &dim.d[2], &dim.name) == 4)
529 {
530 obstack_grow (&dims_os, &dim, sizeof (dim));
531 dims_count++;
532 }
533
534 break;
535 }
536 case IN_METADATA:
537 {
538 if (sscanf (buf, " - .name: %ms\n", &regcount.kernel_name) == 1)
539 break;
540 else if (sscanf (buf, " .sgpr_count: %d\n",
541 &regcount.sgpr_count) == 1)
542 {
543 gcc_assert (regcount.kernel_name);
544 break;
545 }
546 else if (sscanf (buf, " .vgpr_count: %d\n",
547 &regcount.vgpr_count) == 1)
548 {
549 gcc_assert (regcount.kernel_name);
550 break;
551 }
552
553 break;
554 }
555 case IN_VARS:
556 {
557 char *varname;
558 unsigned varsize;
559 if (sscanf (buf, " .8byte %ms\n", &varname))
560 {
561 fputs (buf, out);
562 fgets (buf, sizeof (buf), in);
563 if (!sscanf (buf, " .8byte %u\n", &varsize))
564 abort ();
565 var_count++;
566 }
567 break;
568 }
569 case IN_FUNCS:
570 {
571 char *funcname;
572 if (sscanf (buf, "\t.8byte\t%ms\n", &funcname))
573 {
574 fputs (buf, out);
575 obstack_ptr_grow (&fns_os, funcname);
576 fn_count++;
577 continue;
578 }
579 break;
580 }
581 case IN_IND_FUNCS:
582 {
583 char *funcname;
584 if (sscanf (buf, "\t.8byte\t%ms\n", &funcname))
585 {
586 fputs (buf, out);
587 ind_fn_count++;
588 continue;
589 }
590 break;
591 }
592 }
593
594 char dummy;
595 if (sscanf (buf, " .section .gnu.offload_vars%c", &dummy) > 0)
596 {
597 state = IN_VARS;
598
599 /* Add a global symbol to allow plugin-gcn.c to locate the table
600 at runtime. It can't use the "offload_var_table.N" emitted by
601 the compiler because a) they're not global, and b) there's one
602 for each input file combined into the binary. */
603 fputs (buf, out);
604 fputs ("\t.global .offload_var_table\n"
605 "\t.type .offload_var_table, @object\n"
606 ".offload_var_table:\n",
607 out);
608 }
609 else if (sscanf (buf, " .section .gnu.offload_funcs%c", &dummy) > 0)
610 {
611 state = IN_FUNCS;
612 /* Likewise for .gnu.offload_vars; used for reverse offload. */
613 fputs (buf, out);
614 fputs ("\t.global .offload_func_table\n"
615 "\t.type .offload_func_table, @object\n"
616 ".offload_func_table:\n",
617 out);
618 }
619 else if (sscanf (buf, " .section .gnu.offload_ind_funcs%c", &dummy) > 0)
620 {
621 state = IN_IND_FUNCS;
622 fputs (buf, out);
623 fputs ("\t.global .offload_ind_func_table\n"
624 "\t.type .offload_ind_func_table, @object\n"
625 ".offload_ind_func_table:\n",
626 out);
627 }
628 else if (sscanf (buf, " .amdgpu_metadata%c", &dummy) > 0)
629 {
630 state = IN_METADATA;
631 regcount.kernel_name = NULL;
632 regcount.sgpr_count = regcount.vgpr_count = -1;
633 }
634 else if (sscanf (buf, " .section %c", &dummy) > 0
635 || sscanf (buf, " .text%c", &dummy) > 0
636 || sscanf (buf, " .bss%c", &dummy) > 0
637 || sscanf (buf, " .data%c", &dummy) > 0
638 || sscanf (buf, " .ident %c", &dummy) > 0)
639 state = IN_CODE;
640 else if (sscanf (buf, " .end_amdgpu_metadata%c", &dummy) > 0)
641 {
642 state = IN_CODE;
643 gcc_assert (regcount.kernel_name != NULL
644 && regcount.sgpr_count >= 0
645 && regcount.vgpr_count >= 0);
646 obstack_grow (&regcounts_os, &regcount, sizeof (regcount));
647 regcount_count++;
648 regcount.kernel_name = NULL;
649 regcount.sgpr_count = regcount.vgpr_count = -1;
650 }
651
652 if (state == IN_CODE || state == IN_METADATA || state == IN_VARS)
653 fputs (buf, out);
654 }
655
656 char **fns = XOBFINISH (&fns_os, char **);
657 struct oaccdims *dims = XOBFINISH (&dims_os, struct oaccdims *);
658 struct regcount *regcounts = XOBFINISH (&regcounts_os, struct regcount *);
659
660 fprintf (cfile, "#include <stdlib.h>\n");
661 fprintf (cfile, "#include <stdint.h>\n");
662 fprintf (cfile, "#include <stdbool.h>\n\n");
663
664 fprintf (cfile, "static const int gcn_num_vars = %d;\n\n", var_count);
665 fprintf (cfile, "static const int gcn_num_ind_funcs = %d;\n\n", ind_fn_count);
666
667 /* Dump out function idents. */
668 fprintf (cfile, "static const struct hsa_kernel_description {\n"
669 " const char *name;\n"
670 " int oacc_dims[3];\n"
671 " int sgpr_count;\n"
672 " int vgpr_count;\n"
673 "} gcn_kernels[] = {\n ");
674 dim.d[0] = dim.d[1] = dim.d[2] = 0;
675 const char *comma;
676 int i;
677 for (comma = "", i = 0; i < fn_count; comma = ",\n ", i++)
678 {
679 /* Find if we recorded dimensions for this function. */
680 int *d = dim.d; /* Previously zeroed. */
681 int sgpr_count = 0;
682 int vgpr_count = 0;
683 for (int j = 0; j < dims_count; j++)
684 if (strcmp (fns[i], dims[j].name) == 0)
685 {
686 d = dims[j].d;
687 break;
688 }
689 for (int j = 0; j < regcount_count; j++)
690 if (strcmp (fns[i], regcounts[j].kernel_name) == 0)
691 {
692 sgpr_count = regcounts[j].sgpr_count;
693 vgpr_count = regcounts[j].vgpr_count;
694 break;
695 }
696
697 fprintf (cfile, "%s{\"%s\", {%d, %d, %d}, %d, %d}", comma,
698 fns[i], d[0], d[1], d[2], sgpr_count, vgpr_count);
699
700 free (fns[i]);
701 }
702 fprintf (cfile, "\n};\n\n");
703
704 /* Set the stack size if the user configured a value. */
705 if (gcn_stack_size)
706 fprintf (cfile,
707 "static __attribute__((constructor))\n"
708 "void configure_stack_size (void)\n"
709 "{\n"
710 " const char *val = getenv (\"GCN_STACK_SIZE\");\n"
711 " if (!val || val[0] == '\\0')\n"
712 " setenv (\"GCN_STACK_SIZE\", \"%d\", true);\n"
713 "}\n\n",
714 gcn_stack_size);
715
716 obstack_free (&fns_os, NULL);
717 for (i = 0; i < dims_count; i++)
718 free (dims[i].name);
719 for (i = 0; i < regcount_count; i++)
720 free (regcounts[i].kernel_name);
721 obstack_free (&dims_os, NULL);
722 obstack_free (&regcounts_os, NULL);
723 }
724
725 /* Embed an object file into a C source file. */
726
727 static void
728 process_obj (FILE *in, FILE *cfile, uint32_t omp_requires)
729 {
730 size_t len = 0;
731 const char *input = read_file (in, &len);
732
733 /* Dump out an array containing the binary.
734 FIXME: do this with objcopy. */
735 fprintf (cfile, "static unsigned char gcn_code[] = {");
736 for (size_t i = 0; i < len; i += 17)
737 {
738 fprintf (cfile, "\n\t");
739 for (size_t j = i; j < i + 17 && j < len; j++)
740 fprintf (cfile, "%3u,", (unsigned char) input[j]);
741 }
742 fprintf (cfile, "\n};\n\n");
743
744 fprintf (cfile,
745 "static const struct gcn_image {\n"
746 " size_t size;\n"
747 " void *image;\n"
748 "} gcn_image = {\n"
749 " %zu,\n"
750 " gcn_code\n"
751 "};\n\n",
752 len);
753
754 fprintf (cfile,
755 "static const struct gcn_data {\n"
756 " uintptr_t omp_requires_mask;\n"
757 " const struct gcn_image *gcn_image;\n"
758 " unsigned kernel_count;\n"
759 " const struct hsa_kernel_description *kernel_infos;\n"
760 " unsigned ind_func_count;\n"
761 " unsigned global_variable_count;\n"
762 "} gcn_data = {\n"
763 " %d,\n"
764 " &gcn_image,\n"
765 " sizeof (gcn_kernels) / sizeof (gcn_kernels[0]),\n"
766 " gcn_kernels,\n"
767 " gcn_num_ind_funcs,\n"
768 " gcn_num_vars\n"
769 "};\n\n", omp_requires);
770
771 fprintf (cfile,
772 "#ifdef __cplusplus\n"
773 "extern \"C\" {\n"
774 "#endif\n"
775 "extern void GOMP_offload_register_ver"
776 " (unsigned, const void *, int, const void *);\n"
777 "extern void GOMP_offload_unregister_ver"
778 " (unsigned, const void *, int, const void *);\n"
779 "#ifdef __cplusplus\n"
780 "}\n"
781 "#endif\n\n");
782
783 fprintf (cfile, "extern const void *const __OFFLOAD_TABLE__[];\n\n");
784
785 fprintf (cfile, "static __attribute__((constructor)) void init (void)\n"
786 "{\n"
787 " GOMP_offload_register_ver (%#x, __OFFLOAD_TABLE__,"
788 " %d/*GCN*/, &gcn_data);\n"
789 "};\n",
790 GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_GCN),
791 GOMP_DEVICE_GCN);
792
793 fprintf (cfile, "static __attribute__((destructor)) void fini (void)\n"
794 "{\n"
795 " GOMP_offload_unregister_ver (%#x, __OFFLOAD_TABLE__,"
796 " %d/*GCN*/, &gcn_data);\n"
797 "};\n",
798 GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_GCN),
799 GOMP_DEVICE_GCN);
800 }
801
802 /* Compile a C file using the host compiler. */
803
804 static void
805 compile_native (const char *infile, const char *outfile, const char *compiler,
806 bool fPIC, bool fpic)
807 {
808 const char *collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
809 if (!collect_gcc_options)
810 fatal_error (input_location,
811 "environment variable %<COLLECT_GCC_OPTIONS%> must be set");
812
813 struct obstack argv_obstack;
814 obstack_init (&argv_obstack);
815 obstack_ptr_grow (&argv_obstack, compiler);
816 if (fPIC)
817 obstack_ptr_grow (&argv_obstack, "-fPIC");
818 if (fpic)
819 obstack_ptr_grow (&argv_obstack, "-fpic");
820 if (save_temps)
821 obstack_ptr_grow (&argv_obstack, "-save-temps");
822 if (verbose)
823 obstack_ptr_grow (&argv_obstack, "-v");
824 obstack_ptr_grow (&argv_obstack, "-dumpdir");
825 obstack_ptr_grow (&argv_obstack, "");
826 obstack_ptr_grow (&argv_obstack, "-dumpbase");
827 obstack_ptr_grow (&argv_obstack, gcn_dumpbase);
828 obstack_ptr_grow (&argv_obstack, "-dumpbase-ext");
829 obstack_ptr_grow (&argv_obstack, ".c");
830 switch (offload_abi)
831 {
832 case OFFLOAD_ABI_LP64:
833 obstack_ptr_grow (&argv_obstack, "-m64");
834 break;
835 case OFFLOAD_ABI_ILP32:
836 obstack_ptr_grow (&argv_obstack, "-m32");
837 break;
838 default:
839 gcc_unreachable ();
840 }
841 obstack_ptr_grow (&argv_obstack, infile);
842 obstack_ptr_grow (&argv_obstack, "-c");
843 obstack_ptr_grow (&argv_obstack, "-o");
844 obstack_ptr_grow (&argv_obstack, outfile);
845 obstack_ptr_grow (&argv_obstack, NULL);
846
847 const char **new_argv = XOBFINISH (&argv_obstack, const char **);
848 fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true,
849 ".gccnative_args");
850 obstack_free (&argv_obstack, NULL);
851 }
852
853 static int
854 get_arch (const char *str, const char *with_arch_str)
855 {
856 if (strcmp (str, "fiji") == 0)
857 return EF_AMDGPU_MACH_AMDGCN_GFX803;
858 else if (strcmp (str, "gfx900") == 0)
859 return EF_AMDGPU_MACH_AMDGCN_GFX900;
860 else if (strcmp (str, "gfx906") == 0)
861 return EF_AMDGPU_MACH_AMDGCN_GFX906;
862 else if (strcmp (str, "gfx908") == 0)
863 return EF_AMDGPU_MACH_AMDGCN_GFX908;
864 else if (strcmp (str, "gfx90a") == 0)
865 return EF_AMDGPU_MACH_AMDGCN_GFX90a;
866 else if (strcmp (str, "gfx90c") == 0)
867 return EF_AMDGPU_MACH_AMDGCN_GFX90c;
868 else if (strcmp (str, "gfx1030") == 0)
869 return EF_AMDGPU_MACH_AMDGCN_GFX1030;
870 else if (strcmp (str, "gfx1036") == 0)
871 return EF_AMDGPU_MACH_AMDGCN_GFX1036;
872 else if (strcmp (str, "gfx1100") == 0)
873 return EF_AMDGPU_MACH_AMDGCN_GFX1100;
874 else if (strcmp (str, "gfx1103") == 0)
875 return EF_AMDGPU_MACH_AMDGCN_GFX1103;
876
877 error ("unrecognized argument in option %<-march=%s%>", str);
878
879 /* The suggestions are based on the configured multilib support; the compiler
880 itself might support more. */
881 if (multilib_options[0] != '\0')
882 {
883 /* Example: "march=gfx900/march=gfx906" */
884 char *args = (char *) alloca (strlen (multilib_options));
885 const char *p = multilib_options, *q = NULL;
886 args[0] = '\0';
887 while (true)
888 {
889 p = strchr (p, '=');
890 if (!p)
891 break;
892 if (q)
893 strcat (args, ", ");
894 ++p;
895 q = strchr (p, '/');
896 if (q)
897 strncat (args, p, q-p);
898 else
899 strcat (args, p);
900 }
901 inform (UNKNOWN_LOCATION, "valid arguments to %<-march=%> are: %s", args);
902 }
903 else if (with_arch_str)
904 inform (UNKNOWN_LOCATION, "valid argument to %<-march=%> is %qs", with_arch_str);
905
906 exit (FATAL_EXIT_CODE);
907
908 return 0;
909 }
910
911 int
912 main (int argc, char **argv)
913 {
914 FILE *in = stdin;
915 FILE *out = stdout;
916 FILE *cfile = stdout;
917 const char *outname = 0;
918 const char *with_arch_str = NULL;
919
920 progname = tool_name;
921 gcc_init_libintl ();
922 diagnostic_initialize (global_dc, 0);
923 diagnostic_color_init (global_dc);
924
925 for (size_t i = 0; i < ARRAY_SIZE (configure_default_options); i++)
926 if (configure_default_options[i].name != NULL
927 && strcmp (configure_default_options[i].name, "arch") == 0)
928 {
929 with_arch_str = configure_default_options[0].value;
930 elf_arch = get_arch (configure_default_options[0].value, NULL);
931 break;
932 }
933
934 obstack_init (&files_to_cleanup);
935 if (atexit (mkoffload_cleanup) != 0)
936 fatal_error (input_location, "%<atexit%> failed");
937
938 char *collect_gcc = getenv ("COLLECT_GCC");
939 if (collect_gcc == NULL)
940 fatal_error (input_location, "%<COLLECT_GCC%> must be set");
941 const char *gcc_path = dirname (ASTRDUP (collect_gcc));
942 const char *gcc_exec = basename (ASTRDUP (collect_gcc));
943
944 size_t len = (strlen (gcc_path) + 1 + strlen (GCC_INSTALL_NAME) + 1);
945 char *driver = XALLOCAVEC (char, len);
946
947 if (strcmp (gcc_exec, collect_gcc) == 0)
948 /* collect_gcc has no path, so it was found in PATH. Make sure we also
949 find accel-gcc in PATH. */
950 gcc_path = NULL;
951
952 int driver_used = 0;
953 if (gcc_path != NULL)
954 driver_used = sprintf (driver, "%s/", gcc_path);
955 sprintf (driver + driver_used, "%s", GCC_INSTALL_NAME);
956
957 bool found = false;
958 if (gcc_path == NULL)
959 found = true;
960 else if (access_check (driver, X_OK) == 0)
961 found = true;
962 else
963 {
964 /* Don't use alloca pointer with XRESIZEVEC. */
965 driver = NULL;
966 /* Look in all COMPILER_PATHs for GCC_INSTALL_NAME. */
967 char **paths = NULL;
968 unsigned n_paths;
969 n_paths = parse_env_var (getenv ("COMPILER_PATH"), &paths);
970 for (unsigned i = 0; i < n_paths; i++)
971 {
972 len = strlen (paths[i]) + 1 + strlen (GCC_INSTALL_NAME) + 1;
973 driver = XRESIZEVEC (char, driver, len);
974 sprintf (driver, "%s/%s", paths[i], GCC_INSTALL_NAME);
975 if (access_check (driver, X_OK) == 0)
976 {
977 found = true;
978 break;
979 }
980 }
981 free_array_of_ptrs ((void **) paths, n_paths);
982 }
983
984 if (!found)
985 fatal_error (input_location,
986 "offload compiler %qs not found", GCC_INSTALL_NAME);
987
988 /* We may be called with all the arguments stored in some file and
989 passed with @file. Expand them into argv before processing. */
990 expandargv (&argc, &argv);
991
992 /* Scan the argument vector. */
993 bool fopenmp = false;
994 bool fopenacc = false;
995 bool fPIC = false;
996 bool fpic = false;
997 for (int i = 1; i < argc; i++)
998 {
999 #define STR "-foffload-abi="
1000 if (startswith (argv[i], STR))
1001 {
1002 if (strcmp (argv[i] + strlen (STR), "lp64") == 0)
1003 offload_abi = OFFLOAD_ABI_LP64;
1004 else if (strcmp (argv[i] + strlen (STR), "ilp32") == 0)
1005 offload_abi = OFFLOAD_ABI_ILP32;
1006 else
1007 fatal_error (input_location,
1008 "unrecognizable argument of option %<" STR "%>");
1009 }
1010 #undef STR
1011 else if (strcmp (argv[i], "-fopenmp") == 0)
1012 fopenmp = true;
1013 else if (strcmp (argv[i], "-fopenacc") == 0)
1014 fopenacc = true;
1015 else if (strcmp (argv[i], "-fPIC") == 0)
1016 fPIC = true;
1017 else if (strcmp (argv[i], "-fpic") == 0)
1018 fpic = true;
1019 else if (strcmp (argv[i], "-mxnack=on") == 0)
1020 SET_XNACK_ON (elf_flags);
1021 else if (strcmp (argv[i], "-mxnack=any") == 0)
1022 SET_XNACK_ANY (elf_flags);
1023 else if (strcmp (argv[i], "-mxnack=off") == 0)
1024 SET_XNACK_OFF (elf_flags);
1025 else if (strcmp (argv[i], "-msram-ecc=on") == 0)
1026 SET_SRAM_ECC_ON (elf_flags);
1027 else if (strcmp (argv[i], "-msram-ecc=any") == 0)
1028 SET_SRAM_ECC_ANY (elf_flags);
1029 else if (strcmp (argv[i], "-msram-ecc=off") == 0)
1030 SET_SRAM_ECC_OFF (elf_flags);
1031 else if (strcmp (argv[i], "-save-temps") == 0)
1032 save_temps = true;
1033 else if (strcmp (argv[i], "-v") == 0)
1034 verbose = true;
1035 else if (strcmp (argv[i], "-dumpbase") == 0
1036 && i + 1 < argc)
1037 dumppfx = argv[++i];
1038 else if (startswith (argv[i], "-march="))
1039 elf_arch = get_arch (argv[i] + strlen ("-march="), with_arch_str);
1040 #define STR "-mstack-size="
1041 else if (startswith (argv[i], STR))
1042 gcn_stack_size = atoi (argv[i] + strlen (STR));
1043 #undef STR
1044 /* Translate host into offloading libraries. */
1045 else if (strcmp (argv[i], "-l_GCC_gfortran") == 0
1046 || strcmp (argv[i], "-l_GCC_m") == 0)
1047 {
1048 /* Elide '_GCC_'. */
1049 size_t i_dst = strlen ("-l");
1050 size_t i_src = strlen ("-l_GCC_");
1051 char c;
1052 do
1053 c = argv[i][i_dst++] = argv[i][i_src++];
1054 while (c != '\0');
1055 }
1056 }
1057
1058 if (!(fopenacc ^ fopenmp))
1059 fatal_error (input_location,
1060 "either %<-fopenacc%> or %<-fopenmp%> must be set");
1061
1062 const char *abi;
1063 switch (offload_abi)
1064 {
1065 case OFFLOAD_ABI_LP64:
1066 abi = "-m64";
1067 break;
1068 case OFFLOAD_ABI_ILP32:
1069 abi = "-m32";
1070 break;
1071 default:
1072 gcc_unreachable ();
1073 }
1074
1075 /* This must match gcn-hsa.h's settings for NO_XNACK, NO_SRAM_ECC
1076 and ASM_SPEC. */
1077 switch (elf_arch)
1078 {
1079 case EF_AMDGPU_MACH_AMDGCN_GFX803:
1080 case EF_AMDGPU_MACH_AMDGCN_GFX1030:
1081 case EF_AMDGPU_MACH_AMDGCN_GFX1036:
1082 case EF_AMDGPU_MACH_AMDGCN_GFX1100:
1083 case EF_AMDGPU_MACH_AMDGCN_GFX1103:
1084 SET_XNACK_UNSET (elf_flags);
1085 SET_SRAM_ECC_UNSET (elf_flags);
1086 break;
1087 case EF_AMDGPU_MACH_AMDGCN_GFX900:
1088 SET_XNACK_OFF (elf_flags);
1089 SET_SRAM_ECC_UNSET (elf_flags);
1090 break;
1091 case EF_AMDGPU_MACH_AMDGCN_GFX906:
1092 SET_XNACK_OFF (elf_flags);
1093 SET_SRAM_ECC_ANY (elf_flags);
1094 break;
1095 case EF_AMDGPU_MACH_AMDGCN_GFX908:
1096 SET_XNACK_OFF (elf_flags);
1097 if (TEST_SRAM_ECC_UNSET (elf_flags))
1098 SET_SRAM_ECC_ANY (elf_flags);
1099 break;
1100 case EF_AMDGPU_MACH_AMDGCN_GFX90a:
1101 if (TEST_XNACK_UNSET (elf_flags))
1102 SET_XNACK_ANY (elf_flags);
1103 if (TEST_SRAM_ECC_UNSET (elf_flags))
1104 SET_SRAM_ECC_ANY (elf_flags);
1105 break;
1106 case EF_AMDGPU_MACH_AMDGCN_GFX90c:
1107 if (TEST_XNACK_UNSET (elf_flags))
1108 SET_XNACK_ANY (elf_flags);
1109 SET_SRAM_ECC_UNSET (elf_flags);
1110 break;
1111 default:
1112 fatal_error (input_location, "unhandled architecture");
1113 }
1114
1115 /* Build arguments for compiler pass. */
1116 struct obstack cc_argv_obstack;
1117 obstack_init (&cc_argv_obstack);
1118 obstack_ptr_grow (&cc_argv_obstack, driver);
1119 obstack_ptr_grow (&cc_argv_obstack, "-S");
1120
1121 if (save_temps)
1122 obstack_ptr_grow (&cc_argv_obstack, "-save-temps");
1123 if (verbose)
1124 obstack_ptr_grow (&cc_argv_obstack, "-v");
1125 obstack_ptr_grow (&cc_argv_obstack, abi);
1126 obstack_ptr_grow (&cc_argv_obstack, "-xlto");
1127 if (fopenmp)
1128 obstack_ptr_grow (&cc_argv_obstack, "-mgomp");
1129
1130 for (int ix = 1; ix != argc; ix++)
1131 {
1132 if (!strcmp (argv[ix], "-o") && ix + 1 != argc)
1133 outname = argv[++ix];
1134 else
1135 obstack_ptr_grow (&cc_argv_obstack, argv[ix]);
1136 }
1137
1138 if (!dumppfx)
1139 dumppfx = outname;
1140
1141 gcn_dumpbase = concat (dumppfx, ".c", NULL);
1142
1143 const char *gcn_cfile_name;
1144 if (save_temps)
1145 gcn_cfile_name = gcn_dumpbase;
1146 else
1147 gcn_cfile_name = make_temp_file (".c");
1148 obstack_ptr_grow (&files_to_cleanup, gcn_cfile_name);
1149
1150 cfile = fopen (gcn_cfile_name, "w");
1151 if (!cfile)
1152 fatal_error (input_location, "cannot open %qs", gcn_cfile_name);
1153
1154 /* Currently, we only support offloading in 64-bit configurations. */
1155 if (offload_abi == OFFLOAD_ABI_LP64)
1156 {
1157 const char *mko_dumpbase = concat (dumppfx, ".mkoffload", NULL);
1158 const char *hsaco_dumpbase = concat (dumppfx, ".mkoffload.hsaco", NULL);
1159
1160 const char *gcn_s1_name;
1161 const char *gcn_s2_name;
1162 const char *gcn_o_name;
1163 if (save_temps)
1164 {
1165 gcn_s1_name = concat (mko_dumpbase, ".1.s", NULL);
1166 gcn_s2_name = concat (mko_dumpbase, ".2.s", NULL);
1167 gcn_o_name = hsaco_dumpbase;
1168 }
1169 else
1170 {
1171 gcn_s1_name = make_temp_file (".mkoffload.1.s");
1172 gcn_s2_name = make_temp_file (".mkoffload.2.s");
1173 gcn_o_name = make_temp_file (".mkoffload.hsaco");
1174 }
1175 obstack_ptr_grow (&files_to_cleanup, gcn_s1_name);
1176 obstack_ptr_grow (&files_to_cleanup, gcn_s2_name);
1177 obstack_ptr_grow (&files_to_cleanup, gcn_o_name);
1178
1179 obstack_ptr_grow (&cc_argv_obstack, "-dumpdir");
1180 obstack_ptr_grow (&cc_argv_obstack, "");
1181 obstack_ptr_grow (&cc_argv_obstack, "-dumpbase");
1182 obstack_ptr_grow (&cc_argv_obstack, mko_dumpbase);
1183 obstack_ptr_grow (&cc_argv_obstack, "-dumpbase-ext");
1184 obstack_ptr_grow (&cc_argv_obstack, "");
1185
1186 obstack_ptr_grow (&cc_argv_obstack, "-o");
1187 obstack_ptr_grow (&cc_argv_obstack, gcn_s1_name);
1188 obstack_ptr_grow (&cc_argv_obstack, NULL);
1189 const char **cc_argv = XOBFINISH (&cc_argv_obstack, const char **);
1190
1191 /* Build arguments for assemble/link pass. */
1192 struct obstack ld_argv_obstack;
1193 obstack_init (&ld_argv_obstack);
1194 obstack_ptr_grow (&ld_argv_obstack, driver);
1195
1196 /* Extract early-debug information from the input objects.
1197 This loop finds all the inputs that end ".o" and aren't the output. */
1198 int dbgcount = 0;
1199 for (int ix = 1; ix != argc; ix++)
1200 {
1201 if (!strcmp (argv[ix], "-o") && ix + 1 != argc)
1202 ++ix;
1203 else
1204 {
1205 if (strcmp (argv[ix] + strlen(argv[ix]) - 2, ".o") == 0)
1206 {
1207 char *dbgobj;
1208 if (save_temps)
1209 {
1210 char buf[10];
1211 sprintf (buf, "%d", dbgcount++);
1212 dbgobj = concat (dumppfx, ".mkoffload.dbg", buf, ".o", NULL);
1213 }
1214 else
1215 dbgobj = make_temp_file (".mkoffload.dbg.o");
1216
1217 /* If the copy fails then just ignore it. */
1218 if (copy_early_debug_info (argv[ix], dbgobj))
1219 {
1220 obstack_ptr_grow (&ld_argv_obstack, dbgobj);
1221 obstack_ptr_grow (&files_to_cleanup, dbgobj);
1222 }
1223 else
1224 {
1225 maybe_unlink (dbgobj);
1226 free (dbgobj);
1227 }
1228 }
1229 }
1230 }
1231 obstack_ptr_grow (&ld_argv_obstack, gcn_s2_name);
1232 obstack_ptr_grow (&ld_argv_obstack, "-lgomp");
1233 if (!TEST_XNACK_UNSET (elf_flags))
1234 obstack_ptr_grow (&ld_argv_obstack,
1235 (TEST_XNACK_ON (elf_flags) ? "-mxnack=on"
1236 : TEST_XNACK_ANY (elf_flags) ? "-mxnack=any"
1237 : "-mxnack=off"));
1238 if (!TEST_SRAM_ECC_UNSET (elf_flags))
1239 obstack_ptr_grow (&ld_argv_obstack,
1240 (TEST_SRAM_ECC_ON (elf_flags) ? "-msram-ecc=on"
1241 : TEST_SRAM_ECC_ANY (elf_flags) ? "-msram-ecc=any"
1242 : "-msram-ecc=off"));
1243 if (verbose)
1244 obstack_ptr_grow (&ld_argv_obstack, "-v");
1245
1246 if (save_temps)
1247 obstack_ptr_grow (&ld_argv_obstack, "-save-temps");
1248
1249 for (int i = 1; i < argc; i++)
1250 if (startswith (argv[i], "-l")
1251 || startswith (argv[i], "-Wl")
1252 || startswith (argv[i], "-march"))
1253 obstack_ptr_grow (&ld_argv_obstack, argv[i]);
1254
1255 obstack_ptr_grow (&cc_argv_obstack, "-dumpdir");
1256 obstack_ptr_grow (&cc_argv_obstack, "");
1257 obstack_ptr_grow (&cc_argv_obstack, "-dumpbase");
1258 obstack_ptr_grow (&cc_argv_obstack, hsaco_dumpbase);
1259 obstack_ptr_grow (&cc_argv_obstack, "-dumpbase-ext");
1260 obstack_ptr_grow (&cc_argv_obstack, "");
1261
1262 obstack_ptr_grow (&ld_argv_obstack, "-o");
1263 obstack_ptr_grow (&ld_argv_obstack, gcn_o_name);
1264 obstack_ptr_grow (&ld_argv_obstack, NULL);
1265 const char **ld_argv = XOBFINISH (&ld_argv_obstack, const char **);
1266
1267 /* Clean up unhelpful environment variables. */
1268 char *execpath = getenv ("GCC_EXEC_PREFIX");
1269 char *cpath = getenv ("COMPILER_PATH");
1270 char *lpath = getenv ("LIBRARY_PATH");
1271 unsetenv ("GCC_EXEC_PREFIX");
1272 unsetenv ("COMPILER_PATH");
1273 unsetenv ("LIBRARY_PATH");
1274
1275 char *omp_requires_file;
1276 if (save_temps)
1277 omp_requires_file = concat (dumppfx, ".mkoffload.omp_requires", NULL);
1278 else
1279 omp_requires_file = make_temp_file (".mkoffload.omp_requires");
1280 obstack_ptr_grow (&files_to_cleanup, omp_requires_file);
1281
1282 /* Run the compiler pass. */
1283 xputenv (concat ("GCC_OFFLOAD_OMP_REQUIRES_FILE=", omp_requires_file, NULL));
1284 fork_execute (cc_argv[0], CONST_CAST (char **, cc_argv), true, ".gcc_args");
1285 obstack_free (&cc_argv_obstack, NULL);
1286 unsetenv("GCC_OFFLOAD_OMP_REQUIRES_FILE");
1287
1288 in = fopen (omp_requires_file, "rb");
1289 if (!in)
1290 fatal_error (input_location, "cannot open omp_requires file %qs",
1291 omp_requires_file);
1292 uint32_t omp_requires;
1293 if (fread (&omp_requires, sizeof (omp_requires), 1, in) != 1)
1294 fatal_error (input_location, "cannot read omp_requires file %qs",
1295 omp_requires_file);
1296 fclose (in);
1297
1298 in = fopen (gcn_s1_name, "r");
1299 if (!in)
1300 fatal_error (input_location, "cannot open intermediate gcn asm file");
1301
1302 out = fopen (gcn_s2_name, "w");
1303 if (!out)
1304 fatal_error (input_location, "cannot open %qs", gcn_s2_name);
1305
1306 process_asm (in, out, cfile);
1307
1308 fclose (in);
1309 fclose (out);
1310
1311 /* Run the assemble/link pass. */
1312 fork_execute (ld_argv[0], CONST_CAST (char **, ld_argv), true, ".ld_args");
1313 obstack_free (&ld_argv_obstack, NULL);
1314
1315 in = fopen (gcn_o_name, "r");
1316 if (!in)
1317 fatal_error (input_location, "cannot open intermediate gcn obj file");
1318
1319 process_obj (in, cfile, omp_requires);
1320
1321 fclose (in);
1322
1323 xputenv (concat ("GCC_EXEC_PREFIX=", execpath, NULL));
1324 xputenv (concat ("COMPILER_PATH=", cpath, NULL));
1325 xputenv (concat ("LIBRARY_PATH=", lpath, NULL));
1326 }
1327
1328 fclose (cfile);
1329
1330 compile_native (gcn_cfile_name, outname, collect_gcc, fPIC, fpic);
1331
1332 return 0;
1333 }