--- /dev/null
+/* $Header$ */
+
+#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 *strrindex();
+
+static char ddump[128]; /* data label dump file */
+static char pdump[128]; /* procedure name dump file */
+static char tmpbufs[NTEMPS*2][128];
+
+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 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 int
+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 = strrindex(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) {
+ (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;
+ continue;
+ }
+ 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);
+ 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");
+ }
+
+ (void) strcpy(ddump, TMP_DIR);
+ (void) strcat(ddump, "/ego.dd.XXXXXX");
+ (void) mktemp(ddump);
+ (void) strcpy(pdump, TMP_DIR);
+ (void) strcat(pdump, "/ego.pd.XXXXXX");
+ (void) mktemp(pdump);
+
+ (void) strcpy(tmpbufs[0], TMP_DIR);
+ (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 = strrindex(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*/
+}