421 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			421 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id$ */
 | |
| 
 | |
| /* Driver program for the global optimizer. It might even become the global
 | |
|    optimizer itself one day ...
 | |
| */
 | |
| 
 | |
| #include <em_path.h>
 | |
| #include <signal.h>
 | |
| #include <system.h>
 | |
| 
 | |
| #define	IC	1
 | |
| #define CF	2
 | |
| #define IL	3
 | |
| #define CS	4
 | |
| #define SR	5
 | |
| #define UD	6
 | |
| #define LV	7
 | |
| #define RA	8
 | |
| #define SP	9
 | |
| #define BO	10
 | |
| #define CJ	11
 | |
| #define CA	12
 | |
| 
 | |
| static char *phnames[] = {
 | |
|   0,
 | |
|   "ic",
 | |
|   "cf",
 | |
|   "il",
 | |
|   "cs",
 | |
|   "sr",
 | |
|   "ud",
 | |
|   "lv",
 | |
|   "ra",
 | |
|   "sp",
 | |
|   "bo",
 | |
|   "cj",
 | |
|   "ca",
 | |
|   0
 | |
| };
 | |
| 
 | |
| #define MAXUPHASES	64		/* max # of phases to be run */
 | |
| #define MAXARGS		1024		/* mar # of args */
 | |
| #define NTEMPS		4		/* # of temporary files; not tunable */
 | |
| 
 | |
| extern char	*mktemp();
 | |
| extern char	*strcpy(), *strcat();
 | |
| extern char	*strrchr();
 | |
| 
 | |
| static char	ddump[128] = TMP_DIR;	/* data label dump file */
 | |
| static char	pdump[128] = TMP_DIR;	/* procedure name dump file */
 | |
| static char	tmpbufs[NTEMPS*2][128] = {
 | |
|   TMP_DIR
 | |
| };
 | |
| 
 | |
| static int O2phases[] = {		/* Passes for -O2 */
 | |
|   CJ, BO, SP, 0
 | |
| };
 | |
| 
 | |
| static int O3phases[] = {		/* Passes for -O3 */
 | |
|   CS, SR, CJ, BO, SP, UD, LV, RA, 0
 | |
| };
 | |
| 
 | |
| static int O4phases[] = {		/* Passes for -O4 */
 | |
|   IL, CF, CS, SR, CJ, BO, SP, UD, LV, RA, 0
 | |
| };
 | |
| 
 | |
| static int	*Ophase = &O2phases[0];	/* default : -O2 */
 | |
| 
 | |
| static int	nuphases;		/* # of phases specified by user */
 | |
| static int	uphases[MAXUPHASES+1];	/* phases to be run */
 | |
| 
 | |
| static int	nfiles = NTEMPS*2+1;	/* leave space for tempfilenames */
 | |
| static char	*phargs[MAXARGS+1];
 | |
| 
 | |
| static int	keeptemps = 0;
 | |
| 
 | |
| static char	**phase_args;
 | |
| static int	nphase_args;
 | |
| 
 | |
| static char	*opt_dir;
 | |
| static char	*prog_name;
 | |
| 
 | |
| static int	v_flag;
 | |
| 
 | |
| static void
 | |
| cleanup()
 | |
