OSDN Git Service

Fix for PR debug/43325
[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
47 int debug;                              /* true if -debug */
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
62 static void maybe_unlink_file (const char *);
63
64 /* Delete tempfiles and exit function.  */
65
66 static void
67 lto_wrapper_exit (int status)
68 {
69   static bool cleanup_done = false;
70   if (!cleanup_done)
71     {
72       /* Setting cleanup_done prevents an infinite loop if one of the
73          calls to maybe_unlink_file fails. */
74       cleanup_done = true;
75
76       if (ltrans_output_file)
77         maybe_unlink_file (ltrans_output_file);
78       if (flto_out)
79         maybe_unlink_file (flto_out);
80       if (args_name)
81         maybe_unlink_file (args_name);
82     }
83   exit (status);
84 }
85
86 /* Just die. CMSGID is the error message. */
87
88 static void __attribute__ ((format (printf, 1, 2)))
89 fatal (const char * cmsgid, ...)
90 {
91   va_list ap;
92
93   va_start (ap, cmsgid);
94   fprintf (stderr, "lto-wrapper: ");
95   vfprintf (stderr, _(cmsgid), ap);
96   fprintf (stderr, "\n");
97   va_end (ap);
98
99   lto_wrapper_exit (FATAL_EXIT_CODE);
100 }
101
102
103 /* Die when sys call fails. CMSGID is the error message.  */
104
105 static void __attribute__ ((format (printf, 1, 2)))
106 fatal_perror (const char *cmsgid, ...)
107 {
108   int e = errno;
109   va_list ap;
110
111   va_start (ap, cmsgid);
112   fprintf (stderr, "lto-wrapper: ");
113   vfprintf (stderr, _(cmsgid), ap);
114   fprintf (stderr, ": %s\n", xstrerror (e));
115   va_end (ap);
116
117   lto_wrapper_exit (FATAL_EXIT_CODE);
118 }
119
120
121 /* Execute a program, and wait for the reply. ARGV are the arguments. The
122    last one must be NULL. */
123
124 static struct pex_obj *
125 collect_execute (char **argv)
126 {
127   struct pex_obj *pex;
128   const char *errmsg;
129   int err;
130
131   if (debug)
132     {
133       char **p_argv;
134       const char *str;
135
136       for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
137         fprintf (stderr, " %s", str);
138
139       fprintf (stderr, "\n");
140     }
141
142   fflush (stdout);
143   fflush (stderr);
144
145   pex = pex_init (0, "lto-wrapper", NULL);
146   if (pex == NULL)
147     fatal_perror ("pex_init failed");
148
149   errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL,
150                     NULL, &err);
151   if (errmsg != NULL)
152     {
153       if (err != 0)
154         {
155           errno = err;
156           fatal_perror (errmsg);
157         }
158       else
159         fatal (errmsg);
160     }
161
162   return pex;
163 }
164
165
166 /* Wait for a process to finish, and exit if a nonzero status is found.
167    PROG is the program name. PEX is the process we should wait for. */
168
169 static int
170 collect_wait (const char *prog, struct pex_obj *pex)
171 {
172   int status;
173
174   if (!pex_get_status (pex, 1, &status))
175     fatal_perror ("can't get program status");
176   pex_free (pex);
177
178   if (status)
179     {
180       if (WIFSIGNALED (status))
181         {
182           int sig = WTERMSIG (status);
183           if (WCOREDUMP (status))
184             fatal ("%s terminated with signal %d [%s], core dumped",
185                    prog, sig, strsignal (sig));
186           else
187             fatal ("%s terminated with signal %d [%s]",
188                    prog, sig, strsignal (sig));
189         }
190
191       if (WIFEXITED (status))
192         fatal ("%s returned %d exit status", prog, WEXITSTATUS (status));
193     }
194
195   return 0;
196 }
197
198
199 /* Unlink a temporary LTRANS file unless requested otherwise.  */
200
201 static void
202 maybe_unlink_file (const char *file)
203 {
204   if (! debug)
205     {
206       if (unlink_if_ordinary (file))
207         fatal_perror ("deleting LTRANS file %s", file);
208     }
209   else
210     fprintf (stderr, "[Leaving LTRANS %s]\n", file);
211 }
212
213
214 /* Execute program ARGV[0] with arguments ARGV. Wait for it to finish.  */
215
216 static void
217 fork_execute (char **argv)
218 {
219   struct pex_obj *pex;
220   char *new_argv[3];
221   char *at_args;
222   FILE *args;
223   int status;
224
225   args_name = make_temp_file (".args");
226   at_args = concat ("@", args_name, NULL);
227   args = fopen (args_name, "w");
228   if (args == NULL)
229     fatal ("failed to open %s", args_name);
230
231   status = writeargv (&argv[1], args);
232
233   if (status)
234     fatal ("could not write to temporary file %s",  args_name);
235
236   fclose (args);
237
238   new_argv[0] = argv[0];
239   new_argv[1] = at_args;
240   new_argv[2] = NULL;
241
242   pex = collect_execute (new_argv);
243   collect_wait (new_argv[0], pex);
244
245   maybe_unlink_file (args_name);
246   free (at_args);
247 }
248
249
250 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
251
252 static void
253 run_gcc (unsigned argc, char *argv[])
254 {
255   unsigned i;
256   unsigned new_argc = argc;
257   const char **new_argv;
258   const char **argv_ptr;
259   char *list_option_full = NULL;
260
261   new_argc += 12;
262   new_argv = (const char **) xcalloc (sizeof (char *), new_argc);
263
264   argv_ptr = new_argv;
265
266   *argv_ptr++ = argv[0];
267   *argv_ptr++ = "-combine";
268   *argv_ptr++ = "-x";
269   *argv_ptr++ = "lto";
270   *argv_ptr++ = "-c";
271   if (lto_mode == LTO_MODE_LTO)
272     {
273       flto_out = make_temp_file (".lto.o");
274       *argv_ptr++ = "-o";
275       *argv_ptr++ = flto_out;
276     }
277   else if (lto_mode == LTO_MODE_WHOPR)
278     {
279       const char *list_option = "-fltrans-output-list=";
280       size_t list_option_len = strlen (list_option);
281       char *tmp;
282
283       ltrans_output_file = make_temp_file (".ltrans.out");
284       list_option_full = (char *) xmalloc (sizeof (char) *
285                          (strlen (ltrans_output_file) + list_option_len + 1));
286       tmp = list_option_full;
287
288       *argv_ptr++ = tmp;
289       strcpy (tmp, list_option);
290       tmp += list_option_len;
291       strcpy (tmp, ltrans_output_file);
292
293       *argv_ptr++ = "-fwpa";
294     }
295   else
296     fatal ("invalid LTO mode");
297
298   /* Add inherited GCC options to the LTO back end command line.
299      Filter out some obviously inappropriate options that will
300      conflict with  the options that we force above.  We pass
301      all of the remaining options on to LTO, and let it complain
302      about any it doesn't like. Note that we invoke LTO via the
303      `gcc' driver, so the usual option processing takes place.
304      Except for `-flto' and `-fwhopr', we should only filter options that
305      are meaningful to `ld', lest an option go silently unclaimed.  */
306   for (i = 1; i < argc; i++)
307     {
308       const char *s = argv[i];
309
310       if (strcmp (s, "-flto") == 0 || strcmp (s, "-fwhopr") == 0)
311         /* We've handled this LTO option, don't pass it on.  */
312         ;
313       else if (*s == '-' && s[1] == 'o')
314         {
315           /* Drop `-o' and its filename argument.  We will use a
316              temporary file for the LTO output.  The `-o' option
317              will be interpreted by the linker.  */
318           if (s[2] == '\0')
319             {
320               char *output_dir, *base, *name;
321
322               i++;
323               output_dir = xstrdup (argv[i]);
324               base = output_dir;
325               for (name = base; *name; name++)
326                 if (IS_DIR_SEPARATOR (*name))
327                   base = name + 1;
328               *base = '\0';
329
330               *argv_ptr++ = "-dumpbase";
331               if (*output_dir == '\0')
332                 {
333                   static char current_dir[] =
334                     { '.', DIR_SEPARATOR, '\0' };
335                   output_dir = current_dir;
336                   *argv_ptr++ = argv[i];
337                 }
338               else
339                 *argv_ptr++ = &argv[i][base - output_dir];
340
341               *argv_ptr++ = "-dumpdir";
342               *argv_ptr++ = output_dir;
343             }
344         }
345       else
346         /* Pass the option or argument to LTO.  */
347         *argv_ptr++ = s;
348     }
349
350   *argv_ptr = NULL;
351
352   fork_execute (CONST_CAST (char **, new_argv));
353   free (new_argv);
354   new_argv = NULL;
355
356   if (lto_mode == LTO_MODE_LTO)
357     {
358       printf("%s\n", flto_out);
359       free (flto_out);
360       flto_out = NULL;
361     }
362   else if (lto_mode == LTO_MODE_WHOPR)
363     {
364       FILE *stream = fopen (ltrans_output_file, "r");
365       int c;
366
367       if (!stream)
368         fatal_perror ("fopen: %s", ltrans_output_file);
369
370       while ((c = getc (stream)) != EOF)
371         putc (c, stdout);
372       fclose (stream);
373       maybe_unlink_file (ltrans_output_file);
374       free (list_option_full);
375     }
376   else
377     fatal ("invalid LTO mode");
378 }
379
380
381 /* Parse the command line. Copy any unused argument to GCC_ARGV. ARGC is the
382    number of arguments. ARGV contains the arguments. */
383
384 static int
385 process_args (int argc, char *argv[], char *gcc_argv[])
386 {
387   int i;
388   int j = 0;
389
390   for (i = 1; i < argc; i ++)
391     {
392       if (! strcmp (argv[i], "-debug"))
393         debug = 1;
394       else if (! strcmp (argv[i], "-flto"))
395         lto_mode = LTO_MODE_LTO;
396       else if (! strcmp (argv[i], "-fwhopr"))
397         lto_mode = LTO_MODE_WHOPR;
398       else
399         {
400           gcc_argv[j] = argv[i];
401           j++;
402         }
403     }
404
405   return j;
406 }
407
408
409 /* Entry point.  */
410
411 int
412 main (int argc, char *argv[])
413 {
414   char **gcc_argv;
415   int gcc_argc;
416
417   gcc_init_libintl ();
418
419   /* We may be called with all the arguments stored in some file and
420      passed with @file.  Expand them into argv before processing.  */
421   expandargv (&argc, &argv);
422   gcc_argv = (char **) xcalloc (sizeof (char *), argc);
423   gcc_argc = process_args (argc, argv, gcc_argv);
424   run_gcc (gcc_argc, gcc_argv);
425   free (gcc_argv);
426
427   return 0;
428 }