comparison gcc/lto-wrapper.c @ 67:f6334be47118

update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 22 Mar 2011 17:18:12 +0900
parents b7f97abdc517
children 04ced10e8804
comparison
equal deleted inserted replaced
65:65488c3d617d 67:f6334be47118
30 $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto 30 $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto
31 31
32 The above will print something like 32 The above will print something like
33 /tmp/ccwbQ8B2.lto.o 33 /tmp/ccwbQ8B2.lto.o
34 34
35 If -fwhopr is used instead, more than one file might be produced 35 If WHOPR is used instead, more than one file might be produced
36 ./ccXj2DTk.lto.ltrans.o 36 ./ccXj2DTk.lto.ltrans.o
37 ./ccCJuXGv.lto.ltrans.o 37 ./ccCJuXGv.lto.ltrans.o
38 */ 38 */
39 39
40 #include "config.h" 40 #include "config.h"
41 #include "system.h" 41 #include "system.h"
42 #include "coretypes.h" 42 #include "coretypes.h"
43 #include "tm.h"
44 #include "intl.h" 43 #include "intl.h"
45 #include "libiberty.h"
46 #include "obstack.h" 44 #include "obstack.h"
47 45
48 int debug; /* true if -save-temps. */ 46 int debug; /* true if -save-temps. */
49 int verbose; /* true if -v. */ 47 int verbose; /* true if -v. */
50 48
58 static enum lto_mode_d lto_mode = LTO_MODE_NONE; 56 static enum lto_mode_d lto_mode = LTO_MODE_NONE;
59 57
60 static char *ltrans_output_file; 58 static char *ltrans_output_file;
61 static char *flto_out; 59 static char *flto_out;
62 static char *args_name; 60 static char *args_name;
61 static unsigned int nr;
62 static char **input_names;
63 static char **output_names;
64 static char *makefile;
63 65
64 static void maybe_unlink_file (const char *); 66 static void maybe_unlink_file (const char *);
65 67
66 /* Delete tempfiles and exit function. */ 68 /* Delete tempfiles. */
67 69
68 static void 70 static void
69 lto_wrapper_exit (int status) 71 lto_wrapper_cleanup (void)
70 { 72 {
71 static bool cleanup_done = false; 73 static bool cleanup_done = false;
72 if (!cleanup_done) 74 unsigned int i;
73 { 75
74 /* Setting cleanup_done prevents an infinite loop if one of the 76 if (cleanup_done)
75 calls to maybe_unlink_file fails. */ 77 return;
76 cleanup_done = true; 78
77 79 /* Setting cleanup_done prevents an infinite loop if one of the
78 if (ltrans_output_file) 80 calls to maybe_unlink_file fails. */
79 maybe_unlink_file (ltrans_output_file); 81 cleanup_done = true;
80 if (flto_out) 82
81 maybe_unlink_file (flto_out); 83 if (ltrans_output_file)
82 if (args_name) 84 maybe_unlink_file (ltrans_output_file);
83 maybe_unlink_file (args_name); 85 if (flto_out)
84 } 86 maybe_unlink_file (flto_out);
85 exit (status); 87 if (args_name)
88 maybe_unlink_file (args_name);
89 if (makefile)
90 maybe_unlink_file (makefile);
91 for (i = 0; i < nr; ++i)
92 {
93 maybe_unlink_file (input_names[i]);
94 if (output_names[i])
95 maybe_unlink_file (output_names[i]);
96 }
97 }
98
99 static void
100 fatal_signal (int signum)
101 {
102 signal (signum, SIG_DFL);
103 lto_wrapper_cleanup ();
104 /* Get the same signal again, this time not handled,
105 so its normal effect occurs. */
106 kill (getpid (), signum);
86 } 107 }
87 108
88 /* Just die. CMSGID is the error message. */ 109 /* Just die. CMSGID is the error message. */
89 110
90 static void __attribute__ ((format (printf, 1, 2))) 111 static void __attribute__ ((format (printf, 1, 2)))
96 fprintf (stderr, "lto-wrapper: "); 117 fprintf (stderr, "lto-wrapper: ");
97 vfprintf (stderr, _(cmsgid), ap); 118 vfprintf (stderr, _(cmsgid), ap);
98 fprintf (stderr, "\n"); 119 fprintf (stderr, "\n");
99 va_end (ap); 120 va_end (ap);
100 121
101 lto_wrapper_exit (FATAL_EXIT_CODE); 122 lto_wrapper_cleanup ();
123 exit (FATAL_EXIT_CODE);
102 } 124 }
103 125
104 126
105 /* Die when sys call fails. CMSGID is the error message. */ 127 /* Die when sys call fails. CMSGID is the error message. */
106 128
114 fprintf (stderr, "lto-wrapper: "); 136 fprintf (stderr, "lto-wrapper: ");
115 vfprintf (stderr, _(cmsgid), ap); 137 vfprintf (stderr, _(cmsgid), ap);
116 fprintf (stderr, ": %s\n", xstrerror (e)); 138 fprintf (stderr, ": %s\n", xstrerror (e));
117 va_end (ap); 139 va_end (ap);
118 140
119 lto_wrapper_exit (FATAL_EXIT_CODE); 141 lto_wrapper_cleanup ();
142 exit (FATAL_EXIT_CODE);
120 } 143 }
121 144
122 145
123 /* Execute a program, and wait for the reply. ARGV are the arguments. The 146 /* Execute a program, and wait for the reply. ARGV are the arguments. The
124 last one must be NULL. */ 147 last one must be NULL. */
206 static void 229 static void
207 maybe_unlink_file (const char *file) 230 maybe_unlink_file (const char *file)
208 { 231 {
209 if (! debug) 232 if (! debug)
210 { 233 {
211 if (unlink_if_ordinary (file)) 234 if (unlink_if_ordinary (file)
235 && errno != ENOENT)
212 fatal_perror ("deleting LTRANS file %s", file); 236 fatal_perror ("deleting LTRANS file %s", file);
213 } 237 }
214 else 238 else
215 fprintf (stderr, "[Leaving LTRANS %s]\n", file); 239 fprintf (stderr, "[Leaving LTRANS %s]\n", file);
216 } 240 }
246 270
247 pex = collect_execute (new_argv); 271 pex = collect_execute (new_argv);
248 collect_wait (new_argv[0], pex); 272 collect_wait (new_argv[0], pex);
249 273
250 maybe_unlink_file (args_name); 274 maybe_unlink_file (args_name);
275 args_name = NULL;
251 free (at_args); 276 free (at_args);
252 } 277 }
253 278
254 /* Template of LTRANS dumpbase suffix. */ 279 /* Template of LTRANS dumpbase suffix. */
255 #define DUMPBASE_SUFFIX ".ltrans18446744073709551615" 280 #define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
266 const char *linker_output = NULL; 291 const char *linker_output = NULL;
267 const char *collect_gcc_options, *collect_gcc; 292 const char *collect_gcc_options, *collect_gcc;
268 struct obstack env_obstack; 293 struct obstack env_obstack;
269 bool seen_o = false; 294 bool seen_o = false;
270 int parallel = 0; 295 int parallel = 0;
296 int jobserver = 0;
297 bool no_partition = false;
271 298
272 /* Get the driver and options. */ 299 /* Get the driver and options. */
273 collect_gcc = getenv ("COLLECT_GCC"); 300 collect_gcc = getenv ("COLLECT_GCC");
274 if (!collect_gcc) 301 if (!collect_gcc)
275 fatal ("environment variable COLLECT_GCC must be set"); 302 fatal ("environment variable COLLECT_GCC must be set");
328 if (strcmp (option, "-save-temps") == 0) 355 if (strcmp (option, "-save-temps") == 0)
329 debug = 1; 356 debug = 1;
330 if (strcmp (option, "-v") == 0) 357 if (strcmp (option, "-v") == 0)
331 verbose = 1; 358 verbose = 1;
332 359
360 if (strcmp (option, "-flto-partition=none") == 0)
361 no_partition = true;
333 /* We've handled these LTO options, do not pass them on. */ 362 /* We've handled these LTO options, do not pass them on. */
334 if (strcmp (option, "-flto") == 0) 363 if (strncmp (option, "-flto=", 6) == 0
335 lto_mode = LTO_MODE_LTO; 364 || !strcmp (option, "-flto"))
336 else if (strncmp (option, "-fwhopr", 7) == 0)
337 { 365 {
338 lto_mode = LTO_MODE_WHOPR; 366 lto_mode = LTO_MODE_WHOPR;
339 if (option[7] == '=') 367 if (option[5] == '=')
340 { 368 {
341 parallel = atoi (option+8); 369 if (!strcmp (option + 6, "jobserver"))
342 if (parallel <= 1) 370 {
343 parallel = 0; 371 jobserver = 1;
372 parallel = 1;
373 }
374 else
375 {
376 parallel = atoi (option + 6);
377 if (parallel <= 1)
378 parallel = 0;
379 }
344 } 380 }
345 } 381 }
346 else 382 else
347 *argv_ptr++ = option; 383 *argv_ptr++ = option;
348 } 384 }
385 if (no_partition)
386 {
387 lto_mode = LTO_MODE_LTO;
388 jobserver = 0;
389 parallel = 0;
390 }
349 391
350 if (linker_output) 392 if (linker_output)
351 { 393 {
352 char *output_dir, *base, *name; 394 char *output_dir, *base, *name;
395 bool bit_bucket = strcmp (linker_output, HOST_BIT_BUCKET) == 0;
353 396
354 output_dir = xstrdup (linker_output); 397 output_dir = xstrdup (linker_output);
355 base = output_dir; 398 base = output_dir;
356 for (name = base; *name; name++) 399 for (name = base; *name; name++)
357 if (IS_DIR_SEPARATOR (*name)) 400 if (IS_DIR_SEPARATOR (*name))
362 if (*output_dir == '\0') 405 if (*output_dir == '\0')
363 { 406 {
364 static char current_dir[] = { '.', DIR_SEPARATOR, '\0' }; 407 static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
365 output_dir = current_dir; 408 output_dir = current_dir;
366 } 409 }
367 *argv_ptr++ = "-dumpdir"; 410 if (!bit_bucket)
368 *argv_ptr++ = output_dir; 411 {
412 *argv_ptr++ = "-dumpdir";
413 *argv_ptr++ = output_dir;
414 }
369 415
370 *argv_ptr++ = "-dumpbase"; 416 *argv_ptr++ = "-dumpbase";
371 } 417 }
372 else 418 else
373 argv_ptr--; 419 argv_ptr--;
377 flto_out = make_temp_file (".lto.o"); 423 flto_out = make_temp_file (".lto.o");
378 if (linker_output) 424 if (linker_output)
379 argv_ptr[0] = linker_output; 425 argv_ptr[0] = linker_output;
380 argv_ptr[1] = "-o"; 426 argv_ptr[1] = "-o";
381 argv_ptr[2] = flto_out; 427 argv_ptr[2] = flto_out;
382 argv_ptr[3] = "-combine"; 428 }
383 } 429 else
384 else if (lto_mode == LTO_MODE_WHOPR)
385 { 430 {
386 const char *list_option = "-fltrans-output-list="; 431 const char *list_option = "-fltrans-output-list=";
387 size_t list_option_len = strlen (list_option); 432 size_t list_option_len = strlen (list_option);
388 char *tmp; 433 char *tmp;
389 434
390 if (linker_output) 435 if (linker_output)
391 { 436 {
392 char *dumpbase = (char *) xmalloc (strlen (linker_output) 437 char *dumpbase = (char *) xmalloc (strlen (linker_output)
393 + sizeof(".wpa") + 1); 438 + sizeof (".wpa") + 1);
394 strcpy (dumpbase, linker_output); 439 strcpy (dumpbase, linker_output);
395 strcat (dumpbase, ".wpa"); 440 strcat (dumpbase, ".wpa");
396 argv_ptr[0] = dumpbase; 441 argv_ptr[0] = dumpbase;
397 } 442 }
398 443
399 ltrans_output_file = make_temp_file (".ltrans.out"); 444 if (linker_output && debug)
445 {
446 ltrans_output_file = (char *) xmalloc (strlen (linker_output)
447 + sizeof (".ltrans.out") + 1);
448 strcpy (ltrans_output_file, linker_output);
449 strcat (ltrans_output_file, ".ltrans.out");
450 }
451 else
452 ltrans_output_file = make_temp_file (".ltrans.out");
400 list_option_full = (char *) xmalloc (sizeof (char) * 453 list_option_full = (char *) xmalloc (sizeof (char) *
401 (strlen (ltrans_output_file) + list_option_len + 1)); 454 (strlen (ltrans_output_file) + list_option_len + 1));
402 tmp = list_option_full; 455 tmp = list_option_full;
403 456
404 argv_ptr[1] = tmp; 457 argv_ptr[1] = tmp;
405 strcpy (tmp, list_option); 458 strcpy (tmp, list_option);
406 tmp += list_option_len; 459 tmp += list_option_len;
407 strcpy (tmp, ltrans_output_file); 460 strcpy (tmp, ltrans_output_file);
408 461
409 argv_ptr[2] = "-fwpa"; 462 argv_ptr[2] = "-fwpa";
410 argv_ptr[3] = "-combine"; 463 }
411 }
412 else
413 fatal ("invalid LTO mode");
414 464
415 /* Append the input objects and possible preceeding arguments. */ 465 /* Append the input objects and possible preceeding arguments. */
416 for (i = 1; i < argc; ++i) 466 for (i = 1; i < argc; ++i)
417 argv_ptr[3 + i] = argv[i]; 467 argv_ptr[2 + i] = argv[i];
418 argv_ptr[3 + i] = NULL; 468 argv_ptr[2 + i] = NULL;
419 469
420 fork_execute (CONST_CAST (char **, new_argv)); 470 fork_execute (CONST_CAST (char **, new_argv));
421 471
422 if (lto_mode == LTO_MODE_LTO) 472 if (lto_mode == LTO_MODE_LTO)
423 { 473 {
424 printf("%s\n", flto_out); 474 printf("%s\n", flto_out);
425 free (flto_out); 475 free (flto_out);
426 flto_out = NULL; 476 flto_out = NULL;
427 } 477 }
428 else if (lto_mode == LTO_MODE_WHOPR) 478 else
429 { 479 {
430 FILE *stream = fopen (ltrans_output_file, "r"); 480 FILE *stream = fopen (ltrans_output_file, "r");
431 unsigned int nr = 0;
432 char **input_names = NULL;
433 char **output_names = NULL;
434 char *makefile = NULL;
435 FILE *mstream = NULL; 481 FILE *mstream = NULL;
436 482
437 if (!stream) 483 if (!stream)
438 fatal_perror ("fopen: %s", ltrans_output_file); 484 fatal_perror ("fopen: %s", ltrans_output_file);
439 485
440 argv_ptr[1] = "-fltrans"; 486 /* Parse the list of LTRANS inputs from the WPA stage. */
441 487 nr = 0;
442 if (parallel)
443 {
444 makefile = make_temp_file (".mk");
445 mstream = fopen (makefile, "w");
446 }
447
448 for (;;) 488 for (;;)
449 { 489 {
450 const unsigned piece = 32; 490 const unsigned piece = 32;
451 char *output_name; 491 char *output_name = NULL;
452 char *buf, *input_name = (char *)xmalloc (piece); 492 char *buf, *input_name = (char *)xmalloc (piece);
453 size_t len; 493 size_t len;
454 494
455 buf = input_name; 495 buf = input_name;
456 cont: 496 cont:
465 } 505 }
466 input_name[len - 1] = '\0'; 506 input_name[len - 1] = '\0';
467 507
468 if (input_name[0] == '*') 508 if (input_name[0] == '*')
469 output_name = &input_name[1]; 509 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 510
509 nr++; 511 nr++;
510 input_names = (char **)xrealloc (input_names, nr * sizeof (char *)); 512 input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
511 output_names = (char **)xrealloc (output_names, nr * sizeof (char *)); 513 output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
512 input_names[nr-1] = input_name; 514 input_names[nr-1] = input_name;
513 output_names[nr-1] = output_name; 515 output_names[nr-1] = output_name;
514 } 516 }
517 fclose (stream);
518 maybe_unlink_file (ltrans_output_file);
519 ltrans_output_file = NULL;
520
521 if (parallel)
522 {
523 makefile = make_temp_file (".mk");
524 mstream = fopen (makefile, "w");
525 }
526
527 /* Execute the LTRANS stage for each input file (or prepare a
528 makefile to invoke this in parallel). */
529 for (i = 0; i < nr; ++i)
530 {
531 char *output_name;
532 char *input_name = input_names[i];
533 /* If it's a pass-through file do nothing. */
534 if (output_names[i])
535 continue;
536
537 /* Replace the .o suffix with a .ltrans.o suffix and write
538 the resulting name to the LTRANS output list. */
539 obstack_init (&env_obstack);
540 obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
541 obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
542 output_name = XOBFINISH (&env_obstack, char *);
543
544 /* Adjust the dumpbase if the linker output file was seen. */
545 if (linker_output)
546 {
547 char *dumpbase
548 = (char *) xmalloc (strlen (linker_output)
549 + sizeof(DUMPBASE_SUFFIX) + 1);
550 snprintf (dumpbase,
551 strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
552 "%s.ltrans%u", linker_output, i);
553 argv_ptr[0] = dumpbase;
554 }
555
556 argv_ptr[1] = "-fltrans";
557 argv_ptr[2] = "-o";
558 argv_ptr[3] = output_name;
559 argv_ptr[4] = input_name;
560 argv_ptr[5] = NULL;
561 if (parallel)
562 {
563 fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
564 for (j = 1; new_argv[j] != NULL; ++j)
565 fprintf (mstream, " '%s'", new_argv[j]);
566 fprintf (mstream, "\n");
567 }
568 else
569 fork_execute (CONST_CAST (char **, new_argv));
570
571 output_names[i] = output_name;
572 }
515 if (parallel) 573 if (parallel)
516 { 574 {
517 struct pex_obj *pex; 575 struct pex_obj *pex;
518 char jobs[32]; 576 char jobs[32];
577
519 fprintf (mstream, "all:"); 578 fprintf (mstream, "all:");
520 for (i = 0; i < nr; ++i) 579 for (i = 0; i < nr; ++i)
521 fprintf (mstream, " \\\n\t%s", output_names[i]); 580 fprintf (mstream, " \\\n\t%s", output_names[i]);
522 fprintf (mstream, "\n"); 581 fprintf (mstream, "\n");
523 fclose (mstream); 582 fclose (mstream);
524 new_argv[0] = "make"; 583 if (!jobserver)
584 {
585 /* Avoid passing --jobserver-fd= and similar flags
586 unless jobserver mode is explicitly enabled. */
587 putenv (xstrdup ("MAKEFLAGS="));
588 putenv (xstrdup ("MFLAGS="));
589 }
590 new_argv[0] = getenv ("MAKE");
591 if (!new_argv[0])
592 new_argv[0] = "make";
525 new_argv[1] = "-f"; 593 new_argv[1] = "-f";
526 new_argv[2] = makefile; 594 new_argv[2] = makefile;
527 snprintf (jobs, 31, "-j%d", parallel); 595 i = 3;
528 new_argv[3] = jobs; 596 if (!jobserver)
529 new_argv[4] = "all"; 597 {
530 new_argv[5] = NULL; 598 snprintf (jobs, 31, "-j%d", parallel);
599 new_argv[i++] = jobs;
600 }
601 new_argv[i++] = "all";
602 new_argv[i++] = NULL;
531 pex = collect_execute (CONST_CAST (char **, new_argv)); 603 pex = collect_execute (CONST_CAST (char **, new_argv));
532 collect_wait (new_argv[0], pex); 604 collect_wait (new_argv[0], pex);
533 maybe_unlink_file (makefile); 605 maybe_unlink_file (makefile);
606 makefile = NULL;
534 } 607 }
535 for (i = 0; i < nr; ++i) 608 for (i = 0; i < nr; ++i)
536 { 609 {
537 fputs (output_names[i], stdout); 610 fputs (output_names[i], stdout);
538 putc ('\n', stdout); 611 putc ('\n', stdout);
539 maybe_unlink_file (input_names[i]); 612 maybe_unlink_file (input_names[i]);
540 free (input_names[i]); 613 free (input_names[i]);
541 } 614 }
615 nr = 0;
542 free (output_names); 616 free (output_names);
543 free (input_names); 617 free (input_names);
544 fclose (stream);
545 maybe_unlink_file (ltrans_output_file);
546 free (list_option_full); 618 free (list_option_full);
547 } 619 }
548 else
549 fatal ("invalid LTO mode");
550 620
551 obstack_free (&env_obstack, NULL); 621 obstack_free (&env_obstack, NULL);
552 } 622 }
553 623
554 624
556 626
557 int 627 int
558 main (int argc, char *argv[]) 628 main (int argc, char *argv[])
559 { 629 {
560 gcc_init_libintl (); 630 gcc_init_libintl ();
631
632 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
633 signal (SIGINT, fatal_signal);
634 #ifdef SIGHUP
635 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
636 signal (SIGHUP, fatal_signal);
637 #endif
638 if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
639 signal (SIGTERM, fatal_signal);
640 #ifdef SIGPIPE
641 if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
642 signal (SIGPIPE, fatal_signal);
643 #endif
644 #ifdef SIGCHLD
645 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
646 receive the signal. A different setting is inheritable */
647 signal (SIGCHLD, SIG_DFL);
648 #endif
561 649
562 /* We may be called with all the arguments stored in some file and 650 /* We may be called with all the arguments stored in some file and
563 passed with @file. Expand them into argv before processing. */ 651 passed with @file. Expand them into argv before processing. */
564 expandargv (&argc, &argv); 652 expandargv (&argc, &argv);
565 run_gcc (argc, argv); 653 run_gcc (argc, argv);