| {
 | |
|   /*	Cleanup temporaries */
 | |
| 
 | |
|   if (! keeptemps) {
 | |
| 	register int i;
 | |
| 
 | |
| 	for (i = NTEMPS*2; i > 0; i--) {
 | |
| 		register char	*f = phargs[i];
 | |
| 		if (f != 0 && *f != '\0' && *f != '-') (void) unlink(f);
 | |
| 	}
 | |
| 	if (ddump[0] != '\0') (void) unlink(ddump);
 | |
| 	if (pdump[0] != '\0') (void) unlink(pdump);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /*VARARGS1*/
 | |
| static void
 | |
| fatal(s, s2)
 | |
|   char	*s;
 | |
|   char	*s2;
 | |
| {
 | |
|   /*	A fatal error occurred; exit gracefully */
 | |
| 
 | |
|   fprint(STDERR, "%s: ", prog_name);
 | |
|   fprint(STDERR, s, s2);
 | |
|   fprint(STDERR, "\n");
 | |
|   cleanup();
 | |
|   sys_stop(S_EXIT);
 | |
|   /*NOTREACHED*/
 | |
| }
 | |
| 
 | |
| static void
 | |
| add_file(s)
 | |
|   char	*s;
 | |
| {
 | |
|   /*	Add an input file to the list */
 | |
| 
 | |
|   if (nfiles >= MAXARGS) fatal("too many files");
 | |
|   phargs[nfiles++] = s;
 | |
| }
 | |
| 
 | |
| static void
 | |
| add_uphase(p)
 | |
|   int	p;
 | |
| {
 | |
|   /*	Add an optimizer phase to the list of phases to run */
 | |
| 
 | |
|   if (nuphases >= MAXUPHASES) fatal("too many phases");
 | |
|   uphases[nuphases++] = p;
 | |
| }
 | |
| 
 | |
| static void
 | |
| catch()
 | |
| {
 | |
|   /*	Catch interrupts and exit gracefully */
 | |
| 
 | |
|   cleanup();
 | |
|   sys_stop(S_EXIT);
 | |
| }
 | |
| 
 | |
| static void
 | |
| old_infiles()
 | |
| {
 | |
|   /*	Remove old input files unless we have to keep them around. */
 | |
| 
 | |
|   register int i;
 | |
| 
 | |
|   if (phargs[1] == pdump || keeptemps) return;
 | |
| 
 | |
|   for (i = 1; i <= NTEMPS; i++) (void) unlink(phargs[i]);
 | |
| }
 | |
| 
 | |
| static void
 | |
| get_infiles()
 | |
| {
 | |
|   /*	Make output temps from previous phase input temps of next phase. */
 | |
| 
 | |
|   register int	i;
 | |
|   register char	**dst = &phargs[1];
 | |
|   register char	**src = &phargs[NTEMPS+1];
 | |
| 
 | |
|   for (i = 1; i <= NTEMPS; i++) {
 | |
| 	*dst++ = *src++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void
 | |
| new_outfiles()
 | |
| {
 | |
|   static int	tmpindex = 0;
 | |
|   static int	Bindex = 0;
 | |
|   static char	dig1 = '1';
 | |
|   static char	dig2 = '0';
 | |
|   register int	i;
 | |
|   register char	**dst = &phargs[NTEMPS+1];
 | |
| 
 | |
|   if (! Bindex) {
 | |
| 	Bindex = strrchr(tmpbufs[0], 'B') - tmpbufs[0];
 | |
|   }
 | |
|   for (i = 1; i <= NTEMPS; i++) {
 | |
| 	*dst = tmpbufs[tmpindex];
 | |
| 	(*dst)[Bindex-1] = dig2;
 | |
| 	(*dst)[Bindex] = dig1;
 | |
| 	tmpindex++;
 | |
| 	dst++;
 | |
|   }
 | |
|   if (tmpindex >= 2*NTEMPS) tmpindex = 0;
 | |
|   if (++dig1 > '9') {
 | |
| 	++dig2;
 | |
| 	dig1 = '0';
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void
 | |
| run_phase(phase)
 | |
|   int	phase;
 | |
| {
 | |
|   /*	Run one phase of the global optimizer; special cases are
 | |
| 	IC and CA.
 | |
|   */
 | |
|   static int flags_added;
 | |
|   register int	argc;
 | |
|   register int	i;
 | |
|   char	buf[256];
 | |
|   int	pid, status;
 | |
| 
 | |
|   phargs[0] = buf;
 | |
|   (void) strcpy(buf, opt_dir);
 | |
|   (void) strcat(buf, "/");
 | |
|   (void) strcat(buf, phnames[phase]);
 | |
| 
 | |
|   switch(phase) {
 | |
|   case IC:
 | |
| 	phargs[1] = pdump;
 | |
| 	phargs[2] = ddump;
 | |
| 	for (i = 3; i <= NTEMPS; i++) phargs[i] = "-";
 | |
| 	new_outfiles();
 | |
| 	argc = nfiles;
 | |
|   	phargs[argc] = 0;
 | |
| 	break;
 | |
| 
 | |
|   case CA:
 | |
| 	old_infiles();
 | |
| 	get_infiles();
 | |
| 	phargs[NTEMPS+1] = pdump;
 | |
| 	phargs[NTEMPS+2] = ddump;
 | |
| 	for (i = NTEMPS+3; i <= 2*NTEMPS; i++) phargs[i] = "-";
 | |
| 	argc = 2*NTEMPS+1;
 | |
|   	phargs[argc] = 0;
 | |
| 	break;
 | |
| 
 | |
|   default:
 | |
| 	old_infiles();
 | |
| 	get_infiles();
 | |
| 	new_outfiles();
 | |
| 	if (! flags_added) {
 | |
| 		flags_added = 1;
 | |
| 		argc = 2*NTEMPS+1;
 | |
| 		while (--nphase_args >= 0) {
 | |
| 			phargs[argc++] = *phase_args++;
 | |
| 		}
 | |
|   		phargs[argc] = 0;
 | |
| 	}
 | |
| 	break;
 | |
|   }
 | |
|   if ((pid = fork()) < 0) {
 | |
| 	fatal("Could not fork");
 | |
|   }
 | |
|   else if (pid == 0) {
 | |
| 	if (v_flag) {
 | |
| 		register int i = 0;
 | |
| 
 | |
| 		while (phargs[i]) {
 | |
| 			fprint(STDERR, "%s ", phargs[i]);
 | |
| 			i++;
 | |
| 		}
 | |
| 		fprint(STDERR, "\n");
 | |
| 	}
 | |
| 	(void) execv(phargs[0], phargs);
 | |
| 	fatal("Could not exec %s", phargs[0]);
 | |
| 	sys_stop(S_EXIT);
 | |
|   }
 | |
|   else {
 | |
| 	while (wait(&status) != pid) /* nothing */ ;
 | |
| 	if ((status & 0177) != 0) {
 | |
| 		fatal("%s got a unix signal", phargs[0]);
 | |
| 	}
 | |
| 	if (((status >> 8) & 0377) != 0) {
 | |
| 		cleanup();
 | |
| 		sys_stop(S_EXIT);
 | |
| 	}
 | |
|   }
 | |
| }
 | |
| 
 | |
| main(argc, argv)
 | |
|   int	argc;
 | |
|   char	*argv[];
 | |
| {
 | |
|   register int	i = 0;
 | |
| 
 | |
|   if (signal(SIGHUP, catch) == SIG_IGN) (void) signal(SIGHUP, SIG_IGN);
 | |
|   if (signal(SIGQUIT, catch) == SIG_IGN) (void) signal(SIGQUIT, SIG_IGN);
 | |
|   if (signal(SIGINT, catch) == SIG_IGN) (void) signal(SIGINT, SIG_IGN);
 | |
|   prog_name = argv[0];
 | |
|   phase_args = &argv[1];
 | |
|   while (--argc > 0) {
 | |
| 	argv++;
 | |
| 	if (argv[0][0] == '-') {
 | |
| 		switch(argv[0][1]) {
 | |
| 		case 'P':
 | |
| 			if (argv[0][2] == '\0') {
 | |
| 				opt_dir = argv[1];
 | |
| 				argc--;
 | |
| 				argv++;
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		case 't':
 | |
| 			if (argv[0][2] == '\0') {
 | |
| 				keeptemps = 1;
 | |
| 				/* no continue; IL also needs this */
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'v':
 | |
| 			v_flag = 1;
 | |
| 			break;
 | |
| 		case 'O':
 | |
| 			if (argv[0][2] == '2' || argv[0][2] == '\0') continue;
 | |
| 			if (argv[0][2] == '3') {
 | |
| 				Ophase = &O3phases[0];
 | |
| 				continue;
 | |
| 			}
 | |
| 			Ophase = &O4phases[0];
 | |
| 			continue;
 | |
| 		case 'I':
 | |
| 			if (! strcmp(&argv[0][1], "IL")) {
 | |
| 				add_uphase(IL);
 | |
| 				add_uphase(CF);
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'B':
 | |
| 			if (! strcmp(&argv[0][1], "BO")) {
 | |
| 				add_uphase(BO);
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'R':
 | |
| 			if (! strcmp(&argv[0][1], "RA")) {
 | |
| 				add_uphase(RA);
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'U':
 | |
| 			if (! strcmp(&argv[0][1], "UD")) {
 | |
| 				add_uphase(UD);
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'L':
 | |
| 			if (! strcmp(&argv[0][1], "LV")) {
 | |
| 				add_uphase(LV);
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'C':
 | |
| 			if (! strcmp(&argv[0][1], "CS")) {
 | |
| 				add_uphase(CS);
 | |
| 				continue;
 | |
| 			}
 | |
| 			if (! strcmp(&argv[0][1], "CJ")) {
 | |
| 				add_uphase(CJ);
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		case 'S':
 | |
| 			if (! strcmp(&argv[0][1], "SR")) {
 | |
| 				add_uphase(SR);
 | |
| 				continue;
 | |
| 			}
 | |
| 			if (! strcmp(&argv[0][1], "SP")) {
 | |
| 				add_uphase(SP);
 | |
| 				continue;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 		phase_args[i++] = argv[0];
 | |
| 	}
 | |
| 	else {
 | |
| 		add_file(argv[0]);
 | |
| 	}
 | |
|   }
 | |
|   phase_args[i] = 0;
 | |
|   nphase_args = i;
 | |
|   if (nuphases) Ophase = uphases;
 | |
| 
 | |
|   if (nfiles == 2*NTEMPS+1) {
 | |
| 	/* 2*NTEMPS+1 was the starting value; nothing to do */
 | |
| 	sys_stop(S_END);
 | |
|   }
 | |
| 
 | |
|   if (! opt_dir) {
 | |
| 	fatal("no correct -P flag given");
 | |
|   }
 | |
| 
 | |
|   if (keeptemps) {
 | |
| 	(void) strcpy(ddump, ".");
 | |
| 	(void) strcpy(pdump, ".");
 | |
| 	(void) strcpy(tmpbufs[0], ".");
 | |
|   }
 | |
|   (void) strcat(ddump, "/ego.dd.XXXXXX");
 | |
|   (void) mktemp(ddump);
 | |
|   (void) strcat(pdump, "/ego.pd.XXXXXX");
 | |
|   (void) mktemp(pdump);
 | |
| 
 | |
|   (void) strcat(tmpbufs[0], "/ego.A.BB.XXXXXX");
 | |
|   (void) mktemp(tmpbufs[0]);
 | |
|   for (i = 2*NTEMPS-1; i >= 1; i--) {
 | |
| 	(void) strcpy(tmpbufs[i], tmpbufs[0]);
 | |
|   }
 | |
|   i = strrchr(tmpbufs[0], 'A') - tmpbufs[0];
 | |
|   tmpbufs[0][i] = 'p'; tmpbufs[NTEMPS+0][i] = 'p';
 | |
|   tmpbufs[1][i] = 'd'; tmpbufs[NTEMPS+1][i] = 'd';
 | |
|   tmpbufs[2][i] = 'l'; tmpbufs[NTEMPS+2][i] = 'l';
 | |
|   tmpbufs[3][i] = 'b'; tmpbufs[NTEMPS+3][i] = 'b';
 | |
|   run_phase(IC);
 | |
|   run_phase(CF);
 | |
|   while (*Ophase) {
 | |
| 	run_phase(*Ophase++);
 | |
|   }
 | |
|   run_phase(CA);
 | |
|   cleanup();
 | |
|   sys_stop(S_END);
 | |
|   /*NOTREACHED*/
 | |
| }
 |