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 errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL,
158 fatal_perror (errmsg);
168 /* Wait for a process to finish, and exit if a nonzero status is found.
169 PROG is the program name. PEX is the process we should wait for. */
172 collect_wait (const char *prog, struct pex_obj *pex)
176 if (!pex_get_status (pex, 1, &status))
177 fatal_perror ("can't get program status");
182 if (WIFSIGNALED (status))
184 int sig = WTERMSIG (status);
185 if (WCOREDUMP (status))
186 fatal ("%s terminated with signal %d [%s], core dumped",
187 prog, sig, strsignal (sig));
189 fatal ("%s terminated with signal %d [%s]",
190 prog, sig, strsignal (sig));
193 if (WIFEXITED (status))
194 fatal ("%s returned %d exit status", prog, WEXITSTATUS (status));
201 /* Unlink a temporary LTRANS file unless requested otherwise. */
204 maybe_unlink_file (const char *file)
208 if (unlink_if_ordinary (file))
209 fatal_perror ("deleting LTRANS file %s", file);
212 fprintf (stderr, "[Leaving LTRANS %s]\n", file);
216 /* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */
219 fork_execute (char **argv)
227 args_name = make_temp_file (".args");
228 at_args = concat ("@", args_name, NULL);
229 args = fopen (args_name, "w");
231 fatal ("failed to open %s", args_name);
233 status = writeargv (&argv[1], args);
236 fatal ("could not write to temporary file %s", args_name);
240 new_argv[0] = argv[0];
241 new_argv[1] = at_args;
244 pex = collect_execute (new_argv);
245 collect_wait (new_argv[0], pex);
247 maybe_unlink_file (args_name);
251 /* Template of LTRANS dumpbase suffix. */
252 #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
254 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
257 run_gcc (unsigned argc, char *argv[])
260 const char **new_argv;
261 const char **argv_ptr;
262 char *list_option_full = NULL;
263 const char *linker_output = NULL;
264 const char *collect_gcc_options, *collect_gcc;
265 struct obstack env_obstack;
268 /* Get the driver and options. */
269 collect_gcc = getenv ("COLLECT_GCC");
271 fatal ("environment variable COLLECT_GCC must be set");
273 /* Set the CFLAGS environment variable. */
274 collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
275 if (!collect_gcc_options)
276 fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
278 /* Count arguments. */
280 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
281 if (collect_gcc_options[j] == '\'')
285 fatal ("malformed COLLECT_GCC_OPTIONS");
287 /* Initalize the common arguments for the driver. */
288 new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
290 *argv_ptr++ = collect_gcc;
291 *argv_ptr++ = "-xlto";
293 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
294 if (collect_gcc_options[j] == '\'')
300 while (collect_gcc_options[j] != '\'')
303 obstack_init (&env_obstack);
304 obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
305 obstack_1grow (&env_obstack, 0);
306 option = XOBFINISH (&env_obstack, char *);
309 linker_output = option;
314 /* If we see -o, skip it and skip and record its argument. */
315 if (option[0] == '-' && option[1] == 'o')
317 if (option[2] == '\0')
320 linker_output = &option[2];
324 if (strcmp (option, "-save-temps") == 0)
326 if (strcmp (option, "-v") == 0)
329 /* We've handled these LTO options, do not pass them on. */
330 if (strcmp (option, "-flto") == 0)
331 lto_mode = LTO_MODE_LTO;
332 else if (strcmp (option, "-fwhopr") == 0)
333 lto_mode = LTO_MODE_WHOPR;
335 *argv_ptr++ = option;
340 char *output_dir, *base, *name;
342 output_dir = xstrdup (linker_output);
344 for (name = base; *name; name++)
345 if (IS_DIR_SEPARATOR (*name))
349 linker_output = &linker_output[base - output_dir];
350 if (*output_dir == '\0')
352 static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
353 output_dir = current_dir;
355 *argv_ptr++ = "-dumpdir";
356 *argv_ptr++ = output_dir;
358 *argv_ptr++ = "-dumpbase";
363 if (lto_mode == LTO_MODE_LTO)
365 flto_out = make_temp_file (".lto.o");
367 argv_ptr[0] = linker_output;
369 argv_ptr[2] = flto_out;
370 argv_ptr[3] = "-combine";
372 else if (lto_mode == LTO_MODE_WHOPR)
374 const char *list_option = "-fltrans-output-list=";
375 size_t list_option_len = strlen (list_option);
380 char *dumpbase = (char *) xmalloc (strlen (linker_output)
381 + sizeof(".wpa") + 1);
382 strcpy (dumpbase, linker_output);
383 strcat (dumpbase, ".wpa");
384 argv_ptr[0] = dumpbase;
387 ltrans_output_file = make_temp_file (".ltrans.out");
388 list_option_full = (char *) xmalloc (sizeof (char) *
389 (strlen (ltrans_output_file) + list_option_len + 1));
390 tmp = list_option_full;
393 strcpy (tmp, list_option);
394 tmp += list_option_len;
395 strcpy (tmp, ltrans_output_file);
397 argv_ptr[2] = "-fwpa";
398 argv_ptr[3] = "-combine";
401 fatal ("invalid LTO mode");
403 /* Append the input objects and possible preceeding arguments. */
404 for (i = 1; i < argc; ++i)
405 argv_ptr[3 + i] = argv[i];
406 argv_ptr[3 + i] = NULL;
408 fork_execute (CONST_CAST (char **, new_argv));
410 if (lto_mode == LTO_MODE_LTO)
412 printf("%s\n", flto_out);
416 else if (lto_mode == LTO_MODE_WHOPR)
418 FILE *stream = fopen (ltrans_output_file, "r");
422 fatal_perror ("fopen: %s", ltrans_output_file);
424 argv_ptr[1] = "-fltrans";
428 const unsigned piece = 32;
430 char *buf, *input_name = (char *)xmalloc (piece);
435 if (!fgets (buf, piece, stream))
437 len = strlen (input_name);
438 if (input_name[len - 1] != '\n')
440 input_name = (char *)xrealloc (input_name, len + piece);
441 buf = input_name + len;
444 input_name[len - 1] = '\0';
446 if (input_name[0] == '*')
449 output_name = &input_name[1];
453 /* Otherwise, add FILES[I] to lto_execute_ltrans command line
454 and add the resulting file to LTRANS output list. */
456 /* Replace the .o suffix with a .ltrans.o suffix and write
457 the resulting name to the LTRANS output list. */
458 obstack_init (&env_obstack);
459 obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
460 obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
461 output_name = XOBFINISH (&env_obstack, char *);
466 = (char *) xmalloc (strlen (linker_output)
467 + sizeof(DUMPBASE_SUFFIX) + 1);
469 strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
470 "%s.ltrans%d", linker_output, nr++);
471 argv_ptr[0] = dumpbase;
475 argv_ptr[3] = output_name;
476 argv_ptr[4] = input_name;
479 fork_execute (CONST_CAST (char **, new_argv));
481 maybe_unlink_file (input_name);
484 fputs (output_name, stdout);
488 maybe_unlink_file (ltrans_output_file);
489 free (list_option_full);
492 fatal ("invalid LTO mode");
494 obstack_free (&env_obstack, NULL);
501 main (int argc, char *argv[])
505 /* We may be called with all the arguments stored in some file and
506 passed with @file. Expand them into argv before processing. */
507 expandargv (&argc, &argv);
508 run_gcc (argc, argv);