This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RFA/Patch: gcc.c retry


--retry-without-O will retry a failing compiler process after stripping
out -O command line arguments. Better name suggestions welcome.
The ICE_RETRY environment variable hack is still in so I can use it
without changing the bootstrap process, but if accepted --retry-without-Os
should be part of the bootstrap compiler flags.
It permits alpha-dec-osf4.0e to bootstrap snapshots with --enable-checking
when combine.c, cp/call.c, cp/errfn.c, cp/pt.c otherwise run out of swap
in cc1. Intent is to permit development compilers to bootstrap on resource
constrained machines or during optimizer instabilities so that the testsuite
can highlight problems.

Documentation missing at the moment.
Joseph Myers's suggestion to also automate producing .i or .ii files etc for
error reporting is of larger scope, but worth doing.

NB My prior employer has been taken over by CSC, does the prior corporate
assignment still apply or do I need to explicitly send in another?

2001-04-12  Rodney Brown  <RBrown64@csc.com.au>

	* gcc.c (execute): Add --retry-without-O to retry failing compiler
	processes after stripping -O flags.
	

*** gcc/gcc.c.orig	Tue Mar 27 19:00:47 2001
--- gcc/gcc.c	Tue Apr 10 17:04:50 2001
*************** static int target_help_flag;
*** 148,153 ****
--- 148,158 ----
  
  static int report_times;
  
+ /* Nonzero means retry compilations where the compiler exits unsuccessfully
+    after stripping -O arguments.  */
+ 
+ static int retry_without_flag = 0;
+ 
  /* Nonzero means write "temp" files in source directory
     and use the source file's name in them, and don't delete them.  */
  
