OSDN Git Service

* common.opt (fwhopr=): Update for -fwhopr=jobserver
[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 -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"
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
308   /* Get the driver and options.  */
309   collect_gcc = getenv ("COLLECT_GCC");
310   if (!collect_gcc)
311     fatal ("environment variable COLLECT_GCC must be set");
312
313   /* Set the CFLAGS environment variable.  */
314   collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
315   if (!collect_gcc_options)
316     fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
317
318   /* Count arguments.  */
319   i = 0;
320   for (j = 0; collect_gcc_options[j] != '\0'; ++j)
321     if (collect_gcc_options[j] == '\'')
322       ++i;
323
324   if (i % 2 != 0)
325     fatal ("malformed COLLECT_GCC_OPTIONS");
326
327   /* Initalize the common arguments for the driver.  */
328   new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
329   argv_ptr = new_argv;
330   *argv_ptr++ = collect_gcc;
331   *argv_ptr++ = "-xlto";
332   *argv_ptr++ = "-c";
333   for (j = 0; collect_gcc_options[j] != '\0'; ++j)
334     if (collect_gcc_options[j] == '\'')
335       {
336         char *option;
337
338         ++j;
339         i = j;
340         while (collect_gcc_options[j] != '\'')
341           ++j;
342
343         obstack_init (&env_obstack);
344         obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
345         obstack_1grow (&env_obstack, 0);
346         option = XOBFINISH (&env_obstack, char *);
347         if (seen_o)
348           {
349             linker_output = option;
350             seen_o = false;
351             continue;
352           }
353
354         /* If we see -o, skip it and skip and record its argument.  */
355         if (option[0] == '-' && option[1] == 'o')
356           {
357             if (option[2] == '\0')
358               seen_o = true;
359             else
360               linker_output = &option[2];
361             continue;
362           }
363
364         if (strcmp (option, "-save-temps") == 0)
365           debug = 1;
366         if (strcmp (option, "-v") == 0)
367           verbose = 1;
368
369         /* We've handled these LTO options, do not pass them on.  */
370         if (strcmp (option, "-flto") == 0)
371           lto_mode = LTO_MODE_LTO;
372         else if (strncmp (option, "-fwhopr", 7) == 0)
373           {
374             lto_mode = LTO_MODE_WHOPR;
375             if (option[7] == '=')
376               {
377                 if (!strcmp (option + 8, "jobserver"))
378                   {
379                     jobserver = 1;
380                     parallel = 1;
381                   }
382                 else
383                   {
384                     parallel = atoi (option+8);
385                     if (parallel <= 1)
386                       parallel = 0;
387                   }
388               }
389           }
390         else
391           *argv_ptr++ = option;
392       }
393
394   if (linker_output)
395     {
396       char *output_dir, *base, *name;
397
398       output_dir = xstrdup (linker_output);
399       base = output_dir;
400       for (name = base; *name; name++)
401         if (IS_DIR_SEPARATOR (*name))
402           base = name + 1;
403       *base = '\0';
404
405       linker_output = &linker_output[base - output_dir];
406       if (*output_dir == '\0')
407         {
408           static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
409           output_dir = current_dir;
410         }
411       *argv_ptr++ = "-dumpdir";
412       *argv_ptr++ = output_dir;
413
414       *argv_ptr++ = "-dumpbase";
415     }
416   else
417     argv_ptr--;
418
419   if (lto_mode == LTO_MODE_LTO)
420     {
421       flto_out = make_temp_file (".lto.o");
422       if (linker_output)
423         argv_ptr[0] = linker_output;
424       argv_ptr[1] = "-o";
425       argv_ptr[2] = flto_out;
426       argv_ptr[3] = "-combine";
427     }
428   else if (lto_mode == LTO_MODE_WHOPR)
429     {
430       const char *list_option = "-fltrans-output-list=";
431       size_t list_option_len = strlen (list_option);
432       char *tmp;
433
434       if (linker_output)
435         {
436           char *dumpbase = (char *) xmalloc (strlen (linker_output)
437                                              + sizeof (".wpa") + 1);
438           strcpy (dumpbase, linker_output);
439           strcat (dumpbase, ".wpa");
440           argv_ptr[0] = dumpbase;
441         }
442
443       if (linker_output && debug)
444         {
445           ltrans_output_file = (char *) xmalloc (strlen (linker_output)
446                                                  + sizeof (".ltrans.out") + 1);
447           strcpy (ltrans_output_file, linker_output);
448           strcat (ltrans_output_file, ".ltrans.out");
449         }
450       else
451         ltrans_output_file = make_temp_file (".ltrans.out");
452       list_option_full = (char *) xmalloc (sizeof (char) *
453                          (strlen (ltrans_output_file) + list_option_len + 1));
454       tmp = list_option_full;
455
456       argv_ptr[1] = tmp;
457       strcpy (tmp, list_option);
458       tmp += list_option_len;
459       strcpy (tmp, ltrans_output_file);
460
461       argv_ptr[2] = "-fwpa";
462       argv_ptr[3] = "-combine";
463     }
464   else
465     fatal ("invalid LTO mode");
466
467   /* Append the input objects and possible preceeding arguments.  */
468   for (i = 1; i < argc; ++i)
469     argv_ptr[3 + i] = argv[i];
470   argv_ptr[3 + i] = NULL;
471
472   fork_execute (CONST_CAST (char **, new_argv));
473
474   if (lto_mode == LTO_MODE_LTO)
475     {
476       printf("%s\n", flto_out);
477       free (flto_out);
478       flto_out = NULL;
479     }
480   else if (lto_mode == LTO_MODE_WHOPR)
481     {
482       FILE *stream = fopen (ltrans_output_file, "r");
483       FILE *mstream = NULL;
484
485       if (!stream)
486         fatal_perror ("fopen: %s", ltrans_output_file);
487
488       /* Parse the list of LTRANS inputs from the WPA stage.  */
489       nr = 0;
490       for (;;)
491         {
492           const unsigned piece = 32;
493           char *output_name = NULL;
494           char *buf, *input_name = (char *)xmalloc (piece);
495           size_t len;
496
497           buf = input_name;
498 cont:
499           if (!fgets (buf, piece, stream))
500             break;
501           len = strlen (input_name);
502           if (input_name[len - 1] != '\n')
503             {
504               input_name = (char *)xrealloc (input_name, len + piece);
505               buf = input_name + len;
506               goto cont;
507             }
508           input_name[len - 1] = '\0';
509
510           if (input_name[0] == '*')
511             output_name = &input_name[1];
512
513           nr++;
514           input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
515           output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
516           input_names[nr-1] = input_name;
517           output_names[nr-1] = output_name;
518         }
519       fclose (stream);
520       maybe_unlink_file (ltrans_output_file);
521       ltrans_output_file = NULL;
522
523       if (parallel)
524         {
525           makefile = make_temp_file (".mk");
526           mstream = fopen (makefile, "w");
527         }
528
529       /* Execute the LTRANS stage for each input file (or prepare a
530          makefile to invoke this in parallel).  */
531       for (i = 0; i < nr; ++i)
532         {
533           char *output_name;
534           char *input_name = input_names[i];
535           /* If it's a pass-through file do nothing.  */
536           if (output_names[i])
537             continue;
538
539           /* Replace the .o suffix with a .ltrans.o suffix and write
540              the resulting name to the LTRANS output list.  */
541           obstack_init (&env_obstack);
542           obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
543           obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
544           output_name = XOBFINISH (&env_obstack, char *);
545
546           /* Adjust the dumpbase if the linker output file was seen.  */
547           if (linker_output)
548             {
549               char *dumpbase
550                   = (char *) xmalloc (strlen (linker_output)
551                                       + sizeof(DUMPBASE_SUFFIX) + 1);
552               snprintf (dumpbase,
553                         strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
554                         "%s.ltrans%u", linker_output, i);
555               argv_ptr[0] = dumpbase;
556             }
557
558           argv_ptr[1] = "-fltrans";
559           argv_ptr[2] = "-o";
560           argv_ptr[3] = output_name;
561           argv_ptr[4] = input_name;
562           argv_ptr[5] = NULL;
563           if (parallel)
564             {
565               fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
566               for (j = 1; new_argv[j] != NULL; ++j)
567                 fprintf (mstream, " '%s'", new_argv[j]);
568               fprintf (mstream, "\n");
569             }
570           else
571             fork_execute (CONST_CAST (char **, new_argv));
572
573           output_names[i] = output_name;
574         }
575       if (parallel)
576         {
577           struct pex_obj *pex;
578           char jobs[32];
579
580           fprintf (mstream, "all:");
581           for (i = 0; i < nr; ++i)
582             fprintf (mstream, " \\\n\t%s", output_names[i]);
583           fprintf (mstream, "\n");
584           fclose (mstream);
585           if (!jobserver)
586             {
587               /* Avoid passing --jobserver-fd= and similar flags 
588                  unless jobserver mode is explicitly enabled.  */
589               putenv (xstrdup ("MAKEFLAGS="));
590               putenv (xstrdup ("MFLAGS="));
591             }
592           new_argv[0] = getenv ("MAKE");
593           if (!new_argv[0])
594             new_argv[0] = "make";
595           new_argv[1] = "-f";
596           new_argv[2] = makefile;
597           i = 3;
598           if (!jobserver)
599             {
600               snprintf (jobs, 31, "-j%d", parallel);
601               new_argv[i++] = jobs;
602             }
603           new_argv[i++] = "all";
604           new_argv[i++] = NULL;
605           pex = collect_execute (CONST_CAST (char **, new_argv));
606           collect_wait (new_argv[0], pex);
607           maybe_unlink_file (makefile);
608           makefile = NULL;
609         }
610       for (i = 0; i < nr; ++i)
611         {
612           fputs (output_names[i], stdout);
613           putc ('\n', stdout);
614           maybe_unlink_file (input_names[i]);
615           free (input_names[i]);
616         }
617       nr = 0;
618       free (output_names);
619       free (input_names);
620       free (list_option_full);
621     }
622   else
623     fatal ("invalid LTO mode");
624
625   obstack_free (&env_obstack, NULL);
626 }
627
628
629 /* Entry point.  */
630
631 int
632 main (int argc, char *argv[])
633 {
634   gcc_init_libintl ();
635
636   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
637     signal (SIGINT, fatal_signal);
638 #ifdef SIGHUP
639   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
640     signal (SIGHUP, fatal_signal);
641 #endif
642   if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
643     signal (SIGTERM, fatal_signal);
644 #ifdef SIGPIPE
645   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
646     signal (SIGPIPE, fatal_signal);
647 #endif
648 #ifdef SIGCHLD
649   /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
650      receive the signal.  A different setting is inheritable */
651   signal (SIGCHLD, SIG_DFL);
652 #endif
653
654   /* We may be called with all the arguments stored in some file and
655      passed with @file.  Expand them into argv before processing.  */
656   expandargv (&argc, &argv);
657   run_gcc (argc, argv);
658
659   return 0;
660 }