OSDN Git Service

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