]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/lto-wrapper.c
re PR tree-optimization/44377 (ICE: gimple check: expected gimple_return(error_mark...
[thirdparty/gcc.git] / gcc / lto-wrapper.c
CommitLineData
d7f09764 1/* Wrapper to call lto. Used by collect2 and the linker plugin.
d7fb0a6d 2 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
d7f09764
DN
3
4 Factored out of collect2 by Rafael Espindola <espindola@google.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22
23/* This program is passed a gcc, a list of gcc arguments and a list of
24 object files containing IL. It scans the argument list to check if
25 we are in whopr mode or not modifies the arguments and needed and
26 prints a list of output files on stdout.
27
28 Example:
29
30 $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto
31
32 The above will print something like
33 /tmp/ccwbQ8B2.lto.o
34
35 If -fwhopr is used instead, more than one file might be produced
36 ./ccXj2DTk.lto.ltrans.o
37 ./ccCJuXGv.lto.ltrans.o
38*/
39
40#include "config.h"
41#include "system.h"
62116e60 42#include <errno.h>
d7f09764
DN
43#include "coretypes.h"
44#include "tm.h"
45#include "intl.h"
46#include "libiberty.h"
48cf395b 47#include "obstack.h"
d7f09764 48
cf96bae7
RG
49int debug; /* true if -save-temps. */
50int verbose; /* true if -v. */
d7f09764
DN
51
52enum lto_mode_d {
cf96bae7
RG
53 LTO_MODE_NONE, /* Not doing LTO. */
54 LTO_MODE_LTO, /* Normal LTO. */
55 LTO_MODE_WHOPR /* WHOPR. */
d7f09764
DN
56};
57
58/* Current LTO mode. */
59static enum lto_mode_d lto_mode = LTO_MODE_NONE;
60
b1b07c92
RG
61static char *ltrans_output_file;
62static char *flto_out;
63static char *args_name;
50ee30d5
RG
64static unsigned int nr;
65static char **input_names;
66static char **output_names;
67static char *makefile;
b1b07c92
RG
68
69static void maybe_unlink_file (const char *);
70
71/* Delete tempfiles and exit function. */
72
73static void
74lto_wrapper_exit (int status)
75{
8aea79e6
RAE
76 static bool cleanup_done = false;
77 if (!cleanup_done)
78 {
50ee30d5
RG
79 unsigned int i;
80
8aea79e6
RAE
81 /* Setting cleanup_done prevents an infinite loop if one of the
82 calls to maybe_unlink_file fails. */
83 cleanup_done = true;
84
85 if (ltrans_output_file)
86 maybe_unlink_file (ltrans_output_file);
87 if (flto_out)
88 maybe_unlink_file (flto_out);
89 if (args_name)
90 maybe_unlink_file (args_name);
50ee30d5
RG
91 if (makefile)
92 maybe_unlink_file (makefile);
93 for (i = 0; i < nr; ++i)
94 {
95 maybe_unlink_file (input_names[i]);
96 if (output_names[i])
97 maybe_unlink_file (output_names[i]);
98 }
8aea79e6 99 }
b1b07c92
RG
100 exit (status);
101}
102
d7f09764
DN
103/* Just die. CMSGID is the error message. */
104
105static void __attribute__ ((format (printf, 1, 2)))
106fatal (const char * cmsgid, ...)
107{
108 va_list ap;
109
110 va_start (ap, cmsgid);
111 fprintf (stderr, "lto-wrapper: ");
112 vfprintf (stderr, _(cmsgid), ap);
113 fprintf (stderr, "\n");
114 va_end (ap);
115
b1b07c92 116 lto_wrapper_exit (FATAL_EXIT_CODE);
d7f09764
DN
117}
118
119
120/* Die when sys call fails. CMSGID is the error message. */
121
122static void __attribute__ ((format (printf, 1, 2)))
123fatal_perror (const char *cmsgid, ...)
124{
125 int e = errno;
126 va_list ap;
127
128 va_start (ap, cmsgid);
129 fprintf (stderr, "lto-wrapper: ");
130 vfprintf (stderr, _(cmsgid), ap);
131 fprintf (stderr, ": %s\n", xstrerror (e));
132 va_end (ap);
133
b1b07c92 134 lto_wrapper_exit (FATAL_EXIT_CODE);
d7f09764
DN
135}
136
137
138/* Execute a program, and wait for the reply. ARGV are the arguments. The
139 last one must be NULL. */
140
141static struct pex_obj *
142collect_execute (char **argv)
143{
144 struct pex_obj *pex;
145 const char *errmsg;
146 int err;
147
cf96bae7 148 if (verbose)
d7f09764
DN
149 {
150 char **p_argv;
151 const char *str;
152
153 for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
154 fprintf (stderr, " %s", str);
155
156 fprintf (stderr, "\n");
157 }
158
159 fflush (stdout);
160 fflush (stderr);
161
162 pex = pex_init (0, "lto-wrapper", NULL);
163 if (pex == NULL)
164 fatal_perror ("pex_init failed");
165
c04b6b38
RG
166 /* Do not use PEX_LAST here, we use our stdout for communicating with
167 collect2 or the linker-plugin. Any output from the sub-process
168 will confuse that. */
169 errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL,
d7f09764
DN
170 NULL, &err);
171 if (errmsg != NULL)
172 {
173 if (err != 0)
174 {
175 errno = err;
176 fatal_perror (errmsg);
177 }
178 else
179 fatal (errmsg);
180 }
181
182 return pex;
183}
184
185
186/* Wait for a process to finish, and exit if a nonzero status is found.
187 PROG is the program name. PEX is the process we should wait for. */
188
189static int
190collect_wait (const char *prog, struct pex_obj *pex)
191{
192 int status;
193
194 if (!pex_get_status (pex, 1, &status))
195 fatal_perror ("can't get program status");
196 pex_free (pex);
197
198 if (status)
199 {
200 if (WIFSIGNALED (status))
201 {
202 int sig = WTERMSIG (status);
203 if (WCOREDUMP (status))
204 fatal ("%s terminated with signal %d [%s], core dumped",
205 prog, sig, strsignal (sig));
206 else
207 fatal ("%s terminated with signal %d [%s]",
208 prog, sig, strsignal (sig));
209 }
210
211 if (WIFEXITED (status))
212 fatal ("%s returned %d exit status", prog, WEXITSTATUS (status));
213 }
214
215 return 0;
216}
217
218
219/* Unlink a temporary LTRANS file unless requested otherwise. */
220
221static void
222maybe_unlink_file (const char *file)
223{
224 if (! debug)
225 {
62116e60
RG
226 if (unlink_if_ordinary (file)
227 && errno != ENOENT)
d7f09764
DN
228 fatal_perror ("deleting LTRANS file %s", file);
229 }
230 else
231 fprintf (stderr, "[Leaving LTRANS %s]\n", file);
232}
233
234
235/* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */
236
237static void
238fork_execute (char **argv)
239{
240 struct pex_obj *pex;
241 char *new_argv[3];
b1b07c92
RG
242 char *at_args;
243 FILE *args;
d7f09764
DN
244 int status;
245
b1b07c92
RG
246 args_name = make_temp_file (".args");
247 at_args = concat ("@", args_name, NULL);
248 args = fopen (args_name, "w");
d7f09764
DN
249 if (args == NULL)
250 fatal ("failed to open %s", args_name);
251
252 status = writeargv (&argv[1], args);
253
254 if (status)
255 fatal ("could not write to temporary file %s", args_name);
256
257 fclose (args);
258
259 new_argv[0] = argv[0];
260 new_argv[1] = at_args;
261 new_argv[2] = NULL;
262
263 pex = collect_execute (new_argv);
264 collect_wait (new_argv[0], pex);
265
266 maybe_unlink_file (args_name);
62116e60 267 args_name = NULL;
d7f09764
DN
268 free (at_args);
269}
270
48cf395b
RB
271/* Template of LTRANS dumpbase suffix. */
272#define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
d7f09764
DN
273
274/* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
275
276static void
277run_gcc (unsigned argc, char *argv[])
278{
cf96bae7 279 unsigned i, j;
d7f09764
DN
280 const char **new_argv;
281 const char **argv_ptr;
d7f09764 282 char *list_option_full = NULL;
cf96bae7
RG
283 const char *linker_output = NULL;
284 const char *collect_gcc_options, *collect_gcc;
285 struct obstack env_obstack;
286 bool seen_o = false;
c04b6b38 287 int parallel = 0;
cf96bae7
RG
288
289 /* Get the driver and options. */
290 collect_gcc = getenv ("COLLECT_GCC");
291 if (!collect_gcc)
292 fatal ("environment variable COLLECT_GCC must be set");
293
294 /* Set the CFLAGS environment variable. */
295 collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
296 if (!collect_gcc_options)
297 fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
298
299 /* Count arguments. */
300 i = 0;
301 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
302 if (collect_gcc_options[j] == '\'')
303 ++i;
304
305 if (i % 2 != 0)
306 fatal ("malformed COLLECT_GCC_OPTIONS");
307
308 /* Initalize the common arguments for the driver. */
309 new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
310 argv_ptr = new_argv;
311 *argv_ptr++ = collect_gcc;
312 *argv_ptr++ = "-xlto";
313 *argv_ptr++ = "-c";
314 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
315 if (collect_gcc_options[j] == '\'')
316 {
317 char *option;
318
319 ++j;
320 i = j;
321 while (collect_gcc_options[j] != '\'')
322 ++j;
323
324 obstack_init (&env_obstack);
325 obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
326 obstack_1grow (&env_obstack, 0);
327 option = XOBFINISH (&env_obstack, char *);
328 if (seen_o)
329 {
330 linker_output = option;
331 seen_o = false;
332 continue;
333 }
334
335 /* If we see -o, skip it and skip and record its argument. */
336 if (option[0] == '-' && option[1] == 'o')
337 {
338 if (option[2] == '\0')
339 seen_o = true;
340 else
341 linker_output = &option[2];
342 continue;
343 }
d7f09764 344
cf96bae7
RG
345 if (strcmp (option, "-save-temps") == 0)
346 debug = 1;
347 if (strcmp (option, "-v") == 0)
348 verbose = 1;
349
350 /* We've handled these LTO options, do not pass them on. */
351 if (strcmp (option, "-flto") == 0)
352 lto_mode = LTO_MODE_LTO;
c04b6b38
RG
353 else if (strncmp (option, "-fwhopr", 7) == 0)
354 {
355 lto_mode = LTO_MODE_WHOPR;
356 if (option[7] == '=')
357 {
358 parallel = atoi (option+8);
359 if (parallel <= 1)
360 parallel = 0;
361 }
362 }
cf96bae7
RG
363 else
364 *argv_ptr++ = option;
365 }
366
367 if (linker_output)
368 {
369 char *output_dir, *base, *name;
d7f09764 370
cf96bae7
RG
371 output_dir = xstrdup (linker_output);
372 base = output_dir;
373 for (name = base; *name; name++)
374 if (IS_DIR_SEPARATOR (*name))
375 base = name + 1;
376 *base = '\0';
377
378 linker_output = &linker_output[base - output_dir];
379 if (*output_dir == '\0')
380 {
381 static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
382 output_dir = current_dir;
383 }
384 *argv_ptr++ = "-dumpdir";
385 *argv_ptr++ = output_dir;
386
387 *argv_ptr++ = "-dumpbase";
388 }
389 else
390 argv_ptr--;
d7f09764 391
d7f09764
DN
392 if (lto_mode == LTO_MODE_LTO)
393 {
394 flto_out = make_temp_file (".lto.o");
cf96bae7
RG
395 if (linker_output)
396 argv_ptr[0] = linker_output;
397 argv_ptr[1] = "-o";
398 argv_ptr[2] = flto_out;
399 argv_ptr[3] = "-combine";
d7f09764
DN
400 }
401 else if (lto_mode == LTO_MODE_WHOPR)
402 {
403 const char *list_option = "-fltrans-output-list=";
404 size_t list_option_len = strlen (list_option);
405 char *tmp;
406
cf96bae7
RG
407 if (linker_output)
408 {
409 char *dumpbase = (char *) xmalloc (strlen (linker_output)
b5611987 410 + sizeof (".wpa") + 1);
cf96bae7
RG
411 strcpy (dumpbase, linker_output);
412 strcat (dumpbase, ".wpa");
413 argv_ptr[0] = dumpbase;
414 }
415
b5611987
RG
416 if (linker_output && debug)
417 {
418 ltrans_output_file = (char *) xmalloc (strlen (linker_output)
419 + sizeof (".ltrans.out") + 1);
420 strcpy (ltrans_output_file, linker_output);
421 strcat (ltrans_output_file, ".ltrans.out");
422 }
423 else
424 ltrans_output_file = make_temp_file (".ltrans.out");
d7f09764
DN
425 list_option_full = (char *) xmalloc (sizeof (char) *
426 (strlen (ltrans_output_file) + list_option_len + 1));
427 tmp = list_option_full;
428
cf96bae7 429 argv_ptr[1] = tmp;
d7f09764
DN
430 strcpy (tmp, list_option);
431 tmp += list_option_len;
432 strcpy (tmp, ltrans_output_file);
433
cf96bae7
RG
434 argv_ptr[2] = "-fwpa";
435 argv_ptr[3] = "-combine";
d7f09764
DN
436 }
437 else
438 fatal ("invalid LTO mode");
439
cf96bae7
RG
440 /* Append the input objects and possible preceeding arguments. */
441 for (i = 1; i < argc; ++i)
442 argv_ptr[3 + i] = argv[i];
443 argv_ptr[3 + i] = NULL;
d7f09764
DN
444
445 fork_execute (CONST_CAST (char **, new_argv));
48cf395b 446
d7f09764
DN
447 if (lto_mode == LTO_MODE_LTO)
448 {
449 printf("%s\n", flto_out);
450 free (flto_out);
451 flto_out = NULL;
452 }
453 else if (lto_mode == LTO_MODE_WHOPR)
454 {
455 FILE *stream = fopen (ltrans_output_file, "r");
c04b6b38 456 FILE *mstream = NULL;
d7f09764
DN
457
458 if (!stream)
459 fatal_perror ("fopen: %s", ltrans_output_file);
460
50ee30d5
RG
461 /* Parse the list of LTRANS inputs from the WPA stage. */
462 nr = 0;
48cf395b
RB
463 for (;;)
464 {
465 const unsigned piece = 32;
50ee30d5 466 char *output_name = NULL;
48cf395b
RB
467 char *buf, *input_name = (char *)xmalloc (piece);
468 size_t len;
469
470 buf = input_name;
471cont:
472 if (!fgets (buf, piece, stream))
473 break;
474 len = strlen (input_name);
475 if (input_name[len - 1] != '\n')
476 {
477 input_name = (char *)xrealloc (input_name, len + piece);
478 buf = input_name + len;
479 goto cont;
480 }
481 input_name[len - 1] = '\0';
482
483 if (input_name[0] == '*')
c04b6b38 484 output_name = &input_name[1];
48cf395b 485
c04b6b38
RG
486 nr++;
487 input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
488 output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
489 input_names[nr-1] = input_name;
490 output_names[nr-1] = output_name;
491 }
50ee30d5
RG
492 fclose (stream);
493 maybe_unlink_file (ltrans_output_file);
494 ltrans_output_file = NULL;
495
496 if (parallel)
497 {
498 makefile = make_temp_file (".mk");
499 mstream = fopen (makefile, "w");
500 }
501
502 /* Execute the LTRANS stage for each input file (or prepare a
503 makefile to invoke this in parallel). */
504 for (i = 0; i < nr; ++i)
505 {
506 char *output_name;
507 char *input_name = input_names[i];
508 /* If it's a pass-through file do nothing. */
509 if (output_names[i])
510 continue;
511
512 /* Replace the .o suffix with a .ltrans.o suffix and write
513 the resulting name to the LTRANS output list. */
514 obstack_init (&env_obstack);
515 obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
516 obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
517 output_name = XOBFINISH (&env_obstack, char *);
518
519 /* Adjust the dumpbase if the linker output file was seen. */
520 if (linker_output)
521 {
522 char *dumpbase
523 = (char *) xmalloc (strlen (linker_output)
524 + sizeof(DUMPBASE_SUFFIX) + 1);
525 snprintf (dumpbase,
526 strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
b5611987 527 "%s.ltrans%u", linker_output, i);
50ee30d5
RG
528 argv_ptr[0] = dumpbase;
529 }
530
531 argv_ptr[1] = "-fltrans";
532 argv_ptr[2] = "-o";
533 argv_ptr[3] = output_name;
534 argv_ptr[4] = input_name;
535 argv_ptr[5] = NULL;
536 if (parallel)
537 {
538 fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
539 for (j = 1; new_argv[j] != NULL; ++j)
540 fprintf (mstream, " '%s'", new_argv[j]);
541 fprintf (mstream, "\n");
542 }
543 else
544 fork_execute (CONST_CAST (char **, new_argv));
545
546 output_names[i] = output_name;
547 }
c04b6b38
RG
548 if (parallel)
549 {
550 struct pex_obj *pex;
551 char jobs[32];
552 fprintf (mstream, "all:");
553 for (i = 0; i < nr; ++i)
554 fprintf (mstream, " \\\n\t%s", output_names[i]);
555 fprintf (mstream, "\n");
556 fclose (mstream);
5767217f
RW
557 /* Avoid passing --jobserver-fd= and similar flags. */
558 putenv (xstrdup ("MAKEFLAGS="));
559 putenv (xstrdup ("MFLAGS="));
560 new_argv[0] = getenv ("MAKE");
561 if (!new_argv[0])
562 new_argv[0] = "make";
c04b6b38
RG
563 new_argv[1] = "-f";
564 new_argv[2] = makefile;
565 snprintf (jobs, 31, "-j%d", parallel);
566 new_argv[3] = jobs;
567 new_argv[4] = "all";
568 new_argv[5] = NULL;
569 pex = collect_execute (CONST_CAST (char **, new_argv));
570 collect_wait (new_argv[0], pex);
571 maybe_unlink_file (makefile);
50ee30d5 572 makefile = NULL;
c04b6b38
RG
573 }
574 for (i = 0; i < nr; ++i)
575 {
576 fputs (output_names[i], stdout);
48cf395b 577 putc ('\n', stdout);
c04b6b38
RG
578 maybe_unlink_file (input_names[i]);
579 free (input_names[i]);
48cf395b 580 }
50ee30d5 581 nr = 0;
c04b6b38
RG
582 free (output_names);
583 free (input_names);
d7f09764
DN
584 free (list_option_full);
585 }
586 else
587 fatal ("invalid LTO mode");
d7f09764 588
cf96bae7 589 obstack_free (&env_obstack, NULL);
d7f09764
DN
590}
591
592
593/* Entry point. */
594
595int
596main (int argc, char *argv[])
597{
d7f09764
DN
598 gcc_init_libintl ();
599
600 /* We may be called with all the arguments stored in some file and
601 passed with @file. Expand them into argv before processing. */
602 expandargv (&argc, &argv);
cf96bae7 603 run_gcc (argc, argv);
d7f09764
DN
604
605 return 0;
606}