]>
Commit | Line | Data |
---|---|---|
d7f09764 | 1 | /* Wrapper to call lto. Used by collect2 and the linker plugin. |
23a5b65a | 2 | Copyright (C) 2009-2014 Free Software Foundation, Inc. |
d7f09764 DN |
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 | ||
014d92e1 | 35 | If WHOPR is used instead, more than one file might be produced |
d7f09764 DN |
36 | ./ccXj2DTk.lto.ltrans.o |
37 | ./ccCJuXGv.lto.ltrans.o | |
38 | */ | |
39 | ||
40 | #include "config.h" | |
41 | #include "system.h" | |
10692477 | 42 | #include "coretypes.h" |
d7f09764 | 43 | #include "intl.h" |
2691e6d7 | 44 | #include "diagnostic.h" |
48cf395b | 45 | #include "obstack.h" |
f31c0018 RG |
46 | #include "opts.h" |
47 | #include "options.h" | |
52a35ef7 | 48 | #include "simple-object.h" |
4000360e | 49 | #include "lto-section-names.h" |
a185856a | 50 | #include "collect-utils.h" |
d7f09764 DN |
51 | |
52 | enum lto_mode_d { | |
cf96bae7 RG |
53 | LTO_MODE_NONE, /* Not doing LTO. */ |
54 | LTO_MODE_LTO, /* Normal LTO. */ | |
55 | LTO_MODE_WHOPR /* WHOPR. */ | |
d7f09764 DN |
56 | }; |
57 | ||
58 | /* Current LTO mode. */ | |
59 | static enum lto_mode_d lto_mode = LTO_MODE_NONE; | |
60 | ||
b1b07c92 RG |
61 | static char *ltrans_output_file; |
62 | static char *flto_out; | |
50ee30d5 RG |
63 | static unsigned int nr; |
64 | static char **input_names; | |
65 | static char **output_names; | |
66 | static char *makefile; | |
b1b07c92 | 67 | |
a185856a | 68 | const char tool_name[] = "lto-wrapper"; |
b1b07c92 | 69 | |
a185856a | 70 | /* Delete tempfiles. Called from utils_cleanup. */ |
b1b07c92 | 71 | |
a185856a | 72 | void |
5f0ad6a5 | 73 | tool_cleanup (bool) |
b1b07c92 | 74 | { |
396717c9 RG |
75 | unsigned int i; |
76 | ||
396717c9 | 77 | if (ltrans_output_file) |
a185856a | 78 | maybe_unlink (ltrans_output_file); |
396717c9 | 79 | if (flto_out) |
a185856a | 80 | maybe_unlink (flto_out); |
396717c9 | 81 | if (makefile) |
a185856a | 82 | maybe_unlink (makefile); |
396717c9 | 83 | for (i = 0; i < nr; ++i) |
8aea79e6 | 84 | { |
a185856a | 85 | maybe_unlink (input_names[i]); |
396717c9 | 86 | if (output_names[i]) |
a185856a | 87 | maybe_unlink (output_names[i]); |
8aea79e6 | 88 | } |
396717c9 RG |
89 | } |
90 | ||
91 | static void | |
a185856a | 92 | lto_wrapper_cleanup (void) |
d7f09764 | 93 | { |
5f0ad6a5 | 94 | utils_cleanup (false); |
d7f09764 DN |
95 | } |
96 | ||
d7f09764 DN |
97 | /* Unlink a temporary LTRANS file unless requested otherwise. */ |
98 | ||
a185856a BS |
99 | void |
100 | maybe_unlink (const char *file) | |
d7f09764 | 101 | { |
608508a6 | 102 | if (!save_temps) |
d7f09764 | 103 | { |
62116e60 RG |
104 | if (unlink_if_ordinary (file) |
105 | && errno != ENOENT) | |
ffb1f5ef | 106 | fatal_error ("deleting LTRANS file %s: %m", file); |
d7f09764 | 107 | } |
eba14fca | 108 | else if (verbose) |
d7f09764 DN |
109 | fprintf (stderr, "[Leaving LTRANS %s]\n", file); |
110 | } | |
111 | ||
48cf395b RB |
112 | /* Template of LTRANS dumpbase suffix. */ |
113 | #define DUMPBASE_SUFFIX ".ltrans18446744073709551615" | |
d7f09764 | 114 | |
f31c0018 RG |
115 | /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS |
116 | environment according to LANG_MASK. */ | |
117 | ||
118 | static void | |
119 | get_options_from_collect_gcc_options (const char *collect_gcc, | |
120 | const char *collect_gcc_options, | |
121 | unsigned int lang_mask, | |
122 | struct cl_decoded_option **decoded_options, | |
123 | unsigned int *decoded_options_count) | |
124 | { | |
969d578c | 125 | struct obstack argv_obstack; |
f31c0018 RG |
126 | char *argv_storage; |
127 | const char **argv; | |
969d578c RG |
128 | int j, k, argc; |
129 | ||
f31c0018 | 130 | argv_storage = xstrdup (collect_gcc_options); |
969d578c RG |
131 | obstack_init (&argv_obstack); |
132 | obstack_ptr_grow (&argv_obstack, collect_gcc); | |
133 | ||
134 | for (j = 0, k = 0; argv_storage[j] != '\0'; ++j) | |
f31c0018 RG |
135 | { |
136 | if (argv_storage[j] == '\'') | |
137 | { | |
969d578c RG |
138 | obstack_ptr_grow (&argv_obstack, &argv_storage[k]); |
139 | ++j; | |
140 | do | |
141 | { | |
142 | if (argv_storage[j] == '\0') | |
ffb1f5ef | 143 | fatal_error ("malformed COLLECT_GCC_OPTIONS"); |
969d578c RG |
144 | else if (strncmp (&argv_storage[j], "'\\''", 4) == 0) |
145 | { | |
146 | argv_storage[k++] = '\''; | |
147 | j += 4; | |
148 | } | |
149 | else if (argv_storage[j] == '\'') | |
150 | break; | |
151 | else | |
152 | argv_storage[k++] = argv_storage[j++]; | |
153 | } | |
154 | while (1); | |
155 | argv_storage[k++] = '\0'; | |
f31c0018 RG |
156 | } |
157 | } | |
969d578c RG |
158 | |
159 | obstack_ptr_grow (&argv_obstack, NULL); | |
160 | argc = obstack_object_size (&argv_obstack) / sizeof (void *) - 1; | |
161 | argv = XOBFINISH (&argv_obstack, const char **); | |
f31c0018 RG |
162 | |
163 | decode_cmdline_options_to_array (argc, (const char **)argv, | |
164 | lang_mask, | |
165 | decoded_options, decoded_options_count); | |
969d578c | 166 | obstack_free (&argv_obstack, NULL); |
f31c0018 RG |
167 | } |
168 | ||
52a35ef7 RG |
169 | /* Append OPTION to the options array DECODED_OPTIONS with size |
170 | DECODED_OPTIONS_COUNT. */ | |
171 | ||
172 | static void | |
173 | append_option (struct cl_decoded_option **decoded_options, | |
174 | unsigned int *decoded_options_count, | |
175 | struct cl_decoded_option *option) | |
176 | { | |
177 | ++*decoded_options_count; | |
178 | *decoded_options | |
179 | = (struct cl_decoded_option *) | |
180 | xrealloc (*decoded_options, | |
181 | (*decoded_options_count | |
182 | * sizeof (struct cl_decoded_option))); | |
183 | memcpy (&(*decoded_options)[*decoded_options_count - 1], option, | |
184 | sizeof (struct cl_decoded_option)); | |
185 | } | |
186 | ||
187 | /* Try to merge and complain about options FDECODED_OPTIONS when applied | |
188 | ontop of DECODED_OPTIONS. */ | |
189 | ||
190 | static void | |
191 | merge_and_complain (struct cl_decoded_option **decoded_options, | |
192 | unsigned int *decoded_options_count, | |
193 | struct cl_decoded_option *fdecoded_options, | |
194 | unsigned int fdecoded_options_count) | |
195 | { | |
196 | unsigned int i, j; | |
197 | ||
198 | /* ??? Merge options from files. Most cases can be | |
199 | handled by either unioning or intersecting | |
200 | (for example -fwrapv is a case for unioning, | |
201 | -ffast-math is for intersection). Most complaints | |
202 | about real conflicts between different options can | |
203 | be deferred to the compiler proper. Options that | |
204 | we can neither safely handle by intersection nor | |
205 | unioning would need to be complained about here. | |
206 | Ideally we'd have a flag in the opt files that | |
207 | tells whether to union or intersect or reject. | |
208 | In absence of that it's unclear what a good default is. | |
209 | It's also difficult to get positional handling correct. */ | |
210 | ||
211 | /* The following does what the old LTO option code did, | |
212 | union all target and a selected set of common options. */ | |
213 | for (i = 0; i < fdecoded_options_count; ++i) | |
214 | { | |
215 | struct cl_decoded_option *foption = &fdecoded_options[i]; | |
216 | switch (foption->opt_index) | |
217 | { | |
169d8507 L |
218 | case OPT_SPECIAL_unknown: |
219 | case OPT_SPECIAL_ignore: | |
220 | case OPT_SPECIAL_program_name: | |
221 | case OPT_SPECIAL_input_file: | |
222 | break; | |
223 | ||
52a35ef7 RG |
224 | default: |
225 | if (!(cl_options[foption->opt_index].flags & CL_TARGET)) | |
226 | break; | |
227 | ||
228 | /* Fallthru. */ | |
229 | case OPT_fPIC: | |
230 | case OPT_fpic: | |
585d0088 | 231 | case OPT_fPIE: |
52a35ef7 RG |
232 | case OPT_fpie: |
233 | case OPT_fcommon: | |
234 | case OPT_fexceptions: | |
2a5145b0 | 235 | case OPT_fnon_call_exceptions: |
aad038ca | 236 | case OPT_fgnu_tm: |
52a35ef7 RG |
237 | /* Do what the old LTO code did - collect exactly one option |
238 | setting per OPT code, we pick the first we encounter. | |
239 | ??? This doesn't make too much sense, but when it doesn't | |
240 | then we should complain. */ | |
241 | for (j = 0; j < *decoded_options_count; ++j) | |
242 | if ((*decoded_options)[j].opt_index == foption->opt_index) | |
243 | break; | |
244 | if (j == *decoded_options_count) | |
245 | append_option (decoded_options, decoded_options_count, foption); | |
246 | break; | |
8bb50e5c | 247 | |
4094757e RB |
248 | case OPT_ftrapv: |
249 | case OPT_fstrict_overflow: | |
5d1a0108 RB |
250 | case OPT_ffp_contract_: |
251 | /* For selected options we can merge conservatively. */ | |
252 | for (j = 0; j < *decoded_options_count; ++j) | |
253 | if ((*decoded_options)[j].opt_index == foption->opt_index) | |
254 | break; | |
255 | if (j == *decoded_options_count) | |
256 | append_option (decoded_options, decoded_options_count, foption); | |
4094757e RB |
257 | /* FP_CONTRACT_OFF < FP_CONTRACT_ON < FP_CONTRACT_FAST, |
258 | -fno-trapv < -ftrapv, | |
259 | -fno-strict-overflow < -fstrict-overflow */ | |
5d1a0108 RB |
260 | else if (foption->value < (*decoded_options)[j].value) |
261 | (*decoded_options)[j] = *foption; | |
262 | break; | |
263 | ||
a35c1ac7 EB |
264 | case OPT_fmath_errno: |
265 | case OPT_fsigned_zeros: | |
266 | case OPT_ftrapping_math: | |
4094757e RB |
267 | case OPT_fwrapv: |
268 | /* For selected options we can merge conservatively. */ | |
269 | for (j = 0; j < *decoded_options_count; ++j) | |
270 | if ((*decoded_options)[j].opt_index == foption->opt_index) | |
271 | break; | |
272 | if (j == *decoded_options_count) | |
273 | append_option (decoded_options, decoded_options_count, foption); | |
a35c1ac7 EB |
274 | /* -fmath-errno > -fno-math-errno, |
275 | -fsigned-zeros > -fno-signed-zeros, | |
276 | -ftrapping-math -> -fno-trapping-math, | |
277 | -fwrapv > -fno-wrapv. */ | |
4094757e RB |
278 | else if (foption->value > (*decoded_options)[j].value) |
279 | (*decoded_options)[j] = *foption; | |
280 | break; | |
281 | ||
8bb50e5c RG |
282 | case OPT_freg_struct_return: |
283 | case OPT_fpcc_struct_return: | |
f42c637e | 284 | case OPT_fshort_double: |
8bb50e5c RG |
285 | for (j = 0; j < *decoded_options_count; ++j) |
286 | if ((*decoded_options)[j].opt_index == foption->opt_index) | |
287 | break; | |
288 | if (j == *decoded_options_count) | |
ffb1f5ef BS |
289 | fatal_error ("Option %s not used consistently in all LTO input" |
290 | " files", foption->orig_option_with_args_text); | |
8bb50e5c | 291 | break; |
f3ba16d0 RB |
292 | |
293 | case OPT_O: | |
294 | case OPT_Ofast: | |
295 | case OPT_Og: | |
296 | case OPT_Os: | |
297 | for (j = 0; j < *decoded_options_count; ++j) | |
298 | if ((*decoded_options)[j].opt_index == OPT_O | |
299 | || (*decoded_options)[j].opt_index == OPT_Ofast | |
300 | || (*decoded_options)[j].opt_index == OPT_Og | |
301 | || (*decoded_options)[j].opt_index == OPT_Os) | |
302 | break; | |
303 | if (j == *decoded_options_count) | |
304 | append_option (decoded_options, decoded_options_count, foption); | |
305 | else if ((*decoded_options)[j].opt_index == foption->opt_index | |
306 | && foption->opt_index != OPT_O) | |
307 | /* Exact same options get merged. */ | |
308 | ; | |
309 | else | |
310 | { | |
311 | /* For mismatched option kinds preserve the optimization | |
312 | level only, thus merge it as -On. This also handles | |
313 | merging of same optimization level -On. */ | |
314 | int level = 0; | |
315 | switch (foption->opt_index) | |
316 | { | |
317 | case OPT_O: | |
318 | if (foption->arg[0] == '\0') | |
319 | level = MAX (level, 1); | |
320 | else | |
321 | level = MAX (level, atoi (foption->arg)); | |
322 | break; | |
323 | case OPT_Ofast: | |
324 | level = MAX (level, 3); | |
325 | break; | |
326 | case OPT_Og: | |
327 | level = MAX (level, 1); | |
328 | break; | |
329 | case OPT_Os: | |
330 | level = MAX (level, 2); | |
331 | break; | |
332 | default: | |
333 | gcc_unreachable (); | |
334 | } | |
335 | switch ((*decoded_options)[j].opt_index) | |
336 | { | |
337 | case OPT_O: | |
338 | if ((*decoded_options)[j].arg[0] == '\0') | |
339 | level = MAX (level, 1); | |
340 | else | |
341 | level = MAX (level, atoi ((*decoded_options)[j].arg)); | |
342 | break; | |
343 | case OPT_Ofast: | |
344 | level = MAX (level, 3); | |
345 | break; | |
346 | case OPT_Og: | |
347 | level = MAX (level, 1); | |
348 | break; | |
349 | case OPT_Os: | |
350 | level = MAX (level, 2); | |
351 | break; | |
352 | default: | |
353 | gcc_unreachable (); | |
354 | } | |
355 | (*decoded_options)[j].opt_index = OPT_O; | |
356 | char *tem; | |
357 | asprintf (&tem, "-O%d", level); | |
358 | (*decoded_options)[j].arg = &tem[2]; | |
359 | (*decoded_options)[j].canonical_option[0] = tem; | |
360 | (*decoded_options)[j].value = 1; | |
361 | } | |
362 | break; | |
52a35ef7 RG |
363 | } |
364 | } | |
365 | } | |
f31c0018 | 366 | |
d7f09764 DN |
367 | /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */ |
368 | ||
369 | static void | |
370 | run_gcc (unsigned argc, char *argv[]) | |
371 | { | |
cf96bae7 | 372 | unsigned i, j; |
d7f09764 DN |
373 | const char **new_argv; |
374 | const char **argv_ptr; | |
d7f09764 | 375 | char *list_option_full = NULL; |
cf96bae7 | 376 | const char *linker_output = NULL; |
f31c0018 | 377 | const char *collect_gcc, *collect_gcc_options; |
c04b6b38 | 378 | int parallel = 0; |
a478ffff | 379 | int jobserver = 0; |
014d92e1 | 380 | bool no_partition = false; |
52a35ef7 RG |
381 | struct cl_decoded_option *fdecoded_options = NULL; |
382 | unsigned int fdecoded_options_count = 0; | |
f31c0018 RG |
383 | struct cl_decoded_option *decoded_options; |
384 | unsigned int decoded_options_count; | |
ef6f874e RG |
385 | struct obstack argv_obstack; |
386 | int new_head_argc; | |
cf96bae7 RG |
387 | |
388 | /* Get the driver and options. */ | |
389 | collect_gcc = getenv ("COLLECT_GCC"); | |
390 | if (!collect_gcc) | |
ffb1f5ef | 391 | fatal_error ("environment variable COLLECT_GCC must be set"); |
cf96bae7 RG |
392 | collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS"); |
393 | if (!collect_gcc_options) | |
ffb1f5ef | 394 | fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set"); |
f31c0018 RG |
395 | get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options, |
396 | CL_LANG_ALL, | |
397 | &decoded_options, | |
398 | &decoded_options_count); | |
cf96bae7 | 399 | |
52a35ef7 RG |
400 | /* Look at saved options in the IL files. */ |
401 | for (i = 1; i < argc; ++i) | |
402 | { | |
403 | char *data, *p; | |
404 | char *fopts; | |
405 | int fd; | |
406 | const char *errmsg; | |
407 | int err; | |
408 | off_t file_offset = 0, offset, length; | |
409 | long loffset; | |
410 | simple_object_read *sobj; | |
411 | int consumed; | |
412 | struct cl_decoded_option *f2decoded_options; | |
413 | unsigned int f2decoded_options_count; | |
414 | char *filename = argv[i]; | |
415 | if ((p = strrchr (argv[i], '@')) | |
416 | && p != argv[i] | |
417 | && sscanf (p, "@%li%n", &loffset, &consumed) >= 1 | |
418 | && strlen (p) == (unsigned int) consumed) | |
419 | { | |
420 | filename = XNEWVEC (char, p - argv[i] + 1); | |
421 | memcpy (filename, argv[i], p - argv[i]); | |
422 | filename[p - argv[i]] = '\0'; | |
423 | file_offset = (off_t) loffset; | |
424 | } | |
425 | fd = open (argv[i], O_RDONLY); | |
426 | if (fd == -1) | |
427 | continue; | |
f2ede0ee AH |
428 | sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO", |
429 | &errmsg, &err); | |
52a35ef7 RG |
430 | if (!sobj) |
431 | { | |
432 | close (fd); | |
433 | continue; | |
434 | } | |
435 | if (!simple_object_find_section (sobj, LTO_SECTION_NAME_PREFIX "." "opts", | |
436 | &offset, &length, &errmsg, &err)) | |
437 | { | |
438 | simple_object_release_read (sobj); | |
439 | close (fd); | |
440 | continue; | |
441 | } | |
442 | lseek (fd, file_offset + offset, SEEK_SET); | |
443 | data = (char *)xmalloc (length); | |
444 | read (fd, data, length); | |
445 | fopts = data; | |
446 | do | |
447 | { | |
448 | get_options_from_collect_gcc_options (collect_gcc, | |
449 | fopts, CL_LANG_ALL, | |
450 | &f2decoded_options, | |
451 | &f2decoded_options_count); | |
452 | if (!fdecoded_options) | |
453 | { | |
454 | fdecoded_options = f2decoded_options; | |
455 | fdecoded_options_count = f2decoded_options_count; | |
456 | } | |
457 | else | |
458 | merge_and_complain (&fdecoded_options, | |
459 | &fdecoded_options_count, | |
460 | f2decoded_options, f2decoded_options_count); | |
461 | ||
462 | fopts += strlen (fopts) + 1; | |
463 | } | |
464 | while (fopts - data < length); | |
465 | ||
466 | free (data); | |
467 | simple_object_release_read (sobj); | |
468 | close (fd); | |
469 | } | |
470 | ||
cf96bae7 | 471 | /* Initalize the common arguments for the driver. */ |
ef6f874e RG |
472 | obstack_init (&argv_obstack); |
473 | obstack_ptr_grow (&argv_obstack, collect_gcc); | |
474 | obstack_ptr_grow (&argv_obstack, "-xlto"); | |
475 | obstack_ptr_grow (&argv_obstack, "-c"); | |
52a35ef7 RG |
476 | |
477 | /* Append compiler driver arguments as far as they were merged. */ | |
478 | for (j = 1; j < fdecoded_options_count; ++j) | |
479 | { | |
480 | struct cl_decoded_option *option = &fdecoded_options[j]; | |
481 | ||
482 | /* File options have been properly filtered by lto-opts.c. */ | |
483 | switch (option->opt_index) | |
484 | { | |
485 | /* Drop arguments that we want to take from the link line. */ | |
486 | case OPT_flto_: | |
487 | case OPT_flto: | |
783dab6b | 488 | case OPT_flto_partition_: |
52a35ef7 RG |
489 | continue; |
490 | ||
491 | default: | |
492 | break; | |
493 | } | |
494 | ||
495 | /* For now do what the original LTO option code was doing - pass | |
496 | on any CL_TARGET flag and a few selected others. */ | |
497 | switch (option->opt_index) | |
498 | { | |
499 | case OPT_fPIC: | |
500 | case OPT_fpic: | |
585d0088 | 501 | case OPT_fPIE: |
52a35ef7 RG |
502 | case OPT_fpie: |
503 | case OPT_fcommon: | |
504 | case OPT_fexceptions: | |
2a5145b0 | 505 | case OPT_fnon_call_exceptions: |
aad038ca | 506 | case OPT_fgnu_tm: |
8bb50e5c RG |
507 | case OPT_freg_struct_return: |
508 | case OPT_fpcc_struct_return: | |
f42c637e | 509 | case OPT_fshort_double: |
5d1a0108 | 510 | case OPT_ffp_contract_: |
a35c1ac7 EB |
511 | case OPT_fmath_errno: |
512 | case OPT_fsigned_zeros: | |
513 | case OPT_ftrapping_math: | |
4094757e RB |
514 | case OPT_fwrapv: |
515 | case OPT_ftrapv: | |
516 | case OPT_fstrict_overflow: | |
f3ba16d0 RB |
517 | case OPT_O: |
518 | case OPT_Ofast: | |
519 | case OPT_Og: | |
520 | case OPT_Os: | |
52a35ef7 RG |
521 | break; |
522 | ||
523 | default: | |
524 | if (!(cl_options[option->opt_index].flags & CL_TARGET)) | |
525 | continue; | |
526 | } | |
527 | ||
528 | /* Pass the option on. */ | |
529 | for (i = 0; i < option->canonical_option_num_elements; ++i) | |
530 | obstack_ptr_grow (&argv_obstack, option->canonical_option[i]); | |
531 | } | |
532 | ||
533 | /* Append linker driver arguments. Compiler options from the linker | |
534 | driver arguments will override / merge with those from the compiler. */ | |
f31c0018 RG |
535 | for (j = 1; j < decoded_options_count; ++j) |
536 | { | |
537 | struct cl_decoded_option *option = &decoded_options[j]; | |
d7f09764 | 538 | |
ef6f874e | 539 | /* Do not pass on frontend specific flags not suitable for lto. */ |
f31c0018 | 540 | if (!(cl_options[option->opt_index].flags |
ef6f874e | 541 | & (CL_COMMON|CL_TARGET|CL_DRIVER|CL_LTO))) |
f31c0018 RG |
542 | continue; |
543 | ||
544 | switch (option->opt_index) | |
545 | { | |
546 | case OPT_o: | |
547 | linker_output = option->arg; | |
548 | /* We generate new intermediate output, drop this arg. */ | |
549 | continue; | |
550 | ||
551 | case OPT_save_temps: | |
608508a6 | 552 | save_temps = 1; |
f31c0018 RG |
553 | break; |
554 | ||
555 | case OPT_v: | |
cf96bae7 | 556 | verbose = 1; |
f31c0018 | 557 | break; |
cf96bae7 | 558 | |
783dab6b RB |
559 | case OPT_flto_partition_: |
560 | if (strcmp (option->arg, "none") == 0) | |
561 | no_partition = true; | |
f31c0018 RG |
562 | break; |
563 | ||
564 | case OPT_flto_: | |
565 | if (strcmp (option->arg, "jobserver") == 0) | |
566 | { | |
567 | jobserver = 1; | |
568 | parallel = 1; | |
569 | } | |
570 | else | |
571 | { | |
572 | parallel = atoi (option->arg); | |
573 | if (parallel <= 1) | |
574 | parallel = 0; | |
575 | } | |
576 | /* Fallthru. */ | |
577 | ||
578 | case OPT_flto: | |
579 | lto_mode = LTO_MODE_WHOPR; | |
580 | /* We've handled these LTO options, do not pass them on. */ | |
581 | continue; | |
582 | ||
8bb50e5c RG |
583 | case OPT_freg_struct_return: |
584 | case OPT_fpcc_struct_return: | |
f42c637e | 585 | case OPT_fshort_double: |
8bb50e5c RG |
586 | /* Ignore these, they are determined by the input files. |
587 | ??? We fail to diagnose a possible mismatch here. */ | |
588 | continue; | |
589 | ||
f31c0018 RG |
590 | default: |
591 | break; | |
592 | } | |
593 | ||
594 | /* Pass the option on. */ | |
ef6f874e RG |
595 | for (i = 0; i < option->canonical_option_num_elements; ++i) |
596 | obstack_ptr_grow (&argv_obstack, option->canonical_option[i]); | |
f31c0018 RG |
597 | } |
598 | ||
014d92e1 JH |
599 | if (no_partition) |
600 | { | |
601 | lto_mode = LTO_MODE_LTO; | |
602 | jobserver = 0; | |
603 | parallel = 0; | |
604 | } | |
cf96bae7 RG |
605 | |
606 | if (linker_output) | |
607 | { | |
608 | char *output_dir, *base, *name; | |
dd3b31fb | 609 | bool bit_bucket = strcmp (linker_output, HOST_BIT_BUCKET) == 0; |
d7f09764 | 610 | |
cf96bae7 RG |
611 | output_dir = xstrdup (linker_output); |
612 | base = output_dir; | |
613 | for (name = base; *name; name++) | |
614 | if (IS_DIR_SEPARATOR (*name)) | |
615 | base = name + 1; | |
616 | *base = '\0'; | |
617 | ||
618 | linker_output = &linker_output[base - output_dir]; | |
619 | if (*output_dir == '\0') | |
620 | { | |
621 | static char current_dir[] = { '.', DIR_SEPARATOR, '\0' }; | |
622 | output_dir = current_dir; | |
623 | } | |
dd3b31fb L |
624 | if (!bit_bucket) |
625 | { | |
ef6f874e RG |
626 | obstack_ptr_grow (&argv_obstack, "-dumpdir"); |
627 | obstack_ptr_grow (&argv_obstack, output_dir); | |
dd3b31fb | 628 | } |
cf96bae7 | 629 | |
ef6f874e | 630 | obstack_ptr_grow (&argv_obstack, "-dumpbase"); |
cf96bae7 | 631 | } |
ef6f874e RG |
632 | |
633 | /* Remember at which point we can scrub args to re-use the commons. */ | |
634 | new_head_argc = obstack_object_size (&argv_obstack) / sizeof (void *); | |
d7f09764 | 635 | |
d7f09764 DN |
636 | if (lto_mode == LTO_MODE_LTO) |
637 | { | |
638 | flto_out = make_temp_file (".lto.o"); | |
cf96bae7 | 639 | if (linker_output) |
ef6f874e RG |
640 | obstack_ptr_grow (&argv_obstack, linker_output); |
641 | obstack_ptr_grow (&argv_obstack, "-o"); | |
642 | obstack_ptr_grow (&argv_obstack, flto_out); | |
d7f09764 | 643 | } |
be286227 | 644 | else |
d7f09764 DN |
645 | { |
646 | const char *list_option = "-fltrans-output-list="; | |
647 | size_t list_option_len = strlen (list_option); | |
648 | char *tmp; | |
649 | ||
cf96bae7 RG |
650 | if (linker_output) |
651 | { | |
652 | char *dumpbase = (char *) xmalloc (strlen (linker_output) | |
b5611987 | 653 | + sizeof (".wpa") + 1); |
cf96bae7 RG |
654 | strcpy (dumpbase, linker_output); |
655 | strcat (dumpbase, ".wpa"); | |
ef6f874e | 656 | obstack_ptr_grow (&argv_obstack, dumpbase); |
cf96bae7 RG |
657 | } |
658 | ||
608508a6 | 659 | if (linker_output && save_temps) |
b5611987 RG |
660 | { |
661 | ltrans_output_file = (char *) xmalloc (strlen (linker_output) | |
662 | + sizeof (".ltrans.out") + 1); | |
663 | strcpy (ltrans_output_file, linker_output); | |
664 | strcat (ltrans_output_file, ".ltrans.out"); | |
665 | } | |
666 | else | |
667 | ltrans_output_file = make_temp_file (".ltrans.out"); | |
d7f09764 DN |
668 | list_option_full = (char *) xmalloc (sizeof (char) * |
669 | (strlen (ltrans_output_file) + list_option_len + 1)); | |
670 | tmp = list_option_full; | |
671 | ||
ef6f874e | 672 | obstack_ptr_grow (&argv_obstack, tmp); |
d7f09764 DN |
673 | strcpy (tmp, list_option); |
674 | tmp += list_option_len; | |
675 | strcpy (tmp, ltrans_output_file); | |
676 | ||
f300e7b8 JH |
677 | if (jobserver) |
678 | obstack_ptr_grow (&argv_obstack, xstrdup ("-fwpa=jobserver")); | |
679 | else if (parallel > 1) | |
680 | { | |
681 | char buf[256]; | |
682 | sprintf (buf, "-fwpa=%i", parallel); | |
683 | obstack_ptr_grow (&argv_obstack, xstrdup (buf)); | |
684 | } | |
685 | else | |
686 | obstack_ptr_grow (&argv_obstack, "-fwpa"); | |
d7f09764 | 687 | } |
d7f09764 | 688 | |
073a8998 | 689 | /* Append the input objects and possible preceding arguments. */ |
cf96bae7 | 690 | for (i = 1; i < argc; ++i) |
ef6f874e RG |
691 | obstack_ptr_grow (&argv_obstack, argv[i]); |
692 | obstack_ptr_grow (&argv_obstack, NULL); | |
d7f09764 | 693 | |
ef6f874e RG |
694 | new_argv = XOBFINISH (&argv_obstack, const char **); |
695 | argv_ptr = &new_argv[new_head_argc]; | |
5f0ad6a5 | 696 | fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true); |
48cf395b | 697 | |
d7f09764 DN |
698 | if (lto_mode == LTO_MODE_LTO) |
699 | { | |
c3284718 | 700 | printf ("%s\n", flto_out); |
d7f09764 DN |
701 | free (flto_out); |
702 | flto_out = NULL; | |
703 | } | |
be286227 | 704 | else |
d7f09764 DN |
705 | { |
706 | FILE *stream = fopen (ltrans_output_file, "r"); | |
c04b6b38 | 707 | FILE *mstream = NULL; |
4559db79 | 708 | struct obstack env_obstack; |
d7f09764 DN |
709 | |
710 | if (!stream) | |
ffb1f5ef | 711 | fatal_error ("fopen: %s: %m", ltrans_output_file); |
d7f09764 | 712 | |
50ee30d5 | 713 | /* Parse the list of LTRANS inputs from the WPA stage. */ |
4559db79 | 714 | obstack_init (&env_obstack); |
50ee30d5 | 715 | nr = 0; |
48cf395b RB |
716 | for (;;) |
717 | { | |
718 | const unsigned piece = 32; | |
50ee30d5 | 719 | char *output_name = NULL; |
48cf395b RB |
720 | char *buf, *input_name = (char *)xmalloc (piece); |
721 | size_t len; | |
722 | ||
723 | buf = input_name; | |
724 | cont: | |
725 | if (!fgets (buf, piece, stream)) | |
726 | break; | |
727 | len = strlen (input_name); | |
728 | if (input_name[len - 1] != '\n') | |
729 | { | |
730 | input_name = (char *)xrealloc (input_name, len + piece); | |
731 | buf = input_name + len; | |
732 | goto cont; | |
733 | } | |
734 | input_name[len - 1] = '\0'; | |
735 | ||
736 | if (input_name[0] == '*') | |
c04b6b38 | 737 | output_name = &input_name[1]; |
48cf395b | 738 | |
c04b6b38 RG |
739 | nr++; |
740 | input_names = (char **)xrealloc (input_names, nr * sizeof (char *)); | |
741 | output_names = (char **)xrealloc (output_names, nr * sizeof (char *)); | |
742 | input_names[nr-1] = input_name; | |
743 | output_names[nr-1] = output_name; | |
744 | } | |
50ee30d5 | 745 | fclose (stream); |
a185856a | 746 | maybe_unlink (ltrans_output_file); |
50ee30d5 RG |
747 | ltrans_output_file = NULL; |
748 | ||
749 | if (parallel) | |
750 | { | |
751 | makefile = make_temp_file (".mk"); | |
752 | mstream = fopen (makefile, "w"); | |
753 | } | |
754 | ||
755 | /* Execute the LTRANS stage for each input file (or prepare a | |
756 | makefile to invoke this in parallel). */ | |
757 | for (i = 0; i < nr; ++i) | |
758 | { | |
759 | char *output_name; | |
760 | char *input_name = input_names[i]; | |
761 | /* If it's a pass-through file do nothing. */ | |
762 | if (output_names[i]) | |
763 | continue; | |
764 | ||
765 | /* Replace the .o suffix with a .ltrans.o suffix and write | |
766 | the resulting name to the LTRANS output list. */ | |
50ee30d5 RG |
767 | obstack_grow (&env_obstack, input_name, strlen (input_name) - 2); |
768 | obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o")); | |
769 | output_name = XOBFINISH (&env_obstack, char *); | |
770 | ||
771 | /* Adjust the dumpbase if the linker output file was seen. */ | |
772 | if (linker_output) | |
773 | { | |
774 | char *dumpbase | |
775 | = (char *) xmalloc (strlen (linker_output) | |
c3284718 | 776 | + sizeof (DUMPBASE_SUFFIX) + 1); |
50ee30d5 | 777 | snprintf (dumpbase, |
c3284718 | 778 | strlen (linker_output) + sizeof (DUMPBASE_SUFFIX), |
b5611987 | 779 | "%s.ltrans%u", linker_output, i); |
50ee30d5 RG |
780 | argv_ptr[0] = dumpbase; |
781 | } | |
782 | ||
783 | argv_ptr[1] = "-fltrans"; | |
784 | argv_ptr[2] = "-o"; | |
785 | argv_ptr[3] = output_name; | |
786 | argv_ptr[4] = input_name; | |
787 | argv_ptr[5] = NULL; | |
788 | if (parallel) | |
789 | { | |
790 | fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]); | |
791 | for (j = 1; new_argv[j] != NULL; ++j) | |
792 | fprintf (mstream, " '%s'", new_argv[j]); | |
793 | fprintf (mstream, "\n"); | |
9d69847d RG |
794 | /* If we are not preserving the ltrans input files then |
795 | truncate them as soon as we have processed it. This | |
796 | reduces temporary disk-space usage. */ | |
608508a6 | 797 | if (! save_temps) |
9d69847d RG |
798 | fprintf (mstream, "\t@-touch -r %s %s.tem > /dev/null 2>&1 " |
799 | "&& mv %s.tem %s\n", | |
800 | input_name, input_name, input_name, input_name); | |
50ee30d5 RG |
801 | } |
802 | else | |
9d69847d | 803 | { |
5f0ad6a5 BS |
804 | fork_execute (new_argv[0], CONST_CAST (char **, new_argv), |
805 | true); | |
a185856a | 806 | maybe_unlink (input_name); |
9d69847d | 807 | } |
50ee30d5 RG |
808 | |
809 | output_names[i] = output_name; | |
810 | } | |
c04b6b38 RG |
811 | if (parallel) |
812 | { | |
813 | struct pex_obj *pex; | |
814 | char jobs[32]; | |
a478ffff | 815 | |
c04b6b38 RG |
816 | fprintf (mstream, "all:"); |
817 | for (i = 0; i < nr; ++i) | |
818 | fprintf (mstream, " \\\n\t%s", output_names[i]); | |
819 | fprintf (mstream, "\n"); | |
820 | fclose (mstream); | |
a478ffff AK |
821 | if (!jobserver) |
822 | { | |
823 | /* Avoid passing --jobserver-fd= and similar flags | |
824 | unless jobserver mode is explicitly enabled. */ | |
825 | putenv (xstrdup ("MAKEFLAGS=")); | |
826 | putenv (xstrdup ("MFLAGS=")); | |
827 | } | |
5767217f RW |
828 | new_argv[0] = getenv ("MAKE"); |
829 | if (!new_argv[0]) | |
830 | new_argv[0] = "make"; | |
c04b6b38 RG |
831 | new_argv[1] = "-f"; |
832 | new_argv[2] = makefile; | |
a478ffff AK |
833 | i = 3; |
834 | if (!jobserver) | |
835 | { | |
836 | snprintf (jobs, 31, "-j%d", parallel); | |
837 | new_argv[i++] = jobs; | |
838 | } | |
839 | new_argv[i++] = "all"; | |
840 | new_argv[i++] = NULL; | |
5f0ad6a5 BS |
841 | pex = collect_execute (new_argv[0], CONST_CAST (char **, new_argv), |
842 | NULL, NULL, PEX_SEARCH, false); | |
843 | do_wait (new_argv[0], pex); | |
a185856a | 844 | maybe_unlink (makefile); |
50ee30d5 | 845 | makefile = NULL; |
9d69847d | 846 | for (i = 0; i < nr; ++i) |
a185856a | 847 | maybe_unlink (input_names[i]); |
c04b6b38 RG |
848 | } |
849 | for (i = 0; i < nr; ++i) | |
850 | { | |
851 | fputs (output_names[i], stdout); | |
48cf395b | 852 | putc ('\n', stdout); |
c04b6b38 | 853 | free (input_names[i]); |
48cf395b | 854 | } |
50ee30d5 | 855 | nr = 0; |
c04b6b38 RG |
856 | free (output_names); |
857 | free (input_names); | |
d7f09764 | 858 | free (list_option_full); |
4559db79 | 859 | obstack_free (&env_obstack, NULL); |
d7f09764 | 860 | } |
ef6f874e RG |
861 | |
862 | obstack_free (&argv_obstack, NULL); | |
d7f09764 DN |
863 | } |
864 | ||
865 | ||
866 | /* Entry point. */ | |
867 | ||
868 | int | |
869 | main (int argc, char *argv[]) | |
870 | { | |
2691e6d7 JM |
871 | const char *p; |
872 | ||
dc357798 JJ |
873 | gcc_obstack_init (&opts_obstack); |
874 | ||
2691e6d7 JM |
875 | p = argv[0] + strlen (argv[0]); |
876 | while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) | |
877 | --p; | |
878 | progname = p; | |
879 | ||
880 | xmalloc_set_program_name (progname); | |
881 | ||
ffb1f5ef BS |
882 | if (atexit (lto_wrapper_cleanup) != 0) |
883 | fatal_error ("atexit failed"); | |
884 | ||
d7f09764 DN |
885 | gcc_init_libintl (); |
886 | ||
2691e6d7 JM |
887 | diagnostic_initialize (global_dc, 0); |
888 | ||
396717c9 RG |
889 | if (signal (SIGINT, SIG_IGN) != SIG_IGN) |
890 | signal (SIGINT, fatal_signal); | |
891 | #ifdef SIGHUP | |
892 | if (signal (SIGHUP, SIG_IGN) != SIG_IGN) | |
893 | signal (SIGHUP, fatal_signal); | |
894 | #endif | |
895 | if (signal (SIGTERM, SIG_IGN) != SIG_IGN) | |
896 | signal (SIGTERM, fatal_signal); | |
897 | #ifdef SIGPIPE | |
898 | if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) | |
899 | signal (SIGPIPE, fatal_signal); | |
900 | #endif | |
901 | #ifdef SIGCHLD | |
902 | /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will | |
903 | receive the signal. A different setting is inheritable */ | |
904 | signal (SIGCHLD, SIG_DFL); | |
905 | #endif | |
906 | ||
d7f09764 DN |
907 | /* We may be called with all the arguments stored in some file and |
908 | passed with @file. Expand them into argv before processing. */ | |
909 | expandargv (&argc, &argv); | |
f31c0018 | 910 | |
cf96bae7 | 911 | run_gcc (argc, argv); |
d7f09764 DN |
912 | |
913 | return 0; | |
914 | } |