xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/lto-wrapper.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
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 }
429