comparison gcc/lto-wrapper.c @ 63:b7f97abdc517 gcc-4.6-20100522

update gcc from gcc-4.5.0 to gcc-4.6
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Mon, 24 May 2010 12:47:05 +0900
parents 77e2b8dfacca
children f6334be47118
comparison
equal deleted inserted replaced
56:3c8a44c06a95 63:b7f97abdc517
1 /* Wrapper to call lto. Used by collect2 and the linker plugin. 1 /* Wrapper to call lto. Used by collect2 and the linker plugin.
2 Copyright (C) 2009 Free Software Foundation, Inc. 2 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3 3
4 Factored out of collect2 by Rafael Espindola <espindola@google.com> 4 Factored out of collect2 by Rafael Espindola <espindola@google.com>
5 5
6 This file is part of GCC. 6 This file is part of GCC.
7 7
41 #include "system.h" 41 #include "system.h"
42 #include "coretypes.h" 42 #include "coretypes.h"
43 #include "tm.h" 43 #include "tm.h"
44 #include "intl.h" 44 #include "intl.h"
45 #include "libiberty.h" 45 #include "libiberty.h"
46 46 #include "obstack.h"
47 int debug; /* true if -debug */ 47
48 int debug; /* true if -save-temps. */
49 int verbose; /* true if -v. */
48 50
49 enum lto_mode_d { 51 enum lto_mode_d {
50 LTO_MODE_NONE, /* Not doing LTO. */ 52 LTO_MODE_NONE, /* Not doing LTO. */
51 LTO_MODE_LTO, /* Normal LTO. */ 53 LTO_MODE_LTO, /* Normal LTO. */
52 LTO_MODE_WHOPR /* WHOPR. */ 54 LTO_MODE_WHOPR /* WHOPR. */
53 }; 55 };
54 56
55 /* Current LTO mode. */ 57 /* Current LTO mode. */
56 static enum lto_mode_d lto_mode = LTO_MODE_NONE; 58 static enum lto_mode_d lto_mode = LTO_MODE_NONE;
57 59
126 { 128 {
127 struct pex_obj *pex; 129 struct pex_obj *pex;
128 const char *errmsg; 130 const char *errmsg;
129 int err; 131 int err;
130 132
131 if (debug) 133 if (verbose)
132 { 134 {
133 char **p_argv; 135 char **p_argv;
134 const char *str; 136 const char *str;
135 137
136 for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++) 138 for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
144 146
145 pex = pex_init (0, "lto-wrapper", NULL); 147 pex = pex_init (0, "lto-wrapper", NULL);
146 if (pex == NULL) 148 if (pex == NULL)
147 fatal_perror ("pex_init failed"); 149 fatal_perror ("pex_init failed");
148 150
149 errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL, 151 /* Do not use PEX_LAST here, we use our stdout for communicating with
152 collect2 or the linker-plugin. Any output from the sub-process
153 will confuse that. */
154 errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL,
150 NULL, &err); 155 NULL, &err);
151 if (errmsg != NULL) 156 if (errmsg != NULL)
152 { 157 {
153 if (err != 0) 158 if (err != 0)
154 { 159 {
244 249
245 maybe_unlink_file (args_name); 250 maybe_unlink_file (args_name);
246 free (at_args); 251 free (at_args);
247 } 252 }
248 253
254 /* Template of LTRANS dumpbase suffix. */
255 #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
249 256
250 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */ 257 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
251 258
252 static void 259 static void
253 run_gcc (unsigned argc, char *argv[]) 260 run_gcc (unsigned argc, char *argv[])
254 { 261 {
255 unsigned i; 262 unsigned i, j;
256 unsigned new_argc = argc;
257 const char **new_argv; 263 const char **new_argv;
258 const char **argv_ptr; 264 const char **argv_ptr;
259 char *list_option_full = NULL; 265 char *list_option_full = NULL;
260 266 const char *linker_output = NULL;
261 new_argc += 8; 267 const char *collect_gcc_options, *collect_gcc;
262 new_argv = (const char **) xcalloc (sizeof (char *), new_argc); 268 struct obstack env_obstack;
263 269 bool seen_o = false;
270 int parallel = 0;
271
272 /* Get the driver and options. */
273 collect_gcc = getenv ("COLLECT_GCC");
274 if (!collect_gcc)
275 fatal ("environment variable COLLECT_GCC must be set");
276
277 /* Set the CFLAGS environment variable. */
278 collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
279 if (!collect_gcc_options)
280 fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
281
282 /* Count arguments. */
283 i = 0;
284 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
285 if (collect_gcc_options[j] == '\'')
286 ++i;
287
288 if (i % 2 != 0)
289 fatal ("malformed COLLECT_GCC_OPTIONS");
290
291 /* Initalize the common arguments for the driver. */
292 new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
264 argv_ptr = new_argv; 293 argv_ptr = new_argv;
265 294 *argv_ptr++ = collect_gcc;
266 *argv_ptr++ = argv[0]; 295 *argv_ptr++ = "-xlto";
267 *argv_ptr++ = "-combine";
268 *argv_ptr++ = "-x";
269 *argv_ptr++ = "lto";
270 *argv_ptr++ = "-c"; 296 *argv_ptr++ = "-c";
297 for (j = 0; collect_gcc_options[j] != '\0'; ++j)
298 if (collect_gcc_options[j] == '\'')
299 {
300 char *option;
301
302 ++j;
303 i = j;
304 while (collect_gcc_options[j] != '\'')
305 ++j;
306
307 obstack_init (&env_obstack);
308 obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
309 obstack_1grow (&env_obstack, 0);
310 option = XOBFINISH (&env_obstack, char *);
311 if (seen_o)
312 {
313 linker_output = option;
314 seen_o = false;
315 continue;
316 }
317
318 /* If we see -o, skip it and skip and record its argument. */
319 if (option[0] == '-' && option[1] == 'o')
320 {
321 if (option[2] == '\0')
322 seen_o = true;
323 else
324 linker_output = &option[2];
325 continue;
326 }
327
328 if (strcmp (option, "-save-temps") == 0)
329 debug = 1;
330 if (strcmp (option, "-v") == 0)
331 verbose = 1;
332
333 /* We've handled these LTO options, do not pass them on. */
334 if (strcmp (option, "-flto") == 0)
335 lto_mode = LTO_MODE_LTO;
336 else if (strncmp (option, "-fwhopr", 7) == 0)
337 {
338 lto_mode = LTO_MODE_WHOPR;
339 if (option[7] == '=')
340 {
341 parallel = atoi (option+8);
342 if (parallel <= 1)
343 parallel = 0;
344 }
345 }
346 else
347 *argv_ptr++ = option;
348 }
349
350 if (linker_output)
351 {
352 char *output_dir, *base, *name;
353
354 output_dir = xstrdup (linker_output);
355 base = output_dir;
356 for (name = base; *name; name++)
357 if (IS_DIR_SEPARATOR (*name))
358 base = name + 1;
359 *base = '\0';
360
361 linker_output = &linker_output[base - output_dir];
362 if (*output_dir == '\0')
363 {
364 static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
365 output_dir = current_dir;
366 }
367 *argv_ptr++ = "-dumpdir";
368 *argv_ptr++ = output_dir;
369
370 *argv_ptr++ = "-dumpbase";
371 }
372 else
373 argv_ptr--;
374
271 if (lto_mode == LTO_MODE_LTO) 375 if (lto_mode == LTO_MODE_LTO)
272 { 376 {
273 flto_out = make_temp_file (".lto.o"); 377 flto_out = make_temp_file (".lto.o");
274 *argv_ptr++ = "-o"; 378 if (linker_output)
275 *argv_ptr++ = flto_out; 379 argv_ptr[0] = linker_output;
380 argv_ptr[1] = "-o";
381 argv_ptr[2] = flto_out;
382 argv_ptr[3] = "-combine";
276 } 383 }
277 else if (lto_mode == LTO_MODE_WHOPR) 384 else if (lto_mode == LTO_MODE_WHOPR)
278 { 385 {
279 const char *list_option = "-fltrans-output-list="; 386 const char *list_option = "-fltrans-output-list=";
280 size_t list_option_len = strlen (list_option); 387 size_t list_option_len = strlen (list_option);
281 char *tmp; 388 char *tmp;
389
390 if (linker_output)
391 {
392 char *dumpbase = (char *) xmalloc (strlen (linker_output)
393 + sizeof(".wpa") + 1);
394 strcpy (dumpbase, linker_output);
395 strcat (dumpbase, ".wpa");
396 argv_ptr[0] = dumpbase;
397 }
282 398
283 ltrans_output_file = make_temp_file (".ltrans.out"); 399 ltrans_output_file = make_temp_file (".ltrans.out");
284 list_option_full = (char *) xmalloc (sizeof (char) * 400 list_option_full = (char *) xmalloc (sizeof (char) *
285 (strlen (ltrans_output_file) + list_option_len + 1)); 401 (strlen (ltrans_output_file) + list_option_len + 1));
286 tmp = list_option_full; 402 tmp = list_option_full;
287 403
288 *argv_ptr++ = tmp; 404 argv_ptr[1] = tmp;
289 strcpy (tmp, list_option); 405 strcpy (tmp, list_option);
290 tmp += list_option_len; 406 tmp += list_option_len;
291 strcpy (tmp, ltrans_output_file); 407 strcpy (tmp, ltrans_output_file);
292 408
293 *argv_ptr++ = "-fwpa"; 409 argv_ptr[2] = "-fwpa";
410 argv_ptr[3] = "-combine";
294 } 411 }
295 else 412 else
296 fatal ("invalid LTO mode"); 413 fatal ("invalid LTO mode");
297 414
298 /* Add inherited GCC options to the LTO back end command line. 415 /* Append the input objects and possible preceeding arguments. */
299 Filter out some obviously inappropriate options that will 416 for (i = 1; i < argc; ++i)
300 conflict with the options that we force above. We pass 417 argv_ptr[3 + i] = argv[i];
301 all of the remaining options on to LTO, and let it complain 418 argv_ptr[3 + i] = NULL;
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 i++;
320 }
321 else
322 /* Pass the option or argument to LTO. */
323 *argv_ptr++ = s;
324 }
325
326 *argv_ptr = NULL;
327 419
328 fork_execute (CONST_CAST (char **, new_argv)); 420 fork_execute (CONST_CAST (char **, new_argv));
329 free (new_argv);
330 new_argv = NULL;
331 421
332 if (lto_mode == LTO_MODE_LTO) 422 if (lto_mode == LTO_MODE_LTO)
333 { 423 {
334 printf("%s\n", flto_out); 424 printf("%s\n", flto_out);
335 free (flto_out); 425 free (flto_out);
336 flto_out = NULL; 426 flto_out = NULL;
337 } 427 }
338 else if (lto_mode == LTO_MODE_WHOPR) 428 else if (lto_mode == LTO_MODE_WHOPR)
339 { 429 {
340 FILE *stream = fopen (ltrans_output_file, "r"); 430 FILE *stream = fopen (ltrans_output_file, "r");
341 int c; 431 unsigned int nr = 0;
432 char **input_names = NULL;
433 char **output_names = NULL;
434 char *makefile = NULL;
435 FILE *mstream = NULL;
342 436
343 if (!stream) 437 if (!stream)
344 fatal_perror ("fopen: %s", ltrans_output_file); 438 fatal_perror ("fopen: %s", ltrans_output_file);
345 439
346 while ((c = getc (stream)) != EOF) 440 argv_ptr[1] = "-fltrans";
347 putc (c, stdout); 441
442 if (parallel)
443 {
444 makefile = make_temp_file (".mk");
445 mstream = fopen (makefile, "w");
446 }
447
448 for (;;)
449 {
450 const unsigned piece = 32;
451 char *output_name;
452 char *buf, *input_name = (char *)xmalloc (piece);
453 size_t len;
454
455 buf = input_name;
456 cont:
457 if (!fgets (buf, piece, stream))
458 break;
459 len = strlen (input_name);
460 if (input_name[len - 1] != '\n')
461 {
462 input_name = (char *)xrealloc (input_name, len + piece);
463 buf = input_name + len;
464 goto cont;
465 }
466 input_name[len - 1] = '\0';
467
468 if (input_name[0] == '*')
469 output_name = &input_name[1];
470 else
471 {
472 /* Otherwise, add FILES[I] to lto_execute_ltrans command line
473 and add the resulting file to LTRANS output list. */
474
475 /* Replace the .o suffix with a .ltrans.o suffix and write
476 the resulting name to the LTRANS output list. */
477 obstack_init (&env_obstack);
478 obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
479 obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
480 output_name = XOBFINISH (&env_obstack, char *);
481
482 if (linker_output)
483 {
484 char *dumpbase
485 = (char *) xmalloc (strlen (linker_output)
486 + sizeof(DUMPBASE_SUFFIX) + 1);
487 snprintf (dumpbase,
488 strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
489 "%s.ltrans%u", linker_output, nr);
490 argv_ptr[0] = dumpbase;
491 }
492
493 argv_ptr[2] = "-o";
494 argv_ptr[3] = output_name;
495 argv_ptr[4] = input_name;
496 argv_ptr[5] = NULL;
497
498 if (parallel)
499 {
500 fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
501 for (i = 1; new_argv[i] != NULL; ++i)
502 fprintf (mstream, " '%s'", new_argv[i]);
503 fprintf (mstream, "\n");
504 }
505 else
506 fork_execute (CONST_CAST (char **, new_argv));
507 }
508
509 nr++;
510 input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
511 output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
512 input_names[nr-1] = input_name;
513 output_names[nr-1] = output_name;
514 }
515 if (parallel)
516 {
517 struct pex_obj *pex;
518 char jobs[32];
519 fprintf (mstream, "all:");
520 for (i = 0; i < nr; ++i)
521 fprintf (mstream, " \\\n\t%s", output_names[i]);
522 fprintf (mstream, "\n");
523 fclose (mstream);
524 new_argv[0] = "make";
525 new_argv[1] = "-f";
526 new_argv[2] = makefile;
527 snprintf (jobs, 31, "-j%d", parallel);
528 new_argv[3] = jobs;
529 new_argv[4] = "all";
530 new_argv[5] = NULL;
531 pex = collect_execute (CONST_CAST (char **, new_argv));
532 collect_wait (new_argv[0], pex);
533 maybe_unlink_file (makefile);
534 }
535 for (i = 0; i < nr; ++i)
536 {
537 fputs (output_names[i], stdout);
538 putc ('\n', stdout);
539 maybe_unlink_file (input_names[i]);
540 free (input_names[i]);
541 }
542 free (output_names);
543 free (input_names);
348 fclose (stream); 544 fclose (stream);
349 maybe_unlink_file (ltrans_output_file); 545 maybe_unlink_file (ltrans_output_file);
350 free (list_option_full); 546 free (list_option_full);
351 } 547 }
352 else 548 else
353 fatal ("invalid LTO mode"); 549 fatal ("invalid LTO mode");
354 } 550
355 551 obstack_free (&env_obstack, NULL);
356
357 /* Parse the command line. Copy any unused argument to GCC_ARGV. ARGC is the
358 number of arguments. ARGV contains the arguments. */
359
360 static int
361 process_args (int argc, char *argv[], char *gcc_argv[])
362 {
363 int i;
364 int j = 0;
365
366 for (i = 1; i < argc; i ++)
367 {
368 if (! strcmp (argv[i], "-debug"))
369 debug = 1;
370 else if (! strcmp (argv[i], "-flto"))
371 lto_mode = LTO_MODE_LTO;
372 else if (! strcmp (argv[i], "-fwhopr"))
373 lto_mode = LTO_MODE_WHOPR;
374 else
375 {
376 gcc_argv[j] = argv[i];
377 j++;
378 }
379 }
380
381 return j;
382 } 552 }
383 553
384 554
385 /* Entry point. */ 555 /* Entry point. */
386 556
387 int 557 int
388 main (int argc, char *argv[]) 558 main (int argc, char *argv[])
389 { 559 {
390 char **gcc_argv;
391 int gcc_argc;
392
393 gcc_init_libintl (); 560 gcc_init_libintl ();
394 561
395 /* We may be called with all the arguments stored in some file and 562 /* We may be called with all the arguments stored in some file and
396 passed with @file. Expand them into argv before processing. */ 563 passed with @file. Expand them into argv before processing. */
397 expandargv (&argc, &argv); 564 expandargv (&argc, &argv);
398 gcc_argv = (char **) xcalloc (sizeof (char *), argc); 565 run_gcc (argc, argv);
399 gcc_argc = process_args (argc, argv, gcc_argv);
400 run_gcc (gcc_argc, gcc_argv);
401 free (gcc_argv);
402 566
403 return 0; 567 return 0;
404 } 568 }