OSDN Git Service

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