OSDN Git Service

* gnatvsn.adb (Gnat_Version_String): Don't overrun Ver_Len_Max.
[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 if (lto_mode == LTO_MODE_WHOPR)
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   else
461     fatal ("invalid LTO mode");
462
463   /* Append the input objects and possible preceeding arguments.  */
464   for (i = 1; i < argc; ++i)
465     argv_ptr[2 + i] = argv[i];
466   argv_ptr[2 + i] = NULL;
467
468   fork_execute (CONST_CAST (char **, new_argv));
469
470   if (lto_mode == LTO_MODE_LTO)
471     {
472       printf("%s\n", flto_out);
473       free (flto_out);
474       flto_out = NULL;
475     }
476   else if (lto_mode == LTO_MODE_WHOPR)
477     {
478       FILE *stream = fopen (ltrans_output_file, "r");
479       FILE *mstream = NULL;
480
481       if (!stream)
482         fatal_perror ("fopen: %s", ltrans_output_file);
483
484       /* Parse the list of LTRANS inputs from the WPA stage.  */
485       nr = 0;
486       for (;;)
487         {
488           const unsigned piece = 32;
489           char *output_name = NULL;
490           char *buf, *input_name = (char *)xmalloc (piece);
491           size_t len;
492
493           buf = input_name;
494 cont:
495           if (!fgets (buf, piece, stream))
496             break;
497           len = strlen (input_name);
498           if (input_name[len - 1] != '\n')
499             {
500               input_name = (char *)xrealloc (input_name, len + piece);
501               buf = input_name + len;
502               goto cont;
503             }
504           input_name[len - 1] = '\0';
505
506           if (input_name[0] == '*')
507             output_name = &input_name[1];
508
509           nr++;
510           input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
511           output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
512           input_names[nr-1] = input_name;
513           output_names[nr-1] = output_name;
514         }
515       fclose (stream);
516       maybe_unlink_file (ltrans_output_file);
517       ltrans_output_file = NULL;
518
519       if (parallel)
520         {
521           makefile = make_temp_file (".mk");
522           mstream = fopen (makefile, "w");
523         }
524
525       /* Execute the LTRANS stage for each input file (or prepare a
526          makefile to invoke this in parallel).  */
527       for (i = 0; i < nr; ++i)
528         {
529           char *output_name;
530           char *input_name = input_names[i];
531           /* If it's a pass-through file do nothing.  */
532           if (output_names[i])
533             continue;
534
535           /* Replace the .o suffix with a .ltrans.o suffix and write
536              the resulting name to the LTRANS output list.  */
537           obstack_init (&env_obstack);
538           obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
539           obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
540           output_name = XOBFINISH (&env_obstack, char *);
541
542           /* Adjust the dumpbase if the linker output file was seen.  */
543           if (linker_output)
544             {
545               char *dumpbase
546                   = (char *) xmalloc (strlen (linker_output)
547                                       + sizeof(DUMPBASE_SUFFIX) + 1);
548               snprintf (dumpbase,
549                         strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
550                         "%s.ltrans%u", linker_output, i);
551               argv_ptr[0] = dumpbase;
552             }
553
554           argv_ptr[1] = "-fltrans";
555           argv_ptr[2] = "-o";
556           argv_ptr[3] = output_name;
557           argv_ptr[4] = input_name;
558           argv_ptr[5] = NULL;
559           if (parallel)
560             {
561               fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
562               for (j = 1; new_argv[j] != NULL; ++j)
563                 fprintf (mstream, " '%s'", new_argv[j]);
564               fprintf (mstream, "\n");
565             }
566           else
567             fork_execute (CONST_CAST (char **, new_argv));
568
569           output_names[i] = output_name;
570         }
571       if (parallel)
572         {
573           struct pex_obj *pex;
574           char jobs[32];
575
576           fprintf (mstream, "all:");
577           for (i = 0; i < nr; ++i)
578             fprintf (mstream, " \\\n\t%s", output_names[i]);
579           fprintf (mstream, "\n");
580           fclose (mstream);
581           if (!jobserver)
582             {
583               /* Avoid passing --jobserver-fd= and similar flags 
584                  unless jobserver mode is explicitly enabled.  */
585               putenv (xstrdup ("MAKEFLAGS="));
586               putenv (xstrdup ("MFLAGS="));
587             }
588           new_argv[0] = getenv ("MAKE");
589           if (!new_argv[0])
590             new_argv[0] = "make";
591           new_argv[1] = "-f";
592           new_argv[2] = makefile;
593           i = 3;
594           if (!jobserver)
595             {
596               snprintf (jobs, 31, "-j%d", parallel);
597               new_argv[i++] = jobs;
598             }
599           new_argv[i++] = "all";
600           new_argv[i++] = NULL;
601           pex = collect_execute (CONST_CAST (char **, new_argv));
602           collect_wait (new_argv[0], pex);
603           maybe_unlink_file (makefile);
604           makefile = NULL;
605         }
606       for (i = 0; i < nr; ++i)
607         {
608           fputs (output_names[i], stdout);
609           putc ('\n', stdout);
610           maybe_unlink_file (input_names[i]);
611           free (input_names[i]);
612         }
613       nr = 0;
614       free (output_names);
615       free (input_names);
616       free (list_option_full);
617     }
618   else
619     fatal ("invalid LTO mode");
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 }