OSDN Git Service

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