OSDN Git Service

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