OSDN Git Service

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