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
42 #include "coretypes.h"
45 #include "libiberty.h"
48 int debug; /* true if -save-temps. */
49 int verbose; /* true if -v. */
52 LTO_MODE_NONE, /* Not doing LTO. */
53 LTO_MODE_LTO, /* Normal LTO. */
54 LTO_MODE_WHOPR /* WHOPR. */
57 /* Current LTO mode. */
58 static enum lto_mode_d lto_mode = LTO_MODE_NONE;
60 static char *ltrans_output_file;
61 static char *flto_out;
62 static char *args_name;
64 static void maybe_unlink_file (const char *);
66 /* Delete tempfiles and exit function. */
69 lto_wrapper_exit (int status)
71 static bool cleanup_done = false;
74 /* Setting cleanup_done prevents an infinite loop if one of the
75 calls to maybe_unlink_file fails. */
78 if (ltrans_output_file)
79 maybe_unlink_file (ltrans_output_file);
81 maybe_unlink_file (flto_out);
83 maybe_unlink_file (args_name);
88 /* Just die. CMSGID is the error message. */
90 static void __attribute__ ((format (printf, 1, 2)))
91 fatal (const char * cmsgid, ...)
95 va_start (ap, cmsgid);
96 fprintf (stderr, "lto-wrapper: ");
97 vfprintf (stderr, _(cmsgid), ap);
98 fprintf (stderr, "\n");
101 lto_wrapper_exit (FATAL_EXIT_CODE);
105 /* Die when sys call fails. CMSGID is the error message. */
107 static void __attribute__ ((format (printf, 1, 2)))
108 fatal_perror (const char *cmsgid, ...)
113 va_start (ap, cmsgid);
114 fprintf (stderr, "lto-wrapper: ");
115 vfprintf (stderr, _(cmsgid), ap);
116 fprintf (stderr, ": %s\n", xstrerror (e));
119 lto_wrapper_exit (FATAL_EXIT_CODE);
123 /* Execute a program, and wait for the reply. ARGV are the arguments. The
124 last one must be NULL. */
126 static struct pex_obj *
127 collect_execute (char **argv)
138 for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
139 fprintf (stderr, " %s", str);
141 fprintf (stderr, "\n");
147 pex = pex_init (0, "lto-wrapper", NULL);
149 fatal_perror ("pex_init failed");
151 /* Do not use PEX_LAST here, we use our stdout for communicating with
152 collect2 or the linker-plugin. Any output from the sub-process
153 will confuse that. */
154 errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL,
161 fatal_perror (errmsg);
171 /* Wait for a process to finish, and exit if a nonzero status is found.
172 PROG is the program name. PEX is the process we should wait for. */
175 collect_wait (const char *prog, struct pex_obj *pex)
179 if (!pex_get_status (pex, 1, &status))
180 fatal_perror ("can't get program status");
185 if (WIFSIGNALED (status))
187 int sig = WTERMSIG (status);
188 if (WCOREDUMP (status))
189 fatal ("%s terminated with signal %d [%s], core dumped",
190 prog, sig, strsignal (sig));
192 fatal ("%s terminated with signal %d [%s]",
193 prog, sig, strsignal (sig));
196 if (WIFEXITED (status))
197 fatal ("%s returned %d exit status", prog, WEXITSTATUS (status));
204 /* Unlink a temporary LTRANS file unless requested otherwise. */
207 maybe_unlink_file (const char *file)
211 if (unlink_if_ordinary (file))
212 fatal_perror ("deleting LTRANS file %s", file);
215 fprintf (stderr, "[Leaving LTRANS %s]\n", file);
219 /* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */
222 fork_execute (char **argv)
230 args_name = make_temp_file (".args");
231 at_args = concat ("@", args_name, NULL);
232 args = fopen (args_name, "w");
234 fatal ("failed to open %s", args_name);
236 status = writeargv (&argv[1], args);
239 fatal ("could not write to temporary file %s", args_name);
243 new_argv[0] = argv[0];
244 new_argv[1] = at_args;
247 pex = collect_execute (new_argv);
248 collect_wait (new_argv[0], pex);
250 maybe_unlink_file (args_name);
254 /* Template of LTRANS dumpbase suffix. */
255 #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
257 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
260 run_gcc (unsigned argc, char *argv[])
263 const char **new_argv;
264 const char **argv_ptr;
265 char *list_option_full = NULL;
266 const char *linker_output = NULL;
267 const char *collect_gcc_options, *collect_gcc;
268 struct obstack env_obstack;
272 /* Get the driver and options. */
273 collect_gcc = getenv ("COLLECT_GCC");
275 fatal ("environment variable COLLECT_GCC must be set");
277 /* Set the CFLAGS environment variable. */
278 collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
279 if (!collect_gcc_options)
280 fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
282 /* Count arguments. */
284 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
285 if (collect_gcc_options[j] == '\'')
289 fatal ("malformed COLLECT_GCC_OPTIONS");
291 /* Initalize the common arguments for the driver. */
292 new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
294 *argv_ptr++ = collect_gcc;
295 *argv_ptr++ = "-xlto";
297 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
298 if (collect_gcc_options[j] == '\'')
304 while (collect_gcc_options[j] != '\'')
307 obstack_init (&env_obstack);
308 obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
309 obstack_1grow (&env_obstack, 0);
310 option = XOBFINISH (&env_obstack, char *);
313 linker_output = option;
318 /* If we see -o, skip it and skip and record its argument. */
319 if (option[0] == '-' && option[1] == 'o')
321 if (option[2] == '\0')
324 linker_output = &option[2];
328 if (strcmp (option, "-save-temps") == 0)
330 if (strcmp (option, "-v") == 0)
333 /* We've handled these LTO options, do not pass them on. */
334 if (strcmp (option, "-flto") == 0)
335 lto_mode = LTO_MODE_LTO;
336 else if (strncmp (option, "-fwhopr", 7) == 0)
338 lto_mode = LTO_MODE_WHOPR;
339 if (option[7] == '=')
341 parallel = atoi (option+8);
347 *argv_ptr++ = option;
352 char *output_dir, *base, *name;
354 output_dir = xstrdup (linker_output);
356 for (name = base; *name; name++)
357 if (IS_DIR_SEPARATOR (*name))
361 linker_output = &linker_output[base - output_dir];
362 if (*output_dir == '\0')
364 static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
365 output_dir = current_dir;
367 *argv_ptr++ = "-dumpdir";
368 *argv_ptr++ = output_dir;
370 *argv_ptr++ = "-dumpbase";
375 if (lto_mode == LTO_MODE_LTO)
377 flto_out = make_temp_file (".lto.o");
379 argv_ptr[0] = linker_output;
381 argv_ptr[2] = flto_out;
382 argv_ptr[3] = "-combine";
384 else if (lto_mode == LTO_MODE_WHOPR)
386 const char *list_option = "-fltrans-output-list=";
387 size_t list_option_len = strlen (list_option);
392 char *dumpbase = (char *) xmalloc (strlen (linker_output)
393 + sizeof(".wpa") + 1);
394 strcpy (dumpbase, linker_output);
395 strcat (dumpbase, ".wpa");
396 argv_ptr[0] = dumpbase;
399 ltrans_output_file = make_temp_file (".ltrans.out");
400 list_option_full = (char *) xmalloc (sizeof (char) *
401 (strlen (ltrans_output_file) + list_option_len + 1));
402 tmp = list_option_full;
405 strcpy (tmp, list_option);
406 tmp += list_option_len;
407 strcpy (tmp, ltrans_output_file);
409 argv_ptr[2] = "-fwpa";
410 argv_ptr[3] = "-combine";
413 fatal ("invalid LTO mode");
415 /* Append the input objects and possible preceeding arguments. */
416 for (i = 1; i < argc; ++i)
417 argv_ptr[3 + i] = argv[i];
418 argv_ptr[3 + i] = NULL;
420 fork_execute (CONST_CAST (char **, new_argv));
422 if (lto_mode == LTO_MODE_LTO)
424 printf("%s\n", flto_out);
428 else if (lto_mode == LTO_MODE_WHOPR)
430 FILE *stream = fopen (ltrans_output_file, "r");
432 char **input_names = NULL;
433 char **output_names = NULL;
434 char *makefile = NULL;
435 FILE *mstream = NULL;
438 fatal_perror ("fopen: %s", ltrans_output_file);
440 argv_ptr[1] = "-fltrans";
444 makefile = make_temp_file (".mk");
445 mstream = fopen (makefile, "w");
450 const unsigned piece = 32;
452 char *buf, *input_name = (char *)xmalloc (piece);
457 if (!fgets (buf, piece, stream))
459 len = strlen (input_name);
460 if (input_name[len - 1] != '\n')
462 input_name = (char *)xrealloc (input_name, len + piece);
463 buf = input_name + len;
466 input_name[len - 1] = '\0';
468 if (input_name[0] == '*')
469 output_name = &input_name[1];
472 /* Otherwise, add FILES[I] to lto_execute_ltrans command line
473 and add the resulting file to LTRANS output list. */
475 /* Replace the .o suffix with a .ltrans.o suffix and write
476 the resulting name to the LTRANS output list. */
477 obstack_init (&env_obstack);
478 obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
479 obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
480 output_name = XOBFINISH (&env_obstack, char *);
485 = (char *) xmalloc (strlen (linker_output)
486 + sizeof(DUMPBASE_SUFFIX) + 1);
488 strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
489 "%s.ltrans%u", linker_output, nr);
490 argv_ptr[0] = dumpbase;
494 argv_ptr[3] = output_name;
495 argv_ptr[4] = input_name;
500 fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
501 for (i = 1; new_argv[i] != NULL; ++i)
502 fprintf (mstream, " '%s'", new_argv[i]);
503 fprintf (mstream, "\n");
506 fork_execute (CONST_CAST (char **, new_argv));
510 input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
511 output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
512 input_names[nr-1] = input_name;
513 output_names[nr-1] = output_name;
519 fprintf (mstream, "all:");
520 for (i = 0; i < nr; ++i)
521 fprintf (mstream, " \\\n\t%s", output_names[i]);
522 fprintf (mstream, "\n");
524 new_argv[0] = "make";
526 new_argv[2] = makefile;
527 snprintf (jobs, 31, "-j%d", parallel);
531 pex = collect_execute (CONST_CAST (char **, new_argv));
532 collect_wait (new_argv[0], pex);
533 maybe_unlink_file (makefile);
535 for (i = 0; i < nr; ++i)
537 fputs (output_names[i], stdout);
539 maybe_unlink_file (input_names[i]);
540 free (input_names[i]);
545 maybe_unlink_file (ltrans_output_file);
546 free (list_option_full);
549 fatal ("invalid LTO mode");
551 obstack_free (&env_obstack, NULL);
558 main (int argc, char *argv[])
562 /* We may be called with all the arguments stored in some file and
563 passed with @file. Expand them into argv before processing. */
564 expandargv (&argc, &argv);
565 run_gcc (argc, argv);