xref: /dflybsd-src/contrib/gcc-4.7/gcc/lto-wrapper.c (revision 81fc95a5293ee307c688a350a3feb4734aaddbb4)
1e4b17023SJohn Marino /* Wrapper to call lto.  Used by collect2 and the linker plugin.
2e4b17023SJohn Marino    Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3e4b17023SJohn Marino 
4e4b17023SJohn Marino    Factored out of collect2 by Rafael Espindola <espindola@google.com>
5e4b17023SJohn Marino 
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino 
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11e4b17023SJohn Marino version.
12e4b17023SJohn Marino 
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16e4b17023SJohn Marino for more details.
17e4b17023SJohn Marino 
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21e4b17023SJohn Marino 
22e4b17023SJohn Marino 
23e4b17023SJohn Marino /* This program is passed a gcc, a list of gcc arguments and a list of
24e4b17023SJohn Marino    object files containing IL. It scans the argument list to check if
25e4b17023SJohn Marino    we are in whopr mode or not modifies the arguments and needed and
26e4b17023SJohn Marino    prints a list of output files on stdout.
27e4b17023SJohn Marino 
28e4b17023SJohn Marino    Example:
29e4b17023SJohn Marino 
30e4b17023SJohn Marino    $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto
31e4b17023SJohn Marino 
32e4b17023SJohn Marino    The above will print something like
33e4b17023SJohn Marino    /tmp/ccwbQ8B2.lto.o
34e4b17023SJohn Marino 
35e4b17023SJohn Marino    If WHOPR is used instead, more than one file might be produced
36e4b17023SJohn Marino    ./ccXj2DTk.lto.ltrans.o
37e4b17023SJohn Marino    ./ccCJuXGv.lto.ltrans.o
38e4b17023SJohn Marino */
39e4b17023SJohn Marino 
40e4b17023SJohn Marino #include "config.h"
41e4b17023SJohn Marino #include "system.h"
42e4b17023SJohn Marino #include "coretypes.h"
43e4b17023SJohn Marino #include "intl.h"
44e4b17023SJohn Marino #include "diagnostic.h"
45e4b17023SJohn Marino #include "obstack.h"
46e4b17023SJohn Marino #include "opts.h"
47e4b17023SJohn Marino #include "options.h"
48e4b17023SJohn Marino #include "simple-object.h"
49e4b17023SJohn Marino 
50e4b17023SJohn Marino /* From lto-streamer.h which we cannot include with -fkeep-inline-functions.
51e4b17023SJohn Marino    ???  Split out a lto-streamer-core.h.  */
52e4b17023SJohn Marino 
53e4b17023SJohn Marino #define LTO_SECTION_NAME_PREFIX         ".gnu.lto_"
54e4b17023SJohn Marino 
55e4b17023SJohn Marino /* End of lto-streamer.h copy.  */
56e4b17023SJohn Marino 
57e4b17023SJohn Marino int debug;				/* true if -save-temps.  */
58e4b17023SJohn Marino int verbose;				/* true if -v.  */
59e4b17023SJohn Marino 
60e4b17023SJohn Marino enum lto_mode_d {
61e4b17023SJohn Marino   LTO_MODE_NONE,			/* Not doing LTO.  */
62e4b17023SJohn Marino   LTO_MODE_LTO,				/* Normal LTO.  */
63e4b17023SJohn Marino   LTO_MODE_WHOPR			/* WHOPR.  */
64e4b17023SJohn Marino };
65e4b17023SJohn Marino 
66e4b17023SJohn Marino /* Current LTO mode.  */
67e4b17023SJohn Marino static enum lto_mode_d lto_mode = LTO_MODE_NONE;
68e4b17023SJohn Marino 
69e4b17023SJohn Marino static char *ltrans_output_file;
70e4b17023SJohn Marino static char *flto_out;
71e4b17023SJohn Marino static char *args_name;
72e4b17023SJohn Marino static unsigned int nr;
73e4b17023SJohn Marino static char **input_names;
74e4b17023SJohn Marino static char **output_names;
75e4b17023SJohn Marino static char *makefile;
76e4b17023SJohn Marino 
77e4b17023SJohn Marino static void maybe_unlink_file (const char *);
78e4b17023SJohn Marino 
79e4b17023SJohn Marino  /* Delete tempfiles.  */
80e4b17023SJohn Marino 
81e4b17023SJohn Marino static void
lto_wrapper_cleanup(void)82e4b17023SJohn Marino lto_wrapper_cleanup (void)
83e4b17023SJohn Marino {
84e4b17023SJohn Marino   static bool cleanup_done = false;
85e4b17023SJohn Marino   unsigned int i;
86e4b17023SJohn Marino 
87e4b17023SJohn Marino   if (cleanup_done)
88e4b17023SJohn Marino     return;
89e4b17023SJohn Marino 
90e4b17023SJohn Marino   /* Setting cleanup_done prevents an infinite loop if one of the
91e4b17023SJohn Marino      calls to maybe_unlink_file fails. */
92e4b17023SJohn Marino   cleanup_done = true;
93e4b17023SJohn Marino 
94e4b17023SJohn Marino   if (ltrans_output_file)
95e4b17023SJohn Marino     maybe_unlink_file (ltrans_output_file);
96e4b17023SJohn Marino   if (flto_out)
97e4b17023SJohn Marino     maybe_unlink_file (flto_out);
98e4b17023SJohn Marino   if (args_name)
99e4b17023SJohn Marino     maybe_unlink_file (args_name);
100e4b17023SJohn Marino   if (makefile)
101e4b17023SJohn Marino     maybe_unlink_file (makefile);
102e4b17023SJohn Marino   for (i = 0; i < nr; ++i)
103e4b17023SJohn Marino     {
104e4b17023SJohn Marino       maybe_unlink_file (input_names[i]);
105e4b17023SJohn Marino       if (output_names[i])
106e4b17023SJohn Marino 	maybe_unlink_file (output_names[i]);
107e4b17023SJohn Marino     }
108e4b17023SJohn Marino }
109e4b17023SJohn Marino 
110e4b17023SJohn Marino static void
fatal_signal(int signum)111e4b17023SJohn Marino fatal_signal (int signum)
112e4b17023SJohn Marino {
113e4b17023SJohn Marino   signal (signum, SIG_DFL);
114e4b17023SJohn Marino   lto_wrapper_cleanup ();
115e4b17023SJohn Marino   /* Get the same signal again, this time not handled,
116e4b17023SJohn Marino      so its normal effect occurs.  */
117e4b17023SJohn Marino   kill (getpid (), signum);
118e4b17023SJohn Marino }
119e4b17023SJohn Marino 
120e4b17023SJohn Marino /* Just die. CMSGID is the error message. */
121e4b17023SJohn Marino 
122e4b17023SJohn Marino static void __attribute__ ((format (printf, 1, 2)))
fatal(const char * cmsgid,...)123e4b17023SJohn Marino fatal (const char * cmsgid, ...)
124e4b17023SJohn Marino {
125e4b17023SJohn Marino   va_list ap;
126e4b17023SJohn Marino 
127e4b17023SJohn Marino   va_start (ap, cmsgid);
128e4b17023SJohn Marino   fprintf (stderr, "lto-wrapper: ");
129e4b17023SJohn Marino   vfprintf (stderr, _(cmsgid), ap);
130e4b17023SJohn Marino   fprintf (stderr, "\n");
131e4b17023SJohn Marino   va_end (ap);
132e4b17023SJohn Marino 
133e4b17023SJohn Marino   lto_wrapper_cleanup ();
134e4b17023SJohn Marino   exit (FATAL_EXIT_CODE);
135e4b17023SJohn Marino }
136e4b17023SJohn Marino 
137e4b17023SJohn Marino 
138e4b17023SJohn Marino /* Die when sys call fails. CMSGID is the error message.  */
139e4b17023SJohn Marino 
140e4b17023SJohn Marino static void __attribute__ ((format (printf, 1, 2)))
fatal_perror(const char * cmsgid,...)141e4b17023SJohn Marino fatal_perror (const char *cmsgid, ...)
142e4b17023SJohn Marino {
143e4b17023SJohn Marino   int e = errno;
144e4b17023SJohn Marino   va_list ap;
145e4b17023SJohn Marino 
146e4b17023SJohn Marino   va_start (ap, cmsgid);
147e4b17023SJohn Marino   fprintf (stderr, "lto-wrapper: ");
148e4b17023SJohn Marino   vfprintf (stderr, _(cmsgid), ap);
149e4b17023SJohn Marino   fprintf (stderr, ": %s\n", xstrerror (e));
150e4b17023SJohn Marino   va_end (ap);
151e4b17023SJohn Marino 
152e4b17023SJohn Marino   lto_wrapper_cleanup ();
153e4b17023SJohn Marino   exit (FATAL_EXIT_CODE);
154e4b17023SJohn Marino }
155e4b17023SJohn Marino 
156e4b17023SJohn Marino 
157e4b17023SJohn Marino /* Execute a program, and wait for the reply. ARGV are the arguments. The
158e4b17023SJohn Marino    last one must be NULL. */
159e4b17023SJohn Marino 
160e4b17023SJohn Marino static struct pex_obj *
collect_execute(char ** argv)161e4b17023SJohn Marino collect_execute (char **argv)
162e4b17023SJohn Marino {
163e4b17023SJohn Marino   struct pex_obj *pex;
164e4b17023SJohn Marino   const char *errmsg;
165e4b17023SJohn Marino   int err;
166e4b17023SJohn Marino 
167e4b17023SJohn Marino   if (verbose)
168e4b17023SJohn Marino     {
169e4b17023SJohn Marino       char **p_argv;
170e4b17023SJohn Marino       const char *str;
171e4b17023SJohn Marino 
172e4b17023SJohn Marino       for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
173e4b17023SJohn Marino 	fprintf (stderr, " %s", str);
174e4b17023SJohn Marino 
175e4b17023SJohn Marino       fprintf (stderr, "\n");
176e4b17023SJohn Marino     }
177e4b17023SJohn Marino 
178e4b17023SJohn Marino   fflush (stdout);
179e4b17023SJohn Marino   fflush (stderr);
180e4b17023SJohn Marino 
181e4b17023SJohn Marino   pex = pex_init (0, "lto-wrapper", NULL);
182e4b17023SJohn Marino   if (pex == NULL)
183e4b17023SJohn Marino     fatal_perror ("pex_init failed");
184e4b17023SJohn Marino 
185e4b17023SJohn Marino   /* Do not use PEX_LAST here, we use our stdout for communicating with
186e4b17023SJohn Marino      collect2 or the linker-plugin.  Any output from the sub-process
187e4b17023SJohn Marino      will confuse that.  */
188e4b17023SJohn Marino   errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL,
189e4b17023SJohn Marino 		    NULL, &err);
190e4b17023SJohn Marino   if (errmsg != NULL)
191e4b17023SJohn Marino     {
192e4b17023SJohn Marino       if (err != 0)
193e4b17023SJohn Marino 	{
194e4b17023SJohn Marino 	  errno = err;
195e4b17023SJohn Marino 	  fatal_perror (errmsg);
196e4b17023SJohn Marino 	}
197e4b17023SJohn Marino       else
198e4b17023SJohn Marino 	fatal (errmsg);
199e4b17023SJohn Marino     }
200e4b17023SJohn Marino 
201e4b17023SJohn Marino   return pex;
202e4b17023SJohn Marino }
203e4b17023SJohn Marino 
204e4b17023SJohn Marino 
205e4b17023SJohn Marino /* Wait for a process to finish, and exit if a nonzero status is found.
206e4b17023SJohn Marino    PROG is the program name. PEX is the process we should wait for. */
207e4b17023SJohn Marino 
208e4b17023SJohn Marino static int
collect_wait(const char * prog,struct pex_obj * pex)209e4b17023SJohn Marino collect_wait (const char *prog, struct pex_obj *pex)
210e4b17023SJohn Marino {
211e4b17023SJohn Marino   int status;
212e4b17023SJohn Marino 
213e4b17023SJohn Marino   if (!pex_get_status (pex, 1, &status))
214e4b17023SJohn Marino     fatal_perror ("can't get program status");
215e4b17023SJohn Marino   pex_free (pex);
216e4b17023SJohn Marino 
217e4b17023SJohn Marino   if (status)
218e4b17023SJohn Marino     {
219e4b17023SJohn Marino       if (WIFSIGNALED (status))
220e4b17023SJohn Marino 	{
221e4b17023SJohn Marino 	  int sig = WTERMSIG (status);
222e4b17023SJohn Marino 	  if (WCOREDUMP (status))
223e4b17023SJohn Marino 	    fatal ("%s terminated with signal %d [%s], core dumped",
224e4b17023SJohn Marino 		   prog, sig, strsignal (sig));
225e4b17023SJohn Marino 	  else
226e4b17023SJohn Marino 	    fatal ("%s terminated with signal %d [%s]",
227e4b17023SJohn Marino 		   prog, sig, strsignal (sig));
228e4b17023SJohn Marino 	}
229e4b17023SJohn Marino 
230e4b17023SJohn Marino       if (WIFEXITED (status))
231e4b17023SJohn Marino 	fatal ("%s returned %d exit status", prog, WEXITSTATUS (status));
232e4b17023SJohn Marino     }
233e4b17023SJohn Marino 
234e4b17023SJohn Marino   return 0;
235e4b17023SJohn Marino }
236e4b17023SJohn Marino 
237e4b17023SJohn Marino 
238e4b17023SJohn Marino /* Unlink a temporary LTRANS file unless requested otherwise.  */
239e4b17023SJohn Marino 
240e4b17023SJohn Marino static void
maybe_unlink_file(const char * file)241e4b17023SJohn Marino maybe_unlink_file (const char *file)
242e4b17023SJohn Marino {
243e4b17023SJohn Marino   if (! debug)
244e4b17023SJohn Marino     {
245e4b17023SJohn Marino       if (unlink_if_ordinary (file)
246e4b17023SJohn Marino 	  && errno != ENOENT)
247e4b17023SJohn Marino 	fatal_perror ("deleting LTRANS file %s", file);
248e4b17023SJohn Marino     }
249e4b17023SJohn Marino   else
250e4b17023SJohn Marino     fprintf (stderr, "[Leaving LTRANS %s]\n", file);
251e4b17023SJohn Marino }
252e4b17023SJohn Marino 
253e4b17023SJohn Marino 
254e4b17023SJohn Marino /* Execute program ARGV[0] with arguments ARGV. Wait for it to finish.  */
255e4b17023SJohn Marino 
256e4b17023SJohn Marino static void
fork_execute(char ** argv)257e4b17023SJohn Marino fork_execute (char **argv)
258e4b17023SJohn Marino {
259e4b17023SJohn Marino   struct pex_obj *pex;
260e4b17023SJohn Marino   char *new_argv[3];
261e4b17023SJohn Marino   char *at_args;
262e4b17023SJohn Marino   FILE *args;
263e4b17023SJohn Marino   int status;
264e4b17023SJohn Marino 
265e4b17023SJohn Marino   args_name = make_temp_file (".args");
266e4b17023SJohn Marino   at_args = concat ("@", args_name, NULL);
267e4b17023SJohn Marino   args = fopen (args_name, "w");
268e4b17023SJohn Marino   if (args == NULL)
269e4b17023SJohn Marino     fatal ("failed to open %s", args_name);
270e4b17023SJohn Marino 
271e4b17023SJohn Marino   status = writeargv (&argv[1], args);
272e4b17023SJohn Marino 
273e4b17023SJohn Marino   if (status)
274e4b17023SJohn Marino     fatal ("could not write to temporary file %s",  args_name);
275e4b17023SJohn Marino 
276e4b17023SJohn Marino   fclose (args);
277e4b17023SJohn Marino 
278e4b17023SJohn Marino   new_argv[0] = argv[0];
279e4b17023SJohn Marino   new_argv[1] = at_args;
280e4b17023SJohn Marino   new_argv[2] = NULL;
281e4b17023SJohn Marino 
282e4b17023SJohn Marino   pex = collect_execute (new_argv);
283e4b17023SJohn Marino   collect_wait (new_argv[0], pex);
284e4b17023SJohn Marino 
285e4b17023SJohn Marino   maybe_unlink_file (args_name);
286e4b17023SJohn Marino   args_name = NULL;
287e4b17023SJohn Marino   free (at_args);
288e4b17023SJohn Marino }
289e4b17023SJohn Marino 
290e4b17023SJohn Marino /* Template of LTRANS dumpbase suffix.  */
291e4b17023SJohn Marino #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
292e4b17023SJohn Marino 
293e4b17023SJohn Marino /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
294e4b17023SJohn Marino    environment according to LANG_MASK.  */
295e4b17023SJohn Marino 
296e4b17023SJohn Marino static void
get_options_from_collect_gcc_options(const char * collect_gcc,const char * collect_gcc_options,unsigned int lang_mask,struct cl_decoded_option ** decoded_options,unsigned int * decoded_options_count)297e4b17023SJohn Marino get_options_from_collect_gcc_options (const char *collect_gcc,
298e4b17023SJohn Marino 				      const char *collect_gcc_options,
299e4b17023SJohn Marino 				      unsigned int lang_mask,
300e4b17023SJohn Marino 				      struct cl_decoded_option **decoded_options,
301e4b17023SJohn Marino 				      unsigned int *decoded_options_count)
302e4b17023SJohn Marino {
303e4b17023SJohn Marino   struct obstack argv_obstack;
304e4b17023SJohn Marino   char *argv_storage;
305e4b17023SJohn Marino   const char **argv;
306e4b17023SJohn Marino   int j, k, argc;
307e4b17023SJohn Marino 
308e4b17023SJohn Marino   argv_storage = xstrdup (collect_gcc_options);
309e4b17023SJohn Marino   obstack_init (&argv_obstack);
310e4b17023SJohn Marino   obstack_ptr_grow (&argv_obstack, collect_gcc);
311e4b17023SJohn Marino 
312e4b17023SJohn Marino   for (j = 0, k = 0; argv_storage[j] != '\0'; ++j)
313e4b17023SJohn Marino     {
314e4b17023SJohn Marino       if (argv_storage[j] == '\'')
315e4b17023SJohn Marino 	{
316e4b17023SJohn Marino 	  obstack_ptr_grow (&argv_obstack, &argv_storage[k]);
317e4b17023SJohn Marino 	  ++j;
318e4b17023SJohn Marino 	  do
319e4b17023SJohn Marino 	    {
320e4b17023SJohn Marino 	      if (argv_storage[j] == '\0')
321e4b17023SJohn Marino 		fatal ("malformed COLLECT_GCC_OPTIONS");
322e4b17023SJohn Marino 	      else if (strncmp (&argv_storage[j], "'\\''", 4) == 0)
323e4b17023SJohn Marino 		{
324e4b17023SJohn Marino 		  argv_storage[k++] = '\'';
325e4b17023SJohn Marino 		  j += 4;
326e4b17023SJohn Marino 		}
327e4b17023SJohn Marino 	      else if (argv_storage[j] == '\'')
328e4b17023SJohn Marino 		break;
329e4b17023SJohn Marino 	      else
330e4b17023SJohn Marino 		argv_storage[k++] = argv_storage[j++];
331e4b17023SJohn Marino 	    }
332e4b17023SJohn Marino 	  while (1);
333e4b17023SJohn Marino 	  argv_storage[k++] = '\0';
334e4b17023SJohn Marino 	}
335e4b17023SJohn Marino     }
336e4b17023SJohn Marino 
337e4b17023SJohn Marino   obstack_ptr_grow (&argv_obstack, NULL);
338e4b17023SJohn Marino   argc = obstack_object_size (&argv_obstack) / sizeof (void *) - 1;
339e4b17023SJohn Marino   argv = XOBFINISH (&argv_obstack, const char **);
340e4b17023SJohn Marino 
341e4b17023SJohn Marino   decode_cmdline_options_to_array (argc, (const char **)argv,
342e4b17023SJohn Marino 				   lang_mask,
343e4b17023SJohn Marino 				   decoded_options, decoded_options_count);
344e4b17023SJohn Marino   obstack_free (&argv_obstack, NULL);
345e4b17023SJohn Marino }
346e4b17023SJohn Marino 
347e4b17023SJohn Marino /* Append OPTION to the options array DECODED_OPTIONS with size
348e4b17023SJohn Marino    DECODED_OPTIONS_COUNT.  */
349e4b17023SJohn Marino 
350e4b17023SJohn Marino static void
append_option(struct cl_decoded_option ** decoded_options,unsigned int * decoded_options_count,struct cl_decoded_option * option)351e4b17023SJohn Marino append_option (struct cl_decoded_option **decoded_options,
352e4b17023SJohn Marino 	       unsigned int *decoded_options_count,
353e4b17023SJohn Marino 	       struct cl_decoded_option *option)
354e4b17023SJohn Marino {
355e4b17023SJohn Marino   ++*decoded_options_count;
356e4b17023SJohn Marino   *decoded_options
357e4b17023SJohn Marino     = (struct cl_decoded_option *)
358e4b17023SJohn Marino 	xrealloc (*decoded_options,
359e4b17023SJohn Marino 		  (*decoded_options_count
360e4b17023SJohn Marino 		   * sizeof (struct cl_decoded_option)));
361e4b17023SJohn Marino   memcpy (&(*decoded_options)[*decoded_options_count - 1], option,
362e4b17023SJohn Marino 	  sizeof (struct cl_decoded_option));
363e4b17023SJohn Marino }
364e4b17023SJohn Marino 
365e4b17023SJohn Marino /* Try to merge and complain about options FDECODED_OPTIONS when applied
366e4b17023SJohn Marino    ontop of DECODED_OPTIONS.  */
367e4b17023SJohn Marino 
368e4b17023SJohn Marino static void
merge_and_complain(struct cl_decoded_option ** decoded_options,unsigned int * decoded_options_count,struct cl_decoded_option * fdecoded_options,unsigned int fdecoded_options_count)369e4b17023SJohn Marino merge_and_complain (struct cl_decoded_option **decoded_options,
370e4b17023SJohn Marino 		    unsigned int *decoded_options_count,
371e4b17023SJohn Marino 		    struct cl_decoded_option *fdecoded_options,
372e4b17023SJohn Marino 		    unsigned int fdecoded_options_count)
373e4b17023SJohn Marino {
374e4b17023SJohn Marino   unsigned int i, j;
375e4b17023SJohn Marino 
376e4b17023SJohn Marino   /* ???  Merge options from files.  Most cases can be
377e4b17023SJohn Marino      handled by either unioning or intersecting
378e4b17023SJohn Marino      (for example -fwrapv is a case for unioning,
379e4b17023SJohn Marino      -ffast-math is for intersection).  Most complaints
380e4b17023SJohn Marino      about real conflicts between different options can
381e4b17023SJohn Marino      be deferred to the compiler proper.  Options that
382e4b17023SJohn Marino      we can neither safely handle by intersection nor
383e4b17023SJohn Marino      unioning would need to be complained about here.
384e4b17023SJohn Marino      Ideally we'd have a flag in the opt files that
385e4b17023SJohn Marino      tells whether to union or intersect or reject.
386e4b17023SJohn Marino      In absence of that it's unclear what a good default is.
387e4b17023SJohn Marino      It's also difficult to get positional handling correct.  */
388e4b17023SJohn Marino 
389e4b17023SJohn Marino   /* The following does what the old LTO option code did,
390e4b17023SJohn Marino      union all target and a selected set of common options.  */
391e4b17023SJohn Marino   for (i = 0; i < fdecoded_options_count; ++i)
392e4b17023SJohn Marino     {
393e4b17023SJohn Marino       struct cl_decoded_option *foption = &fdecoded_options[i];
394e4b17023SJohn Marino       switch (foption->opt_index)
395e4b17023SJohn Marino 	{
396*5ce9237cSJohn Marino 	case OPT_SPECIAL_unknown:
397*5ce9237cSJohn Marino 	case OPT_SPECIAL_ignore:
398*5ce9237cSJohn Marino 	case OPT_SPECIAL_program_name:
399*5ce9237cSJohn Marino 	case OPT_SPECIAL_input_file:
400*5ce9237cSJohn Marino 	  break;
401*5ce9237cSJohn Marino 
402e4b17023SJohn Marino 	default:
403e4b17023SJohn Marino 	  if (!(cl_options[foption->opt_index].flags & CL_TARGET))
404e4b17023SJohn Marino 	    break;
405e4b17023SJohn Marino 
406e4b17023SJohn Marino 	  /* Fallthru.  */
407e4b17023SJohn Marino 	case OPT_fPIC:
408e4b17023SJohn Marino 	case OPT_fpic:
409e4b17023SJohn Marino 	case OPT_fpie:
410e4b17023SJohn Marino 	case OPT_fcommon:
411e4b17023SJohn Marino 	case OPT_fexceptions:
412e4b17023SJohn Marino 	case OPT_fgnu_tm:
413e4b17023SJohn Marino 	  /* Do what the old LTO code did - collect exactly one option
414e4b17023SJohn Marino 	     setting per OPT code, we pick the first we encounter.
415e4b17023SJohn Marino 	     ???  This doesn't make too much sense, but when it doesn't
416e4b17023SJohn Marino 	     then we should complain.  */
417e4b17023SJohn Marino 	  for (j = 0; j < *decoded_options_count; ++j)
418e4b17023SJohn Marino 	    if ((*decoded_options)[j].opt_index == foption->opt_index)
419e4b17023SJohn Marino 	      break;
420e4b17023SJohn Marino 	  if (j == *decoded_options_count)
421e4b17023SJohn Marino 	    append_option (decoded_options, decoded_options_count, foption);
422e4b17023SJohn Marino 	  break;
423e4b17023SJohn Marino 	}
424e4b17023SJohn Marino     }
425e4b17023SJohn Marino }
426e4b17023SJohn Marino 
427e4b17023SJohn Marino /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
428e4b17023SJohn Marino 
429e4b17023SJohn Marino static void
run_gcc(unsigned argc,char * argv[])430e4b17023SJohn Marino run_gcc (unsigned argc, char *argv[])
431e4b17023SJohn Marino {
432e4b17023SJohn Marino   unsigned i, j;
433e4b17023SJohn Marino   const char **new_argv;
434e4b17023SJohn Marino   const char **argv_ptr;
435e4b17023SJohn Marino   char *list_option_full = NULL;
436e4b17023SJohn Marino   const char *linker_output = NULL;
437e4b17023SJohn Marino   const char *collect_gcc, *collect_gcc_options;
438e4b17023SJohn Marino   int parallel = 0;
439e4b17023SJohn Marino   int jobserver = 0;
440e4b17023SJohn Marino   bool no_partition = false;
441e4b17023SJohn Marino   struct cl_decoded_option *fdecoded_options = NULL;
442e4b17023SJohn Marino   unsigned int fdecoded_options_count = 0;
443e4b17023SJohn Marino   struct cl_decoded_option *decoded_options;
444e4b17023SJohn Marino   unsigned int decoded_options_count;
445e4b17023SJohn Marino   struct obstack argv_obstack;
446e4b17023SJohn Marino   int new_head_argc;
447e4b17023SJohn Marino 
448e4b17023SJohn Marino   /* Get the driver and options.  */
449e4b17023SJohn Marino   collect_gcc = getenv ("COLLECT_GCC");
450e4b17023SJohn Marino   if (!collect_gcc)
451e4b17023SJohn Marino     fatal ("environment variable COLLECT_GCC must be set");
452e4b17023SJohn Marino   collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
453e4b17023SJohn Marino   if (!collect_gcc_options)
454e4b17023SJohn Marino     fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
455e4b17023SJohn Marino   get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
456e4b17023SJohn Marino 					CL_LANG_ALL,
457e4b17023SJohn Marino 					&decoded_options,
458e4b17023SJohn Marino 					&decoded_options_count);
459e4b17023SJohn Marino 
460e4b17023SJohn Marino   /* Look at saved options in the IL files.  */
461e4b17023SJohn Marino   for (i = 1; i < argc; ++i)
462e4b17023SJohn Marino     {
463e4b17023SJohn Marino       char *data, *p;
464e4b17023SJohn Marino       char *fopts;
465e4b17023SJohn Marino       int fd;
466e4b17023SJohn Marino       const char *errmsg;
467e4b17023SJohn Marino       int err;
468e4b17023SJohn Marino       off_t file_offset = 0, offset, length;
469e4b17023SJohn Marino       long loffset;
470e4b17023SJohn Marino       simple_object_read *sobj;
471e4b17023SJohn Marino       int consumed;
472e4b17023SJohn Marino       struct cl_decoded_option *f2decoded_options;
473e4b17023SJohn Marino       unsigned int f2decoded_options_count;
474e4b17023SJohn Marino       char *filename = argv[i];
475e4b17023SJohn Marino       if ((p = strrchr (argv[i], '@'))
476e4b17023SJohn Marino 	  && p != argv[i]
477e4b17023SJohn Marino 	  && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
478e4b17023SJohn Marino 	  && strlen (p) == (unsigned int) consumed)
479e4b17023SJohn Marino 	{
480e4b17023SJohn Marino 	  filename = XNEWVEC (char, p - argv[i] + 1);
481e4b17023SJohn Marino 	  memcpy (filename, argv[i], p - argv[i]);
482e4b17023SJohn Marino 	  filename[p - argv[i]] = '\0';
483e4b17023SJohn Marino 	  file_offset = (off_t) loffset;
484e4b17023SJohn Marino 	}
485e4b17023SJohn Marino       fd = open (argv[i], O_RDONLY);
486e4b17023SJohn Marino       if (fd == -1)
487e4b17023SJohn Marino 	continue;
488e4b17023SJohn Marino       sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO",
489e4b17023SJohn Marino 	  			       &errmsg, &err);
490e4b17023SJohn Marino       if (!sobj)
491e4b17023SJohn Marino 	{
492e4b17023SJohn Marino 	  close (fd);
493e4b17023SJohn Marino 	  continue;
494e4b17023SJohn Marino 	}
495e4b17023SJohn Marino       if (!simple_object_find_section (sobj, LTO_SECTION_NAME_PREFIX "." "opts",
496e4b17023SJohn Marino 				       &offset, &length, &errmsg, &err))
497e4b17023SJohn Marino 	{
498e4b17023SJohn Marino 	  simple_object_release_read (sobj);
499e4b17023SJohn Marino 	  close (fd);
500e4b17023SJohn Marino 	  continue;
501e4b17023SJohn Marino 	}
502e4b17023SJohn Marino       lseek (fd, file_offset + offset, SEEK_SET);
503e4b17023SJohn Marino       data = (char *)xmalloc (length);
504e4b17023SJohn Marino       read (fd, data, length);
505e4b17023SJohn Marino       fopts = data;
506e4b17023SJohn Marino       do
507e4b17023SJohn Marino 	{
508e4b17023SJohn Marino 	  get_options_from_collect_gcc_options (collect_gcc,
509e4b17023SJohn Marino 						fopts, CL_LANG_ALL,
510e4b17023SJohn Marino 						&f2decoded_options,
511e4b17023SJohn Marino 						&f2decoded_options_count);
512e4b17023SJohn Marino 	  if (!fdecoded_options)
513e4b17023SJohn Marino 	    {
514e4b17023SJohn Marino 	      fdecoded_options = f2decoded_options;
515e4b17023SJohn Marino 	      fdecoded_options_count = f2decoded_options_count;
516e4b17023SJohn Marino 	    }
517e4b17023SJohn Marino 	  else
518e4b17023SJohn Marino 	    merge_and_complain (&fdecoded_options,
519e4b17023SJohn Marino 				&fdecoded_options_count,
520e4b17023SJohn Marino 				f2decoded_options, f2decoded_options_count);
521e4b17023SJohn Marino 
522e4b17023SJohn Marino 	  fopts += strlen (fopts) + 1;
523e4b17023SJohn Marino 	}
524e4b17023SJohn Marino       while (fopts - data < length);
525e4b17023SJohn Marino 
526e4b17023SJohn Marino       free (data);
527e4b17023SJohn Marino       simple_object_release_read (sobj);
528e4b17023SJohn Marino       close (fd);
529e4b17023SJohn Marino     }
530e4b17023SJohn Marino 
531e4b17023SJohn Marino   /* Initalize the common arguments for the driver.  */
532e4b17023SJohn Marino   obstack_init (&argv_obstack);
533e4b17023SJohn Marino   obstack_ptr_grow (&argv_obstack, collect_gcc);
534e4b17023SJohn Marino   obstack_ptr_grow (&argv_obstack, "-xlto");
535e4b17023SJohn Marino   obstack_ptr_grow (&argv_obstack, "-c");
536e4b17023SJohn Marino 
537e4b17023SJohn Marino   /* Append compiler driver arguments as far as they were merged.  */
538e4b17023SJohn Marino   for (j = 1; j < fdecoded_options_count; ++j)
539e4b17023SJohn Marino     {
540e4b17023SJohn Marino       struct cl_decoded_option *option = &fdecoded_options[j];
541e4b17023SJohn Marino 
542e4b17023SJohn Marino       /* File options have been properly filtered by lto-opts.c.  */
543e4b17023SJohn Marino       switch (option->opt_index)
544e4b17023SJohn Marino 	{
545e4b17023SJohn Marino 	  /* Drop arguments that we want to take from the link line.  */
546e4b17023SJohn Marino 	  case OPT_flto_:
547e4b17023SJohn Marino 	  case OPT_flto:
548e4b17023SJohn Marino 	  case OPT_flto_partition_none:
549e4b17023SJohn Marino 	  case OPT_flto_partition_1to1:
550e4b17023SJohn Marino 	  case OPT_flto_partition_balanced:
551e4b17023SJohn Marino 	      continue;
552e4b17023SJohn Marino 
553e4b17023SJohn Marino 	  default:
554e4b17023SJohn Marino 	      break;
555e4b17023SJohn Marino 	}
556e4b17023SJohn Marino 
557e4b17023SJohn Marino       /* For now do what the original LTO option code was doing - pass
558e4b17023SJohn Marino 	 on any CL_TARGET flag and a few selected others.  */
559e4b17023SJohn Marino       switch (option->opt_index)
560e4b17023SJohn Marino 	{
561e4b17023SJohn Marino 	case OPT_fPIC:
562e4b17023SJohn Marino 	case OPT_fpic:
563e4b17023SJohn Marino 	case OPT_fpie:
564e4b17023SJohn Marino 	case OPT_fcommon:
565e4b17023SJohn Marino 	case OPT_fexceptions:
566e4b17023SJohn Marino 	case OPT_fgnu_tm:
567e4b17023SJohn Marino 	  break;
568e4b17023SJohn Marino 
569e4b17023SJohn Marino 	default:
570e4b17023SJohn Marino 	  if (!(cl_options[option->opt_index].flags & CL_TARGET))
571e4b17023SJohn Marino 	    continue;
572e4b17023SJohn Marino 	}
573e4b17023SJohn Marino 
574e4b17023SJohn Marino       /* Pass the option on.  */
575e4b17023SJohn Marino       for (i = 0; i < option->canonical_option_num_elements; ++i)
576e4b17023SJohn Marino 	obstack_ptr_grow (&argv_obstack, option->canonical_option[i]);
577e4b17023SJohn Marino     }
578e4b17023SJohn Marino 
579e4b17023SJohn Marino   /* Append linker driver arguments.  Compiler options from the linker
580e4b17023SJohn Marino      driver arguments will override / merge with those from the compiler.  */
581e4b17023SJohn Marino   for (j = 1; j < decoded_options_count; ++j)
582e4b17023SJohn Marino     {
583e4b17023SJohn Marino       struct cl_decoded_option *option = &decoded_options[j];
584e4b17023SJohn Marino 
585e4b17023SJohn Marino       /* Do not pass on frontend specific flags not suitable for lto.  */
586e4b17023SJohn Marino       if (!(cl_options[option->opt_index].flags
587e4b17023SJohn Marino 	    & (CL_COMMON|CL_TARGET|CL_DRIVER|CL_LTO)))
588e4b17023SJohn Marino 	continue;
589e4b17023SJohn Marino 
590e4b17023SJohn Marino       switch (option->opt_index)
591e4b17023SJohn Marino 	{
592e4b17023SJohn Marino 	case OPT_o:
593e4b17023SJohn Marino 	  linker_output = option->arg;
594e4b17023SJohn Marino 	  /* We generate new intermediate output, drop this arg.  */
595e4b17023SJohn Marino 	  continue;
596e4b17023SJohn Marino 
597e4b17023SJohn Marino 	case OPT_save_temps:
598e4b17023SJohn Marino 	  debug = 1;
599e4b17023SJohn Marino 	  break;
600e4b17023SJohn Marino 
601e4b17023SJohn Marino 	case OPT_v:
602e4b17023SJohn Marino 	  verbose = 1;
603e4b17023SJohn Marino 	  break;
604e4b17023SJohn Marino 
605e4b17023SJohn Marino 	case OPT_flto_partition_none:
606e4b17023SJohn Marino 	  no_partition = true;
607e4b17023SJohn Marino 	  break;
608e4b17023SJohn Marino 
609e4b17023SJohn Marino 	case OPT_flto_:
610e4b17023SJohn Marino 	  if (strcmp (option->arg, "jobserver") == 0)
611e4b17023SJohn Marino 	    {
612e4b17023SJohn Marino 	      jobserver = 1;
613e4b17023SJohn Marino 	      parallel = 1;
614e4b17023SJohn Marino 	    }
615e4b17023SJohn Marino 	  else
616e4b17023SJohn Marino 	    {
617e4b17023SJohn Marino 	      parallel = atoi (option->arg);
618e4b17023SJohn Marino 	      if (parallel <= 1)
619e4b17023SJohn Marino 		parallel = 0;
620e4b17023SJohn Marino 	    }
621e4b17023SJohn Marino 	  /* Fallthru.  */
622e4b17023SJohn Marino 
623e4b17023SJohn Marino 	case OPT_flto:
624e4b17023SJohn Marino 	  lto_mode = LTO_MODE_WHOPR;
625e4b17023SJohn Marino 	  /* We've handled these LTO options, do not pass them on.  */
626e4b17023SJohn Marino 	  continue;
627e4b17023SJohn Marino 
628e4b17023SJohn Marino 	default:
629e4b17023SJohn Marino 	  break;
630e4b17023SJohn Marino 	}
631e4b17023SJohn Marino 
632e4b17023SJohn Marino       /* Pass the option on.  */
633e4b17023SJohn Marino       for (i = 0; i < option->canonical_option_num_elements; ++i)
634e4b17023SJohn Marino 	obstack_ptr_grow (&argv_obstack, option->canonical_option[i]);
635e4b17023SJohn Marino     }
636e4b17023SJohn Marino 
637e4b17023SJohn Marino   if (no_partition)
638e4b17023SJohn Marino     {
639e4b17023SJohn Marino       lto_mode = LTO_MODE_LTO;
640e4b17023SJohn Marino       jobserver = 0;
641e4b17023SJohn Marino       parallel = 0;
642e4b17023SJohn Marino     }
643e4b17023SJohn Marino 
644e4b17023SJohn Marino   if (linker_output)
645e4b17023SJohn Marino     {
646e4b17023SJohn Marino       char *output_dir, *base, *name;
647e4b17023SJohn Marino       bool bit_bucket = strcmp (linker_output, HOST_BIT_BUCKET) == 0;
648e4b17023SJohn Marino 
649e4b17023SJohn Marino       output_dir = xstrdup (linker_output);
650e4b17023SJohn Marino       base = output_dir;
651e4b17023SJohn Marino       for (name = base; *name; name++)
652e4b17023SJohn Marino 	if (IS_DIR_SEPARATOR (*name))
653e4b17023SJohn Marino 	  base = name + 1;
654e4b17023SJohn Marino       *base = '\0';
655e4b17023SJohn Marino 
656e4b17023SJohn Marino       linker_output = &linker_output[base - output_dir];
657e4b17023SJohn Marino       if (*output_dir == '\0')
658e4b17023SJohn Marino 	{
659e4b17023SJohn Marino 	  static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
660e4b17023SJohn Marino 	  output_dir = current_dir;
661e4b17023SJohn Marino 	}
662e4b17023SJohn Marino       if (!bit_bucket)
663e4b17023SJohn Marino 	{
664e4b17023SJohn Marino 	  obstack_ptr_grow (&argv_obstack, "-dumpdir");
665e4b17023SJohn Marino 	  obstack_ptr_grow (&argv_obstack, output_dir);
666e4b17023SJohn Marino 	}
667e4b17023SJohn Marino 
668e4b17023SJohn Marino       obstack_ptr_grow (&argv_obstack, "-dumpbase");
669e4b17023SJohn Marino     }
670e4b17023SJohn Marino 
671e4b17023SJohn Marino   /* Remember at which point we can scrub args to re-use the commons.  */
672e4b17023SJohn Marino   new_head_argc = obstack_object_size (&argv_obstack) / sizeof (void *);
673e4b17023SJohn Marino 
674e4b17023SJohn Marino   if (lto_mode == LTO_MODE_LTO)
675e4b17023SJohn Marino     {
676e4b17023SJohn Marino       flto_out = make_temp_file (".lto.o");
677e4b17023SJohn Marino       if (linker_output)
678e4b17023SJohn Marino 	obstack_ptr_grow (&argv_obstack, linker_output);
679e4b17023SJohn Marino       obstack_ptr_grow (&argv_obstack, "-o");
680e4b17023SJohn Marino       obstack_ptr_grow (&argv_obstack, flto_out);
681e4b17023SJohn Marino     }
682e4b17023SJohn Marino   else
683e4b17023SJohn Marino     {
684e4b17023SJohn Marino       const char *list_option = "-fltrans-output-list=";
685e4b17023SJohn Marino       size_t list_option_len = strlen (list_option);
686e4b17023SJohn Marino       char *tmp;
687e4b17023SJohn Marino 
688e4b17023SJohn Marino       if (linker_output)
689e4b17023SJohn Marino 	{
690e4b17023SJohn Marino 	  char *dumpbase = (char *) xmalloc (strlen (linker_output)
691e4b17023SJohn Marino 					     + sizeof (".wpa") + 1);
692e4b17023SJohn Marino 	  strcpy (dumpbase, linker_output);
693e4b17023SJohn Marino 	  strcat (dumpbase, ".wpa");
694e4b17023SJohn Marino 	  obstack_ptr_grow (&argv_obstack, dumpbase);
695e4b17023SJohn Marino 	}
696e4b17023SJohn Marino 
697e4b17023SJohn Marino       if (linker_output && debug)
698e4b17023SJohn Marino 	{
699e4b17023SJohn Marino 	  ltrans_output_file = (char *) xmalloc (strlen (linker_output)
700e4b17023SJohn Marino 						 + sizeof (".ltrans.out") + 1);
701e4b17023SJohn Marino 	  strcpy (ltrans_output_file, linker_output);
702e4b17023SJohn Marino 	  strcat (ltrans_output_file, ".ltrans.out");
703e4b17023SJohn Marino 	}
704e4b17023SJohn Marino       else
705e4b17023SJohn Marino 	ltrans_output_file = make_temp_file (".ltrans.out");
706e4b17023SJohn Marino       list_option_full = (char *) xmalloc (sizeof (char) *
707e4b17023SJohn Marino 		         (strlen (ltrans_output_file) + list_option_len + 1));
708e4b17023SJohn Marino       tmp = list_option_full;
709e4b17023SJohn Marino 
710e4b17023SJohn Marino       obstack_ptr_grow (&argv_obstack, tmp);
711e4b17023SJohn Marino       strcpy (tmp, list_option);
712e4b17023SJohn Marino       tmp += list_option_len;
713e4b17023SJohn Marino       strcpy (tmp, ltrans_output_file);
714e4b17023SJohn Marino 
715e4b17023SJohn Marino       obstack_ptr_grow (&argv_obstack, "-fwpa");
716e4b17023SJohn Marino     }
717e4b17023SJohn Marino 
718e4b17023SJohn Marino   /* Append the input objects and possible preceeding arguments.  */
719e4b17023SJohn Marino   for (i = 1; i < argc; ++i)
720e4b17023SJohn Marino     obstack_ptr_grow (&argv_obstack, argv[i]);
721e4b17023SJohn Marino   obstack_ptr_grow (&argv_obstack, NULL);
722e4b17023SJohn Marino 
723e4b17023SJohn Marino   new_argv = XOBFINISH (&argv_obstack, const char **);
724e4b17023SJohn Marino   argv_ptr = &new_argv[new_head_argc];
725e4b17023SJohn Marino   fork_execute (CONST_CAST (char **, new_argv));
726e4b17023SJohn Marino 
727e4b17023SJohn Marino   if (lto_mode == LTO_MODE_LTO)
728e4b17023SJohn Marino     {
729e4b17023SJohn Marino       printf("%s\n", flto_out);
730e4b17023SJohn Marino       free (flto_out);
731e4b17023SJohn Marino       flto_out = NULL;
732e4b17023SJohn Marino     }
733e4b17023SJohn Marino   else
734e4b17023SJohn Marino     {
735e4b17023SJohn Marino       FILE *stream = fopen (ltrans_output_file, "r");
736e4b17023SJohn Marino       FILE *mstream = NULL;
737e4b17023SJohn Marino       struct obstack env_obstack;
738e4b17023SJohn Marino 
739e4b17023SJohn Marino       if (!stream)
740e4b17023SJohn Marino 	fatal_perror ("fopen: %s", ltrans_output_file);
741e4b17023SJohn Marino 
742e4b17023SJohn Marino       /* Parse the list of LTRANS inputs from the WPA stage.  */
743e4b17023SJohn Marino       obstack_init (&env_obstack);
744e4b17023SJohn Marino       nr = 0;
745e4b17023SJohn Marino       for (;;)
746e4b17023SJohn Marino 	{
747e4b17023SJohn Marino 	  const unsigned piece = 32;
748e4b17023SJohn Marino 	  char *output_name = NULL;
749e4b17023SJohn Marino 	  char *buf, *input_name = (char *)xmalloc (piece);
750e4b17023SJohn Marino 	  size_t len;
751e4b17023SJohn Marino 
752e4b17023SJohn Marino 	  buf = input_name;
753e4b17023SJohn Marino cont:
754e4b17023SJohn Marino 	  if (!fgets (buf, piece, stream))
755e4b17023SJohn Marino 	    break;
756e4b17023SJohn Marino 	  len = strlen (input_name);
757e4b17023SJohn Marino 	  if (input_name[len - 1] != '\n')
758e4b17023SJohn Marino 	    {
759e4b17023SJohn Marino 	      input_name = (char *)xrealloc (input_name, len + piece);
760e4b17023SJohn Marino 	      buf = input_name + len;
761e4b17023SJohn Marino 	      goto cont;
762e4b17023SJohn Marino 	    }
763e4b17023SJohn Marino 	  input_name[len - 1] = '\0';
764e4b17023SJohn Marino 
765e4b17023SJohn Marino 	  if (input_name[0] == '*')
766e4b17023SJohn Marino 	    output_name = &input_name[1];
767e4b17023SJohn Marino 
768e4b17023SJohn Marino 	  nr++;
769e4b17023SJohn Marino 	  input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
770e4b17023SJohn Marino 	  output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
771e4b17023SJohn Marino 	  input_names[nr-1] = input_name;
772e4b17023SJohn Marino 	  output_names[nr-1] = output_name;
773e4b17023SJohn Marino 	}
774e4b17023SJohn Marino       fclose (stream);
775e4b17023SJohn Marino       maybe_unlink_file (ltrans_output_file);
776e4b17023SJohn Marino       ltrans_output_file = NULL;
777e4b17023SJohn Marino 
778e4b17023SJohn Marino       if (parallel)
779e4b17023SJohn Marino 	{
780e4b17023SJohn Marino 	  makefile = make_temp_file (".mk");
781e4b17023SJohn Marino 	  mstream = fopen (makefile, "w");
782e4b17023SJohn Marino 	}
783e4b17023SJohn Marino 
784e4b17023SJohn Marino       /* Execute the LTRANS stage for each input file (or prepare a
785e4b17023SJohn Marino 	 makefile to invoke this in parallel).  */
786e4b17023SJohn Marino       for (i = 0; i < nr; ++i)
787e4b17023SJohn Marino 	{
788e4b17023SJohn Marino 	  char *output_name;
789e4b17023SJohn Marino 	  char *input_name = input_names[i];
790e4b17023SJohn Marino 	  /* If it's a pass-through file do nothing.  */
791e4b17023SJohn Marino 	  if (output_names[i])
792e4b17023SJohn Marino 	    continue;
793e4b17023SJohn Marino 
794e4b17023SJohn Marino 	  /* Replace the .o suffix with a .ltrans.o suffix and write
795e4b17023SJohn Marino 	     the resulting name to the LTRANS output list.  */
796e4b17023SJohn Marino 	  obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
797e4b17023SJohn Marino 	  obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
798e4b17023SJohn Marino 	  output_name = XOBFINISH (&env_obstack, char *);
799e4b17023SJohn Marino 
800e4b17023SJohn Marino 	  /* Adjust the dumpbase if the linker output file was seen.  */
801e4b17023SJohn Marino 	  if (linker_output)
802e4b17023SJohn Marino 	    {
803e4b17023SJohn Marino 	      char *dumpbase
804e4b17023SJohn Marino 		  = (char *) xmalloc (strlen (linker_output)
805e4b17023SJohn Marino 				      + sizeof(DUMPBASE_SUFFIX) + 1);
806e4b17023SJohn Marino 	      snprintf (dumpbase,
807e4b17023SJohn Marino 			strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
808e4b17023SJohn Marino 			"%s.ltrans%u", linker_output, i);
809e4b17023SJohn Marino 	      argv_ptr[0] = dumpbase;
810e4b17023SJohn Marino 	    }
811e4b17023SJohn Marino 
812e4b17023SJohn Marino 	  argv_ptr[1] = "-fltrans";
813e4b17023SJohn Marino 	  argv_ptr[2] = "-o";
814e4b17023SJohn Marino 	  argv_ptr[3] = output_name;
815e4b17023SJohn Marino 	  argv_ptr[4] = input_name;
816e4b17023SJohn Marino 	  argv_ptr[5] = NULL;
817e4b17023SJohn Marino 	  if (parallel)
818e4b17023SJohn Marino 	    {
819e4b17023SJohn Marino 	      fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
820e4b17023SJohn Marino 	      for (j = 1; new_argv[j] != NULL; ++j)
821e4b17023SJohn Marino 		fprintf (mstream, " '%s'", new_argv[j]);
822e4b17023SJohn Marino 	      fprintf (mstream, "\n");
823e4b17023SJohn Marino 	      /* If we are not preserving the ltrans input files then
824e4b17023SJohn Marino 	         truncate them as soon as we have processed it.  This
825e4b17023SJohn Marino 		 reduces temporary disk-space usage.  */
826e4b17023SJohn Marino 	      if (! debug)
827e4b17023SJohn Marino 		fprintf (mstream, "\t@-touch -r %s %s.tem > /dev/null 2>&1 "
828e4b17023SJohn Marino 			 "&& mv %s.tem %s\n",
829e4b17023SJohn Marino 			 input_name, input_name, input_name, input_name);
830e4b17023SJohn Marino 	    }
831e4b17023SJohn Marino 	  else
832e4b17023SJohn Marino 	    {
833e4b17023SJohn Marino 	      fork_execute (CONST_CAST (char **, new_argv));
834e4b17023SJohn Marino 	      maybe_unlink_file (input_name);
835e4b17023SJohn Marino 	    }
836e4b17023SJohn Marino 
837e4b17023SJohn Marino 	  output_names[i] = output_name;
838e4b17023SJohn Marino 	}
839e4b17023SJohn Marino       if (parallel)
840e4b17023SJohn Marino 	{
841e4b17023SJohn Marino 	  struct pex_obj *pex;
842e4b17023SJohn Marino 	  char jobs[32];
843e4b17023SJohn Marino 
844e4b17023SJohn Marino 	  fprintf (mstream, "all:");
845e4b17023SJohn Marino 	  for (i = 0; i < nr; ++i)
846e4b17023SJohn Marino 	    fprintf (mstream, " \\\n\t%s", output_names[i]);
847e4b17023SJohn Marino 	  fprintf (mstream, "\n");
848e4b17023SJohn Marino 	  fclose (mstream);
849e4b17023SJohn Marino 	  if (!jobserver)
850e4b17023SJohn Marino 	    {
851e4b17023SJohn Marino 	      /* Avoid passing --jobserver-fd= and similar flags
852e4b17023SJohn Marino 		 unless jobserver mode is explicitly enabled.  */
853e4b17023SJohn Marino 	      putenv (xstrdup ("MAKEFLAGS="));
854e4b17023SJohn Marino 	      putenv (xstrdup ("MFLAGS="));
855e4b17023SJohn Marino 	    }
856e4b17023SJohn Marino 	  new_argv[0] = getenv ("MAKE");
857e4b17023SJohn Marino 	  if (!new_argv[0])
858e4b17023SJohn Marino 	    new_argv[0] = "make";
859e4b17023SJohn Marino 	  new_argv[1] = "-f";
860e4b17023SJohn Marino 	  new_argv[2] = makefile;
861e4b17023SJohn Marino 	  i = 3;
862e4b17023SJohn Marino 	  if (!jobserver)
863e4b17023SJohn Marino 	    {
864e4b17023SJohn Marino 	      snprintf (jobs, 31, "-j%d", parallel);
865e4b17023SJohn Marino 	      new_argv[i++] = jobs;
866e4b17023SJohn Marino 	    }
867e4b17023SJohn Marino 	  new_argv[i++] = "all";
868e4b17023SJohn Marino 	  new_argv[i++] = NULL;
869e4b17023SJohn Marino 	  pex = collect_execute (CONST_CAST (char **, new_argv));
870e4b17023SJohn Marino 	  collect_wait (new_argv[0], pex);
871e4b17023SJohn Marino 	  maybe_unlink_file (makefile);
872e4b17023SJohn Marino 	  makefile = NULL;
873e4b17023SJohn Marino 	  for (i = 0; i < nr; ++i)
874e4b17023SJohn Marino 	    maybe_unlink_file (input_names[i]);
875e4b17023SJohn Marino 	}
876e4b17023SJohn Marino       for (i = 0; i < nr; ++i)
877e4b17023SJohn Marino 	{
878e4b17023SJohn Marino 	  fputs (output_names[i], stdout);
879e4b17023SJohn Marino 	  putc ('\n', stdout);
880e4b17023SJohn Marino 	  free (input_names[i]);
881e4b17023SJohn Marino 	}
882e4b17023SJohn Marino       nr = 0;
883e4b17023SJohn Marino       free (output_names);
884e4b17023SJohn Marino       free (input_names);
885e4b17023SJohn Marino       free (list_option_full);
886e4b17023SJohn Marino       obstack_free (&env_obstack, NULL);
887e4b17023SJohn Marino     }
888e4b17023SJohn Marino 
889e4b17023SJohn Marino   obstack_free (&argv_obstack, NULL);
890e4b17023SJohn Marino }
891e4b17023SJohn Marino 
892e4b17023SJohn Marino 
893e4b17023SJohn Marino /* Entry point.  */
894e4b17023SJohn Marino 
895e4b17023SJohn Marino int
main(int argc,char * argv[])896e4b17023SJohn Marino main (int argc, char *argv[])
897e4b17023SJohn Marino {
898e4b17023SJohn Marino   const char *p;
899e4b17023SJohn Marino 
900e4b17023SJohn Marino   p = argv[0] + strlen (argv[0]);
901e4b17023SJohn Marino   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
902e4b17023SJohn Marino     --p;
903e4b17023SJohn Marino   progname = p;
904e4b17023SJohn Marino 
905e4b17023SJohn Marino   xmalloc_set_program_name (progname);
906e4b17023SJohn Marino 
907e4b17023SJohn Marino   gcc_init_libintl ();
908e4b17023SJohn Marino 
909e4b17023SJohn Marino   diagnostic_initialize (global_dc, 0);
910e4b17023SJohn Marino 
911e4b17023SJohn Marino   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
912e4b17023SJohn Marino     signal (SIGINT, fatal_signal);
913e4b17023SJohn Marino #ifdef SIGHUP
914e4b17023SJohn Marino   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
915e4b17023SJohn Marino     signal (SIGHUP, fatal_signal);
916e4b17023SJohn Marino #endif
917e4b17023SJohn Marino   if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
918e4b17023SJohn Marino     signal (SIGTERM, fatal_signal);
919e4b17023SJohn Marino #ifdef SIGPIPE
920e4b17023SJohn Marino   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
921e4b17023SJohn Marino     signal (SIGPIPE, fatal_signal);
922e4b17023SJohn Marino #endif
923e4b17023SJohn Marino #ifdef SIGCHLD
924e4b17023SJohn Marino   /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
925e4b17023SJohn Marino      receive the signal.  A different setting is inheritable */
926e4b17023SJohn Marino   signal (SIGCHLD, SIG_DFL);
927e4b17023SJohn Marino #endif
928e4b17023SJohn Marino 
929e4b17023SJohn Marino   /* We may be called with all the arguments stored in some file and
930e4b17023SJohn Marino      passed with @file.  Expand them into argv before processing.  */
931e4b17023SJohn Marino   expandargv (&argc, &argv);
932e4b17023SJohn Marino 
933e4b17023SJohn Marino   run_gcc (argc, argv);
934e4b17023SJohn Marino 
935e4b17023SJohn Marino   return 0;
936e4b17023SJohn Marino }
937