Pristine Ack-5.5
[Ack-5.5.git] / util / ego / em_ego / em_ego.c
1 /* $Id: em_ego.c,v 1.6 1994/06/24 10:23:30 ceriel Exp $ */
2
3 /* Driver program for the global optimizer. It might even become the global
4    optimizer itself one day ...
5 */
6
7 #include <em_path.h>
8 #include <signal.h>
9 #include <system.h>
10
11 #define IC      1
12 #define CF      2
13 #define IL      3
14 #define CS      4
15 #define SR      5
16 #define UD      6
17 #define LV      7
18 #define RA      8
19 #define SP      9
20 #define BO      10
21 #define CJ      11
22 #define CA      12
23
24 static char *phnames[] = {
25   0,
26   "ic",
27   "cf",
28   "il",
29   "cs",
30   "sr",
31   "ud",
32   "lv",
33   "ra",
34   "sp",
35   "bo",
36   "cj",
37   "ca",
38   0
39 };
40
41 #define MAXUPHASES      64              /* max # of phases to be run */
42 #define MAXARGS         1024            /* mar # of args */
43 #define NTEMPS          4               /* # of temporary files; not tunable */
44
45 extern char     *mktemp();
46 extern char     *strcpy(), *strcat();
47 extern char     *strrindex();
48
49 static char     ddump[128] = TMP_DIR;   /* data label dump file */
50 static char     pdump[128] = TMP_DIR;   /* procedure name dump file */
51 static char     tmpbufs[NTEMPS*2][128] = {
52   TMP_DIR
53 };
54
55 static int O2phases[] = {               /* Passes for -O2 */
56   CJ, BO, SP, 0
57 };
58
59 static int O3phases[] = {               /* Passes for -O3 */
60   CS, SR, CJ, BO, SP, UD, LV, RA, 0
61 };
62
63 static int O4phases[] = {               /* Passes for -O4 */
64   IL, CF, CS, SR, CJ, BO, SP, UD, LV, RA, 0
65 };
66
67 static int      *Ophase = &O2phases[0]; /* default : -O2 */
68
69 static int      nuphases;               /* # of phases specified by user */
70 static int      uphases[MAXUPHASES+1];  /* phases to be run */
71
72 static int      nfiles = NTEMPS*2+1;    /* leave space for tempfilenames */
73 static char     *phargs[MAXARGS+1];
74
75 static int      keeptemps = 0;
76
77 static char     **phase_args;
78 static int      nphase_args;
79
80 static char     *opt_dir;
81 static char     *prog_name;
82
83 static int      v_flag;
84
85 static void
86 cleanup()
87 {
88   /*    Cleanup temporaries */
89
90   if (! keeptemps) {
91         register int i;
92
93         for (i = NTEMPS*2; i > 0; i--) {
94                 register char   *f = phargs[i];
95                 if (f != 0 && *f != '\0' && *f != '-') (void) unlink(f);
96         }
97         if (ddump[0] != '\0') (void) unlink(ddump);
98         if (pdump[0] != '\0') (void) unlink(pdump);
99   }
100 }
101
102 /*VARARGS1*/
103 static void
104 fatal(s, s2)
105   char  *s;
106   char  *s2;
107 {
108   /*    A fatal error occurred; exit gracefully */
109
110   fprint(STDERR, "%s: ", prog_name);
111   fprint(STDERR, s, s2);
112   fprint(STDERR, "\n");
113   cleanup();
114   sys_stop(S_EXIT);
115   /*NOTREACHED*/
116 }
117
118 static void
119 add_file(s)
120   char  *s;
121 {
122   /*    Add an input file to the list */
123
124   if (nfiles >= MAXARGS) fatal("too many files");
125   phargs[nfiles++] = s;
126 }
127
128 static void
129 add_uphase(p)
130   int   p;
131 {
132   /*    Add an optimizer phase to the list of phases to run */
133
134   if (nuphases >= MAXUPHASES) fatal("too many phases");
135   uphases[nuphases++] = p;
136 }
137
138 static void
139 catch()
140 {
141   /*    Catch interrupts and exit gracefully */
142
143   cleanup();
144   sys_stop(S_EXIT);
145 }
146
147 static void
148 old_infiles()
149 {
150   /*    Remove old input files unless we have to keep them around. */
151
152   register int i;
153
154   if (phargs[1] == pdump || keeptemps) return;
155
156   for (i = 1; i <= NTEMPS; i++) (void) unlink(phargs[i]);
157 }
158
159 static void
160 get_infiles()
161 {
162   /*    Make output temps from previous phase input temps of next phase. */
163
164   register int  i;
165   register char **dst = &phargs[1];
166   register char **src = &phargs[NTEMPS+1];
167
168   for (i = 1; i <= NTEMPS; i++) {
169         *dst++ = *src++;
170   }
171 }
172
173 static void
174 new_outfiles()
175 {
176   static int    tmpindex = 0;
177   static int    Bindex = 0;
178   static char   dig1 = '1';
179   static char   dig2 = '0';
180   register int  i;
181   register char **dst = &phargs[NTEMPS+1];
182
183   if (! Bindex) {
184         Bindex = strrindex(tmpbufs[0], 'B') - tmpbufs[0];
185   }
186   for (i = 1; i <= NTEMPS; i++) {
187         *dst = tmpbufs[tmpindex];
188         (*dst)[Bindex-1] = dig2;
189         (*dst)[Bindex] = dig1;
190         tmpindex++;
191         dst++;
192   }
193   if (tmpindex >= 2*NTEMPS) tmpindex = 0;
194   if (++dig1 > '9') {
195         ++dig2;
196         dig1 = '0';
197   }
198 }
199
200 static void
201 run_phase(phase)
202   int   phase;
203 {
204   /*    Run one phase of the global optimizer; special cases are
205         IC and CA.
206   */
207   static int flags_added;
208   register int  argc;
209   register int  i;
210   char  buf[256];
211   int   pid, status;
212
213   phargs[0] = buf;
214   (void) strcpy(buf, opt_dir);
215   (void) strcat(buf, "/");
216   (void) strcat(buf, phnames[phase]);
217
218   switch(phase) {
219   case IC:
220         phargs[1] = pdump;
221         phargs[2] = ddump;
222         for (i = 3; i <= NTEMPS; i++) phargs[i] = "-";
223         new_outfiles();
224         argc = nfiles;
225         phargs[argc] = 0;
226         break;
227
228   case CA:
229         old_infiles();
230         get_infiles();
231         phargs[NTEMPS+1] = pdump;
232         phargs[NTEMPS+2] = ddump;
233         for (i = NTEMPS+3; i <= 2*NTEMPS; i++) phargs[i] = "-";
234         argc = 2*NTEMPS+1;
235         phargs[argc] = 0;
236         break;
237
238   default:
239         old_infiles();
240         get_infiles();
241         new_outfiles();
242         if (! flags_added) {
243                 flags_added = 1;
244                 argc = 2*NTEMPS+1;
245                 while (--nphase_args >= 0) {
246                         phargs[argc++] = *phase_args++;
247                 }
248                 phargs[argc] = 0;
249         }
250         break;
251   }
252   if ((pid = fork()) < 0) {
253         fatal("Could not fork");
254   }
255   else if (pid == 0) {
256         if (v_flag) {
257                 register int i = 0;
258
259                 while (phargs[i]) {
260                         fprint(STDERR, "%s ", phargs[i]);
261                         i++;
262                 }
263                 fprint(STDERR, "\n");
264         }
265         (void) execv(phargs[0], phargs);
266         fatal("Could not exec %s", phargs[0]);
267         sys_stop(S_EXIT);
268   }
269   else {
270         while (wait(&status) != pid) /* nothing */ ;
271         if ((status & 0177) != 0) {
272                 fatal("%s got a unix signal", phargs[0]);
273         }
274         if (((status >> 8) & 0377) != 0) {
275                 cleanup();
276                 sys_stop(S_EXIT);
277         }
278   }
279 }
280
281 main(argc, argv)
282   int   argc;
283   char  *argv[];
284 {
285   register int  i = 0;
286
287   if (signal(SIGHUP, catch) == SIG_IGN) (void) signal(SIGHUP, SIG_IGN);
288   if (signal(SIGQUIT, catch) == SIG_IGN) (void) signal(SIGQUIT, SIG_IGN);
289   if (signal(SIGINT, catch) == SIG_IGN) (void) signal(SIGINT, SIG_IGN);
290   prog_name = argv[0];
291   phase_args = &argv[1];
292   while (--argc > 0) {
293         argv++;
294         if (argv[0][0] == '-') {
295                 switch(argv[0][1]) {
296                 case 'P':
297                         if (argv[0][2] == '\0') {
298                                 opt_dir = argv[1];
299                                 argc--;
300                                 argv++;
301                                 continue;
302                         }
303                         break;
304                 case 't':
305                         if (argv[0][2] == '\0') {
306                                 keeptemps = 1;
307                                 /* no continue; IL also needs this */
308                         }
309                         break;
310                 case 'v':
311                         v_flag = 1;
312                         break;
313                 case 'O':
314                         if (argv[0][2] == '2' || argv[0][2] == '\0') continue;
315                         if (argv[0][2] == '3') {
316                                 Ophase = &O3phases[0];
317                                 continue;
318                         }
319                         Ophase = &O4phases[0];
320                         continue;
321                 case 'I':
322                         if (! strcmp(&argv[0][1], "IL")) {
323                                 add_uphase(IL);
324                                 add_uphase(CF);
325                                 continue;
326                         }
327                         break;
328                 case 'B':
329                         if (! strcmp(&argv[0][1], "BO")) {
330                                 add_uphase(BO);
331                                 continue;
332                         }
333                         break;
334                 case 'R':
335                         if (! strcmp(&argv[0][1], "RA")) {
336                                 add_uphase(RA);
337                                 continue;
338                         }
339                         break;
340                 case 'U':
341                         if (! strcmp(&argv[0][1], "UD")) {
342                                 add_uphase(UD);
343                                 continue;
344                         }
345                         break;
346                 case 'L':
347                         if (! strcmp(&argv[0][1], "LV")) {
348                                 add_uphase(LV);
349                                 continue;
350                         }
351                         break;
352                 case 'C':
353                         if (! strcmp(&argv[0][1], "CS")) {
354                                 add_uphase(CS);
355                                 continue;
356                         }
357                         if (! strcmp(&argv[0][1], "CJ")) {
358                                 add_uphase(CJ);
359                                 continue;
360                         }
361                         break;
362                 case 'S':
363                         if (! strcmp(&argv[0][1], "SR")) {
364                                 add_uphase(SR);
365                                 continue;
366                         }
367                         if (! strcmp(&argv[0][1], "SP")) {
368                                 add_uphase(SP);
369                                 continue;
370                         }
371                         break;
372                 }
373                 phase_args[i++] = argv[0];
374         }
375         else {
376                 add_file(argv[0]);
377         }
378   }
379   phase_args[i] = 0;
380   nphase_args = i;
381   if (nuphases) Ophase = uphases;
382
383   if (nfiles == 2*NTEMPS+1) {
384         /* 2*NTEMPS+1 was the starting value; nothing to do */
385         sys_stop(S_END);
386   }
387
388   if (! opt_dir) {
389         fatal("no correct -P flag given");
390   }
391
392   if (keeptemps) {
393         (void) strcpy(ddump, ".");
394         (void) strcpy(pdump, ".");
395         (void) strcpy(tmpbufs[0], ".");
396   }
397   (void) strcat(ddump, "/ego.dd.XXXXXX");
398   (void) mktemp(ddump);
399   (void) strcat(pdump, "/ego.pd.XXXXXX");
400   (void) mktemp(pdump);
401
402   (void) strcat(tmpbufs[0], "/ego.A.BB.XXXXXX");
403   (void) mktemp(tmpbufs[0]);
404   for (i = 2*NTEMPS-1; i >= 1; i--) {
405         (void) strcpy(tmpbufs[i], tmpbufs[0]);
406   }
407   i = strrindex(tmpbufs[0], 'A') - tmpbufs[0];
408   tmpbufs[0][i] = 'p'; tmpbufs[NTEMPS+0][i] = 'p';
409   tmpbufs[1][i] = 'd'; tmpbufs[NTEMPS+1][i] = 'd';
410   tmpbufs[2][i] = 'l'; tmpbufs[NTEMPS+2][i] = 'l';
411   tmpbufs[3][i] = 'b'; tmpbufs[NTEMPS+3][i] = 'b';
412   run_phase(IC);
413   run_phase(CF);
414   while (*Ophase) {
415         run_phase(*Ophase++);
416   }
417   run_phase(CA);
418   cleanup();
419   sys_stop(S_END);
420   /*NOTREACHED*/
421 }