/* $Id$ */ /* Driver program for the global optimizer. It might even become the global optimizer itself one day ... */ #include #include #include #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*/ }