OSDN Git Service

doc: fix deftypefn markup in gccint manual.
[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
396       output_dir = xstrdup (linker_output);
397       base = output_dir;
398       for (name = base; *name; name++)
399         if (IS_DIR_SEPARATOR (*name))
400           base = name + 1;
401       *base = '\0';
402
403       linker_output = &linker_output[base - output_dir];
404       if (*output_dir == '\0')
405         {
406           static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
407           output_dir = current_dir;
408         }
409       *argv_ptr++ = "-dumpdir";
410       *argv_ptr++ = output_dir;
411
412       *argv_ptr++ = "-dumpbase";
413     }
414   else
415     argv_ptr--;
416
417   if (lto_mode == LTO_MODE_LTO)
418     {
419       flto_out = make_temp_file (".lto.o");
420       if (linker_output)
421         argv_ptr[0] = linker_output;
422       argv_ptr[1] = "-o";
423       argv_ptr[2] = flto_out;
424     }
425   else 
426     {
427       const char *list_option = "-fltrans-output-list=";
428       size_t list_option_len = strlen (list_option);
429       char *tmp;
430
431       if (linker_output)
432         {
433           char *dumpbase = (char *) xmalloc (strlen (linker_output)
434                                              + sizeof (".wpa") + 1);
435           strcpy (dumpbase, linker_output);
436           strcat (dumpbase, ".wpa");
437           argv_ptr[0] = dumpbase;
438         }
439
440       if (linker_output && debug)
441         {
442           ltrans_output_file = (char *) xmalloc (strlen (linker_output)
443                                                  + sizeof (".ltrans.out") + 1);
444           strcpy (ltrans_output_file, linker_output);
445           strcat (ltrans_output_file, ".ltrans.out");
446         }
447       else
448         ltrans_output_file = make_temp_file (".ltrans.out");
449       list_option_full = (char *) xmalloc (sizeof (char) *
450                          (strlen (ltrans_output_file) + list_option_len + 1));
451       tmp = list_option_full;
452
453       argv_ptr[1] = tmp;
454       strcpy (tmp, list_option);
455       tmp += list_option_len;
456       strcpy (tmp, ltrans_output_file);
457
458       argv_ptr[2] = "-fwpa";
459     }
460
461   /* Append the input objects and possible preceeding arguments.  */
462   for (i = 1; i < argc; ++i)
463     argv_ptr[2 + i] = argv[i];
464   argv_ptr[2 + i] = NULL;
465
466   fork_execute (CONST_CAST (char **, new_argv));
467
468   if (lto_mode == LTO_MODE_LTO)
469     {
470       printf("%s\n", flto_out);
471       free (flto_out);
472       flto_out = NULL;
473     }
474   else
475     {
476       FILE *stream = fopen (ltrans_output_file, "r");
477       FILE *mstream = NULL;
478
479       if (!stream)
480         fatal_perror ("fopen: %s", ltrans_output_file);
481
482       /* Parse the list of LTRANS inputs from the WPA stage.  */
483       nr = 0;
484       for (;;)
485         {
486           const unsigned piece = 32;
487           char *output_name = NULL;
488           char *buf, *input_name = (char *)xmalloc (piece);
489           size_t len;
490
491           buf = input_name;
492 cont:
493           if (!fgets (buf, piece, stream))
494             break;
495           len = strlen (input_name);
496           if (input_name[len - 1] != '\n')
497             {
498               input_name = (char *)xrealloc (input_name, len + piece);
499               buf = input_name + len;
500               goto cont;
501             }
502           input_name[len - 1] = '\0';
503
504           if (input_name[0] == '*')
505             output_name = &input_name[1];
506
507           nr++;
508           input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
509           output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
510           input_names[nr-1] = input_name;
511           output_names[nr-1] = output_name;
512         }
513       fclose (stream);
514       maybe_unlink_file (ltrans_output_file);
515       ltrans_output_file = NULL;
516
517       if (parallel)
518         {
519           makefile = make_temp_file (".mk");
520           mstream = fopen (makefile, "w");
521         }
522
523       /* Execute the LTRANS stage for each input file (or prepare a
524          makefile to invoke this in parallel).  */
525       for (i = 0; i < nr; ++i)
526         {
527           char *output_name;
528           char *input_name = input_names[i];
529           /* If it's a pass-through file do nothing.  */
530           if (output_names[i])
531             continue;
532
533           /* Replace the .o suffix with a .ltrans.o suffix and write
534              the resulting name to the LTRANS output list.  */
535           obstack_init (&env_obstack);
536           obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
537           obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
538           output_name = XOBFINISH (&env_obstack, char *);
539
540           /* Adjust the dumpbase if the linker output file was seen.  */
541           if (linker_output)
542             {
543               char *dumpbase
544                   = (char *) xmalloc (strlen (linker_output)
545                                       + sizeof(DUMPBASE_SUFFIX) + 1);
546               snprintf (dumpbase,
547                         strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
548                         "%s.ltrans%u", linker_output, i);
549               argv_ptr[0] = dumpbase;
550             }
551
552           argv_ptr[1] = "-fltrans";
553           argv_ptr[2] = "-o";
554           argv_ptr[3] = output_name;
555           argv_ptr[4] = input_name;
556           argv_ptr[5] = NULL;
557           if (parallel)
558             {
559               fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
560               for (j = 1; new_argv[j] != NULL; ++j)
561                 fprintf (mstream, " '%s'", new_argv[j]);
562               fprintf (mstream, "\n");
563             }
564           else
565             fork_execute (CONST_CAST (char **, new_argv));
566
567           output_names[i] = output_name;
568         }
569       if (parallel)
570         {
571           struct pex_obj *pex;
572           char jobs[32];
573
574           fprintf (mstream, "all:");
575           for (i = 0; i < nr; ++i)
576             fprintf (mstream, " \\\n\t%s", output_names[i]);
577           fprintf (mstream, "\n");
578           fclose (mstream);
579           if (!jobserver)
580             {
581               /* Avoid passing --jobserver-fd= and similar flags 
582                  unless jobserver mode is explicitly enabled.  */
583               putenv (xstrdup ("MAKEFLAGS="));
584               putenv (xstrdup ("MFLAGS="));
585             }
586           new_argv[0] = getenv ("MAKE");
587           if (!new_argv[0])
588             new_argv[0] = "make";
589           new_argv[1] = "-f";
590           new_argv[2] = makefile;
591           i = 3;
592           if (!jobserver)
593             {
594               snprintf (jobs, 31, "-j%d", parallel);
595               new_argv[i++] = jobs;
596             }
597           new_argv[i++] = "all";
598           new_argv[i++] = NULL;
599           pex = collect_execute (CONST_CAST (char **, new_argv));
600           collect_wait (new_argv[0], pex);
601           maybe_unlink_file (makefile);
602           makefile = NULL;
603         }
604       for (i = 0; i < nr; ++i)
605         {
606           fputs (output_names[i], stdout);
607           putc ('\n', stdout);
608           maybe_unlink_file (input_names[i]);
609           free (input_names[i]);
610         }
611       nr = 0;
612       free (output_names);
613       free (input_names);
614       free (list_option_full);
615     }
616
617   obstack_free (&env_obstack, NULL);
618 }
619
620
621 /* Entry point.  */
622
623 int
624 main (int argc, char *argv[])
625 {
626   gcc_init_libintl ();
627
628   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
629     signal (SIGINT, fatal_signal);
630 #ifdef SIGHUP
631   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
632     signal (SIGHUP, fatal_signal);
633 #endif
634   if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
635     signal (SIGTERM, fatal_signal);
636 #ifdef SIGPIPE
637   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
638     signal (SIGPIPE, fatal_signal);
639 #endif
640 #ifdef SIGCHLD
641   /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
642      receive the signal.  A different setting is inheritable */
643   signal (SIGCHLD, SIG_DFL);
644 #endif
645
646   /* We may be called with all the arguments stored in some file and
647      passed with @file.  Expand them into argv before processing.  */
648   expandargv (&argc, &argv);
649   run_gcc (argc, argv);
650
651   return 0;
652 }