1 /* Wrapper to call lto. Used by collect2 and the linker plugin.
2 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4 Factored out of collect2 by Rafael Espindola <espindola@google.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
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.
30 $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto
32 The above will print something like
35 If -fwhopr is used instead, more than one file might be produced
36 ./ccXj2DTk.lto.ltrans.o
37 ./ccCJuXGv.lto.ltrans.o
43 #include "coretypes.h"
46 #include "libiberty.h"
49 int debug; /* true if -save-temps. */
50 int verbose; /* true if -v. */
53 LTO_MODE_NONE, /* Not doing LTO. */
54 LTO_MODE_LTO, /* Normal LTO. */
55 LTO_MODE_WHOPR /* WHOPR. */
58 /* Current LTO mode. */
59 static enum lto_mode_d lto_mode = LTO_MODE_NONE;
61 static char *ltrans_output_file;
62 static char *flto_out;
63 static char *args_name;
64 static unsigned int nr;
65 static char **input_names;
66 static char **output_names;
67 static char *makefile;
69 static void maybe_unlink_file (const char *);
71 /* Delete tempfiles and exit function. */
74 lto_wrapper_exit (int status)
76 static bool cleanup_done = false;
81 /* Setting cleanup_done prevents an infinite loop if one of the
82 calls to maybe_unlink_file fails. */
85 if (ltrans_output_file)
86 maybe_unlink_file (ltrans_output_file);
88 maybe_unlink_file (flto_out);
90 maybe_unlink_file (args_name);
92 maybe_unlink_file (makefile);
93 for (i = 0; i < nr; ++i)
95 maybe_unlink_file (input_names[i]);
97 maybe_unlink_file (output_names[i]);
103 /* Just die. CMSGID is the error message. */
105 static void __attribute__ ((format (printf, 1, 2)))
106 fatal (const char * cmsgid, ...)
110 va_start (ap, cmsgid);
111 fprintf (stderr, "lto-wrapper: ");
112 vfprintf (stderr, _(cmsgid), ap);
113 fprintf (stderr, "\n");
116 lto_wrapper_exit (FATAL_EXIT_CODE);
120 /* Die when sys call fails. CMSGID is the error message. */
122 static void __attribute__ ((format (printf, 1, 2)))
123 fatal_perror (const char *cmsgid, ...)
128 va_start (ap, cmsgid);
129 fprintf (stderr, "lto-wrapper: ");
130 vfprintf (stderr, _(cmsgid), ap);
131 fprintf (stderr, ": %s\n", xstrerror (e));
134 lto_wrapper_exit (FATAL_EXIT_CODE);
138 /* Execute a program, and wait for the reply. ARGV are the arguments. The
139 last one must be NULL. */
141 static struct pex_obj *
142 collect_execute (char **argv)
153 for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
154 fprintf (stderr, " %s", str);
156 fprintf (stderr, "\n");
162 pex = pex_init (0, "lto-wrapper", NULL);
164 fatal_perror ("pex_init failed");
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,
176 fatal_perror (errmsg);
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. */
190 collect_wait (const char *prog, struct pex_obj *pex)
194 if (!pex_get_status (pex, 1, &status))
195 fatal_perror ("can't get program status");
200 if (WIFSIGNALED (status))
202 int sig = WTERMSIG (status);
203 if (WCOREDUMP (status))
204 fatal ("%s terminated with signal %d [%s], core dumped",
205 prog, sig, strsignal (sig));
207 fatal ("%s terminated with signal %d [%s]",
208 prog, sig, strsignal (sig));
211 if (WIFEXITED (status))
212 fatal ("%s returned %d exit status", prog, WEXITSTATUS (status));
219 /* Unlink a temporary LTRANS file unless requested otherwise. */
222 maybe_unlink_file (const char *file)
226 if (unlink_if_ordinary (file)
228 fatal_perror ("deleting LTRANS file %s", file);
231 fprintf (stderr, "[Leaving LTRANS %s]\n", file);
235 /* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */
238 fork_execute (char **argv)
246 args_name = make_temp_file (".args");
247 at_args = concat ("@", args_name, NULL);
248 args = fopen (args_name, "w");
250 fatal ("failed to open %s", args_name);
252 status = writeargv (&argv[1], args);
255 fatal ("could not write to temporary file %s", args_name);
259 new_argv[0] = argv[0];
260 new_argv[1] = at_args;
263 pex = collect_execute (new_argv);
264 collect_wait (new_argv[0], pex);
266 maybe_unlink_file (args_name);
271 /* Template of LTRANS dumpbase suffix. */
272 #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
274 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
277 run_gcc (unsigned argc, char *argv[])
280 const char **new_argv;
281 const char **argv_ptr;
282 char *list_option_full = NULL;
283 const char *linker_output = NULL;
284 const char *collect_gcc_options, *collect_gcc;
285 struct obstack env_obstack;
289 /* Get the driver and options. */
290 collect_gcc = getenv ("COLLECT_GCC");
292 fatal ("environment variable COLLECT_GCC must be set");
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");
299 /* Count arguments. */
301 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
302 if (collect_gcc_options[j] == '\'')
306 fatal ("malformed COLLECT_GCC_OPTIONS");
308 /* Initalize the common arguments for the driver. */
309 new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
311 *argv_ptr++ = collect_gcc;
312 *argv_ptr++ = "-xlto";
314 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
315 if (collect_gcc_options[j] == '\'')
321 while (collect_gcc_options[j] != '\'')
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 *);
330 linker_output = option;
335 /* If we see -o, skip it and skip and record its argument. */
336 if (option[0] == '-' && option[1] == 'o')
338 if (option[2] == '\0')
341 linker_output = &option[2];
345 if (strcmp (option, "-save-temps") == 0)
347 if (strcmp (option, "-v") == 0)
350 /* We've handled these LTO options, do not pass them on. */
351 if (strcmp (option, "-flto") == 0)
352 lto_mode = LTO_MODE_LTO;
353 else if (strncmp (option, "-fwhopr", 7) == 0)
355 lto_mode = LTO_MODE_WHOPR;
356 if (option[7] == '=')
358 parallel = atoi (option+8);
364 *argv_ptr++ = option;
369 char *output_dir, *base, *name;
371 output_dir = xstrdup (linker_output);
373 for (name = base; *name; name++)
374 if (IS_DIR_SEPARATOR (*name))
378 linker_output = &linker_output[base - output_dir];
379 if (*output_dir == '\0')
381 static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
382 output_dir = current_dir;
384 *argv_ptr++ = "-dumpdir";
385 *argv_ptr++ = output_dir;
387 *argv_ptr++ = "-dumpbase";
392 if (lto_mode == LTO_MODE_LTO)
394 flto_out = make_temp_file (".lto.o");
396 argv_ptr[0] = linker_output;
398 argv_ptr[2] = flto_out;
399 argv_ptr[3] = "-combine";
401 else if (lto_mode == LTO_MODE_WHOPR)
403 const char *list_option = "-fltrans-output-list=";
404 size_t list_option_len = strlen (list_option);
409 char *dumpbase = (char *) xmalloc (strlen (linker_output)
410 + sizeof (".wpa") + 1);
411 strcpy (dumpbase, linker_output);
412 strcat (dumpbase, ".wpa");
413 argv_ptr[0] = dumpbase;
416 if (linker_output && debug)
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");
424 ltrans_output_file = make_temp_file (".ltrans.out");
425 list_option_full = (char *) xmalloc (sizeof (char) *
426 (strlen (ltrans_output_file) + list_option_len + 1));
427 tmp = list_option_full;
430 strcpy (tmp, list_option);
431 tmp += list_option_len;
432 strcpy (tmp, ltrans_output_file);
434 argv_ptr[2] = "-fwpa";
435 argv_ptr[3] = "-combine";
438 fatal ("invalid LTO mode");
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;
445 fork_execute (CONST_CAST (char **, new_argv));
447 if (lto_mode == LTO_MODE_LTO)
449 printf("%s\n", flto_out);
453 else if (lto_mode == LTO_MODE_WHOPR)
455 FILE *stream = fopen (ltrans_output_file, "r");
456 FILE *mstream = NULL;
459 fatal_perror ("fopen: %s", ltrans_output_file);
461 /* Parse the list of LTRANS inputs from the WPA stage. */
465 const unsigned piece = 32;
466 char *output_name = NULL;
467 char *buf, *input_name = (char *)xmalloc (piece);
472 if (!fgets (buf, piece, stream))
474 len = strlen (input_name);
475 if (input_name[len - 1] != '\n')
477 input_name = (char *)xrealloc (input_name, len + piece);
478 buf = input_name + len;
481 input_name[len - 1] = '\0';
483 if (input_name[0] == '*')
484 output_name = &input_name[1];
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;
493 maybe_unlink_file (ltrans_output_file);
494 ltrans_output_file = NULL;
498 makefile = make_temp_file (".mk");
499 mstream = fopen (makefile, "w");
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)
507 char *input_name = input_names[i];
508 /* If it's a pass-through file do nothing. */
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 *);
519 /* Adjust the dumpbase if the linker output file was seen. */
523 = (char *) xmalloc (strlen (linker_output)
524 + sizeof(DUMPBASE_SUFFIX) + 1);
526 strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
527 "%s.ltrans%u", linker_output, i);
528 argv_ptr[0] = dumpbase;
531 argv_ptr[1] = "-fltrans";
533 argv_ptr[3] = output_name;
534 argv_ptr[4] = input_name;
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");
544 fork_execute (CONST_CAST (char **, new_argv));
546 output_names[i] = output_name;
552 fprintf (mstream, "all:");
553 for (i = 0; i < nr; ++i)
554 fprintf (mstream, " \\\n\t%s", output_names[i]);
555 fprintf (mstream, "\n");
557 /* Avoid passing --jobserver-fd= and similar flags. */
558 putenv (xstrdup ("MAKEFLAGS="));
559 putenv (xstrdup ("MFLAGS="));
560 new_argv[0] = getenv ("MAKE");
562 new_argv[0] = "make";
564 new_argv[2] = makefile;
565 snprintf (jobs, 31, "-j%d", parallel);
569 pex = collect_execute (CONST_CAST (char **, new_argv));
570 collect_wait (new_argv[0], pex);
571 maybe_unlink_file (makefile);
574 for (i = 0; i < nr; ++i)
576 fputs (output_names[i], stdout);
578 maybe_unlink_file (input_names[i]);
579 free (input_names[i]);
584 free (list_option_full);
587 fatal ("invalid LTO mode");
589 obstack_free (&env_obstack, NULL);
596 main (int argc, char *argv[])
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);
603 run_gcc (argc, argv);