*************** static void set_input			PARAMS ((const c
*** 270,275 ****
--- 275,282 ----
  static void init_gcc_specs              PARAMS ((struct obstack *,
  						 const char *,
  						 const char *));
+ static int retry_candidate		PARAMS ((const char **, int));
+ static const char ** new_argv_nooptimize	PARAMS ((const char **));
  
  /* Specs are strings containing lines, each of which (if not blank)
  is made up of a program name, and arguments separated by spaces.
*************** struct option_map option_map[] =
*** 878,883 ****
--- 885,891 ----
     {"--profile", "-p", 0},
     {"--profile-blocks", "-a", 0},
     {"--quiet", "-q", 0},
+    {"--retry-without-O", "--retry-without-O", 0},
     {"--save-temps", "-save-temps", 0},
     {"--shared", "-shared", 0},
     {"--silent", "-q", 0},
*************** add_prefix (pprefix, prefix, component, 
*** 2551,2556 ****
--- 2559,2597 ----
    (*prev) = pl;
  }
  
+ static int
+ retry_candidate (argv, n_commands)
+      const char **argv;
+      int n_commands;
+ {
+   if (!save_temps_flag && n_commands == 1 && argv != NULL
+     && (retry_without_flag || getenv ("ICE_RETRY") != NULL))
+     {
+       int i;
+ 
+       for (i = 0; argv[i] != NULL; i++)
+ 	if (strncmp (argv[i], "-O", 2) == 0)
+ 	    return 1;
+     }
+   return 0;
+ }
+ 
+ static const char **
+ new_argv_nooptimize(argv)
+      const char **argv;
+ {
+   const char **n_argv;
+   int i, j;
+ 
+   n_argv = (const char **) xmalloc (argbuf_index * sizeof (char *));
+   for (i = j = 0; argv[i] != NULL; i++)
+     if (strncmp (argv[i], "-O", 2) != 0)
+       n_argv[j++] = argv[i];
+   
+   n_argv[j] = NULL;
+   return n_argv;
+ }
+ 
  /* Execute the command specified by the arguments on the current line of spec.
     When using pipes, this includes several piped-together commands
     with `|' between them.
*************** execute ()
*** 2562,2567 ****
--- 2603,2609 ----
  {
    int i;
    int n_commands;		/* # of command.  */
+   int in_retry = 0;		/* retrying failed command */
    char *string;
    struct command
    {
*************** execute ()
*** 2610,2760 ****
  
    /* If -v, print what we are about to do, and maybe query.  */
  
!   if (verbose_flag)
      {
!       /* For help listings, put a blank line between sub-processes.  */
!       if (print_help_list)
! 	fputc ('\n', stderr);
! 
!       /* Print each piped command as a separate line.  */
!       for (i = 0; i < n_commands; i++)
  	{
! 	  const char *const *j;
  
! 	  for (j = commands[i].argv; *j; j++)
! 	    fprintf (stderr, " %s", *j);
  
! 	  /* Print a pipe symbol after all but the last command.  */
! 	  if (i + 1 != n_commands)
! 	    fprintf (stderr, " |");
! 	  fprintf (stderr, "\n");
! 	}
!       fflush (stderr);
  #ifdef DEBUG
!       notice ("\nGo ahead? (y or n) ");
!       fflush (stderr);
!       i = getchar ();
!       if (i != '\n')
! 	while (getchar () != '\n')
! 	  ;
  
!       if (i != 'y' && i != 'Y')
! 	return 0;
  #endif /* DEBUG */
!     }
  
!   /* Run each piped subprocess.  */
  
!   for (i = 0; i < n_commands; i++)
!     {
!       char *errmsg_fmt, *errmsg_arg;
!       const char *string = commands[i].argv[0];
  
!       /* For some bizarre reason, the second argument of execvp() is
! 	 char *const *, not const char *const *.  */
!       commands[i].pid = pexecute (string, (char *const *) commands[i].argv,
! 				  programname, temp_filename,
! 				  &errmsg_fmt, &errmsg_arg,
! 				  ((i == 0 ? PEXECUTE_FIRST : 0)
! 				   | (i + 1 == n_commands ? PEXECUTE_LAST : 0)
! 				   | (string == commands[i].prog
! 				      ? PEXECUTE_SEARCH : 0)
! 				   | (verbose_flag ? PEXECUTE_VERBOSE : 0)));
! 
!       if (commands[i].pid == -1)
! 	pfatal_pexecute (errmsg_fmt, errmsg_arg);
! 
!       if (string != commands[i].prog)
! 	free ((PTR) string);
!     }
! 
!   execution_count++;
! 
!   /* Wait for all the subprocesses to finish.
!      We don't care what order they finish in;
!      we know that N_COMMANDS waits will get them all.
!      Ignore subprocesses that we don't know about,
!      since they can be spawned by the process that exec'ed us.  */
  
!   {
!     int ret_code = 0;
  #ifdef HAVE_GETRUSAGE
!     struct timeval d;
!     double ut = 0.0, st = 0.0;
  #endif
  
!     for (i = 0; i < n_commands;)
!       {
! 	int j;
! 	int status;
! 	int pid;
! 
! 	pid = pwait (commands[i].pid, &status, 0);
! 	if (pid < 0)
! 	  abort ();
  
  #ifdef HAVE_GETRUSAGE
! 	if (report_times)
! 	  {
! 	    /* getrusage returns the total resource usage of all children
! 	       up to now.  Copy the previous values into prus, get the
! 	       current statistics, then take the difference.  */
! 
! 	    prus = rus;
! 	    getrusage (RUSAGE_CHILDREN, &rus);
! 	    d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
! 	    d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
! 	    ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
! 
! 	    d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
! 	    d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec;
! 	    st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
! 	  }
  #endif
  
! 	for (j = 0; j < n_commands; j++)
! 	  if (commands[j].pid == pid)
! 	    {
! 	      i++;
! 	      if (WIFSIGNALED (status))
  		{
  #ifdef SIGPIPE
! 		  /* SIGPIPE is a special case.  It happens in -pipe mode
! 		     when the compiler dies before the preprocessor is
! 		     done, or the assembler dies before the compiler is
! 		     done.  There's generally been an error already, and
! 		     this is just fallout.  So don't generate another error
! 		     unless we would otherwise have succeeded.  */
! 		  if (WTERMSIG (status) == SIGPIPE
! 		      && (signal_count || greatest_status >= MIN_FATAL_STATUS))
! 		    ;
! 		  else
  #endif
! 		    fatal ("\
  Internal error: %s (program %s)\n\
  Please submit a full bug report.\n\
  See %s for instructions.",
! 			   strsignal (WTERMSIG (status)), commands[j].prog,
! 			   GCCBUGURL);
! 		  signal_count++;
! 		  ret_code = -1;
! 		}
! 	      else if (WIFEXITED (status)
! 		       && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
! 		{
! 		  if (WEXITSTATUS (status) > greatest_status)
! 		    greatest_status = WEXITSTATUS (status);
! 		  ret_code = -1;
! 		}
  #ifdef HAVE_GETRUSAGE
! 	      if (report_times && ut + st != 0)
! 		notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st);
  #endif
! 	      break;
! 	    }
        }
!     return ret_code;
!   }
  }
  
  /* Find all the switches given to us
--- 2652,2835 ----
  
    /* If -v, print what we are about to do, and maybe query.  */
  
!   do
      {
!       if (verbose_flag || in_retry)
  	{
! 	  /* For help listings, put a blank line between sub-processes.  */
! 	  if (print_help_list)
! 	    fputc ('\n', stderr);
  
! 	  /* Print each piped command as a separate line.  */
! 	  for (i = 0; i < n_commands; i++)
! 	    {
! 	      const char *const *j;
  
! 	      for (j = commands[i].argv; *j; j++)
! 		fprintf (stderr, " %s", *j);
! 
! 	      /* Print a pipe symbol after all but the last command.  */
! 	      if (i + 1 != n_commands)
! 		fprintf (stderr, " |");
! 	      fprintf (stderr, "\n");
! 	    }
! 	  fflush (stderr);
  #ifdef DEBUG
! 	  notice ("\nGo ahead? (y or n) ");
! 	  fflush (stderr);
! 	  i = getchar ();
! 	  if (i != '\n')
! 	    while (getchar () != '\n')
! 	      ;
  
! 	  if (i != 'y' && i != 'Y')
! 	    return 0;
  #endif /* DEBUG */
! 	}
  
! 	in_retry = 0;
  
!       /* Run each piped subprocess.  */
  
!       for (i = 0; i < n_commands; i++)
! 	{
! 	  char *errmsg_fmt, *errmsg_arg;
! 	  const char *string = commands[i].argv[0];
  
! 	  /* For some bizarre reason, the second argument of execvp() is
! 	     char *const *, not const char *const *.  */
! 	  commands[i].pid = pexecute (string, (char *const *) commands[i].argv,
! 				      programname, temp_filename,
! 				      &errmsg_fmt, &errmsg_arg,
! 				      ((i == 0 ? PEXECUTE_FIRST : 0)
! 				       | (i + 1 == n_commands
! 					  ? PEXECUTE_LAST : 0)
! 				       | (string == commands[i].prog
! 					  ? PEXECUTE_SEARCH : 0)
! 				       | (verbose_flag
! 					  ? PEXECUTE_VERBOSE : 0)));
! 
! 	  if (commands[i].pid == -1)
! 	    pfatal_pexecute (errmsg_fmt, errmsg_arg);
! 
! 	  /* Defer free-ing commands[i].argv[0] == string to allow retry. */
! 	}
! 
!       execution_count++;
! 
!       /* Wait for all the subprocesses to finish.
! 	 We don't care what order they finish in;
! 	 we know that N_COMMANDS waits will get them all.
! 	 Ignore subprocesses that we don't know about,
! 	 since they can be spawned by the process that exec'ed us.  */
! 
!       {
! 	int ret_code = 0;
  #ifdef HAVE_GETRUSAGE
! 	struct timeval d;
! 	double ut = 0.0, st = 0.0;
  #endif
  
! 	for (i = 0; i < n_commands;)
! 	  {
! 	    int j;
! 	    int status;
! 	    int pid;
! 
! 	    pid = pwait (commands[i].pid, &status, 0);
! 	    if (pid < 0)
! 	      abort ();
  
  #ifdef HAVE_GETRUSAGE
! 	    if (report_times)
! 	      {
! 		/* getrusage returns the total resource usage of all children
! 		   up to now.  Copy the previous values into prus, get the
! 		   current statistics, then take the difference.  */
! 
! 		prus = rus;
! 		getrusage (RUSAGE_CHILDREN, &rus);
! 		d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
! 		d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
! 		ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
! 
! 		d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
! 		d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec;
! 		st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
! 	      }
  #endif
  
! 	    for (j = 0; j < n_commands; j++)
! 	      if (commands[j].pid == pid)
  		{
+ 		  i++;
+ 		  if (WIFSIGNALED (status))
+ 		    {
  #ifdef SIGPIPE
! 		      /* SIGPIPE is a special case.  It happens in -pipe mode
! 			 when the compiler dies before the preprocessor is
! 			 done, or the assembler dies before the compiler is
! 			 done.  There's generally been an error already, and
! 			 this is just fallout.  So don't generate another error
! 			 unless we would otherwise have succeeded.  */
! 		      if (WTERMSIG (status) == SIGPIPE
! 			  && (signal_count
! 			     || greatest_status >= MIN_FATAL_STATUS))
! 			;
! 		      else
  #endif
! 			fatal ("\
  Internal error: %s (program %s)\n\
  Please submit a full bug report.\n\
  See %s for instructions.",
! 			       strsignal (WTERMSIG (status)), commands[j].prog,
! 			       GCCBUGURL);
! 			if (retry_candidate (commands[j].argv, n_commands))
! 			  {
! 			    in_retry = 1;
! 			    commands[j].argv =
! 			      new_argv_nooptimize (commands[j].argv);
! 			  }
! 			else
! 			  {
! 		      signal_count++;
! 		      ret_code = -1;
! 		    }
! 		    }
! 		  else if (WIFEXITED (status)
! 			   && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
! 		    {
! 		      if (retry_candidate (commands[j].argv, n_commands))
! 			{
! 			  in_retry = 1;
! 			  commands[j].argv =
! 			    new_argv_nooptimize (commands[j].argv);
! 			}
! 		      else
! 			{
! 		      if (WEXITSTATUS (status) > greatest_status)
! 			greatest_status = WEXITSTATUS (status);
! 		      ret_code = -1;
! 		    }
! 		    }
  #ifdef HAVE_GETRUSAGE
! 		  if (report_times && ut + st != 0)
! 		    notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st);
  #endif
! 		  if (!in_retry && commands[j].argv[0] != commands[j].prog)
! 		    free ((PTR)commands[j].argv[0]);
! 		  break;
! 		}
! 	  }
! 	if (!in_retry)
! 	  {
! 	    if (commands[0].argv != &argbuf[0])
! 	      free ((PTR) commands[0].argv);
! 	    return ret_code;
! 	  }
        }
!     } while (in_retry);
!   return 0;
  }
  
  /* Find all the switches given to us
*************** display_help ()
*** 2895,2900 ****
--- 2970,2976 ----
    fputs (_("\
    -print-multi-lib         Display the mapping between command line options and\n\
                             multiple library search directories\n"), stdout);
+   fputs (_("  --retry-without-O        If the compiler aborts, retry without optimization\n"), stdout);
    fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
    fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
    fputs (_("  -Wl,<options>            Pass comma-separated <options> on to the linker\n"), stdout);
*************** process_command (argc, argv)
*** 3293,3298 ****
--- 3369,3376 ----
  	}
        else if (strncmp (argv[i], "-l", 2) == 0)
  	n_infiles++;
+       else if (strcmp (argv[i], "--retry-without-O") == 0)
+ 	retry_without_flag = 1;
        else if (strcmp (argv[i], "-save-temps") == 0)
  	{
  	  save_temps_flag = 1;
*************** process_command (argc, argv)
*** 3662,3667 ****
--- 3740,3747 ----
  	;
        else if (! strcmp (argv[i], "-print-multi-directory"))
  	;
+       else if (! strcmp (argv[i], "--retry-without-O"))
+ 	;
        else if (strcmp (argv[i], "-ftarget-help") == 0)
          {
             /* Create a dummy input file, so that we can pass --target-help on to


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]