Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / cg / codegen.c
1 #ifndef NORCSID
2 static char rcsid[] = "$Id: codegen.c,v 2.14 1994/06/24 13:23:19 ceriel Exp $";
3 #endif
4
5 #include "assert.h"
6 #include "param.h"
7 #include "tables.h"
8 #include "types.h"
9 #include <cg_pattern.h>
10 #include "data.h"
11 #include "result.h"
12 #include "state.h"
13 #include "equiv.h"
14 #include "extern.h"
15
16 /*
17  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
18  * See the copyright notice in the ACK home directory, in the file "Copyright".
19  *
20  * Author: Hans van Staveren
21  */
22
23 #define SHORTCUT        /* Stop searching at distance 0 */
24
25 #if NREGS >= MAXRULE
26 #define MAXPOS NREGS
27 #else
28 #define MAXPOS MAXRULE
29 #endif
30
31 #define MAXPATTERN 5
32 #define MAXREPLLEN 5    /* Max length of EM-replacement, should come from boot */
33
34 byte startupcode[] = { DO_NEXTEM };
35
36 byte *nextem();
37 unsigned costcalc();
38 unsigned docoerc();
39 unsigned stackupto();
40 string tostring();
41
42 #ifdef NDEBUG
43 #define DEBUG(xxxxx)
44 #else
45 #include <stdio.h>
46 #define DEBUG(string) {if(Debug) fprintf(stderr,"%-*d%s\n",4*level,level,string);}
47 #endif
48
49 #define BROKE() {assert(origcp!=startupcode);DEBUG("BROKE");goto doreturn;}
50 #define CHKCOST() {if (totalcost>=costlimit) BROKE();}
51
52 unsigned codegen(codep,ply,toplevel,costlimit,forced) byte *codep; unsigned costlimit; {
53 #ifndef NDEBUG
54         byte *origcp=codep;
55         static int level=0;
56 #endif
57         unsigned totalcost = 0;
58         byte *bp;
59         int n;
60         unsigned mindistance,dist;
61         register int i;
62         int cindex;
63         int npos,npos2,pos[MAXPOS],pos2[MAXPOS];
64 #ifdef STONSTACK
65         state_t state;
66 #define SAVEST  savestatus(&state)
67 #define RESTST  restorestatus(&state)
68 #define FREEST  /* nothing */
69 #else
70         state_p state;
71 #define SAVEST  state=savestatus()
72 #define RESTST  restorestatus(state)
73 #define FREEST  freestatus(state)
74 #endif
75         unsigned mincost,t;
76         int texpno,nodeno;
77         token_p tp;
78         tkdef_p tdp;
79         int tinstno;
80         register struct reginfo *rp;
81         struct reginfo **rpp;
82         token_t token,mtoken,token2;
83         int propno;
84         int exactmatch;
85         int j;
86         int decision;
87         int stringno;
88         result_t result;
89         cost_t cost;
90         int size,lsize,repllen;
91         int tokexp[MAXPATTERN];
92         int nregneeded;
93         token_p regtp[MAXCREG];
94         c3_p regcp[MAXCREG];
95         rl_p regls[MAXCREG];
96         c3_p findcoerc();
97         int sret;
98         token_t reptoken[MAXREPLLEN];
99         int emrepllen,eminstr;
100         int inscoerc=0;
101         int stackpad;
102         struct perm *tup,*ntup,*besttup,*tuples();
103
104 #ifndef NDEBUG
105         level++;
106         DEBUG("Entering codegen");
107 #endif
108         for (;;) {
109         switch( (*codep++)&037 ) {
110     default:
111         assert(FALSE);
112         /* NOTREACHED */
113     case DO_NEXTEM:
114         DEBUG("NEXTEM");
115         tokpatlen = 0;
116         nallreg=0;
117         if (toplevel) {
118                 garbage_collect();
119                 totalcost=0;
120         } else {
121                 if (--ply <= 0)
122                         goto doreturn;
123         }
124         if (stackheight>MAXFSTACK-7)    
125                 totalcost += stackupto(&fakestack[6],ply,toplevel);
126         bp = nextem(toplevel);
127         if (bp == 0) {
128                 /*
129                  * No pattern found, can be pseudo or error
130                  * in table.
131                  */
132                 if (toplevel) {
133                         codep--;
134                         DEBUG("pseudo");
135                         dopseudo();
136                 } else
137                         goto doreturn;
138         } else {
139 #ifndef NDEBUG
140                 chkregs();
141 #endif
142                 if (! toplevel) {
143                         ply -= emp-saveemp+1;
144                         if (ply <= 0) ply = 1;
145                 }
146                 n = *bp++;
147                 assert(n>0 && n<=MAXRULE);
148                 if (n>1) {
149                         mindistance = MAXINT; npos=0;
150                         for(i=0;i<n;i++) {
151                                 getint(cindex,bp);
152                                 dist=distance(cindex);
153 #ifndef NDEBUG
154 if (Debug)
155         fprintf(stderr,"distance of pos %d is %u\n",i,dist);
156 #endif
157                                 if (dist<=mindistance) {
158                                         if (dist<mindistance) {
159 #ifdef SHORTCUT
160                                                 if(dist==0)
161                                                         goto gotit;
162 #endif
163                                                 npos=0;
164                                                 mindistance = dist;
165                                         }
166                                         pos[npos++] = cindex;
167                                 }
168                         }
169                         assert(mindistance<MAXINT);
170                         if (npos>1) {
171                                 /*
172                                  * More than 1 tokenpattern is a candidate.
173                                  * Decision has to be made by lookahead.
174                                  */
175                                 SAVEST;
176                                 mincost = costlimit-totalcost+1;
177                                 for(i=0;i<npos;i++) {
178                                         t=codegen(&coderules[pos[i]],ply,FALSE,
179                                                   costlimit<MAXINT?mincost:MAXINT,0);
180 #ifndef NDEBUG
181 if (Debug)
182         fprintf(stderr,"mincost %u,cost %u,pos %d\n",mincost,t,i);
183 #endif
184                                         if (t<mincost) {
185                                                 mincost = t;
186                                                 cindex = pos[i];
187                                         }
188                                         RESTST;
189                                 }
190                                 FREEST;
191                                 if (totalcost+mincost>costlimit) {
192                                         totalcost += mincost;
193                                         BROKE();
194                                 }
195                         } else {
196                                 cindex = pos[0];
197                         }
198                 } else {
199                         getint(cindex,bp);
200                 }
201
202         gotit:
203                 /*
204                  * Now cindex contains the code-index of the best candidate
205                  * so proceed to use it.
206                  */
207                 codep = &coderules[cindex];
208         }
209         break;
210     case DO_COERC:
211         DEBUG("COERC");
212         tokpatlen=1;
213         inscoerc=1;
214         break;
215     case DO_XXMATCH:
216         DEBUG("XXMATCH");
217     case DO_XMATCH:
218         DEBUG("XMATCH");
219         tokpatlen=(codep[-1]>>5)&07;
220         for (i=0;i<tokpatlen;i++)
221                 getint(tokexp[i],codep);
222         tokexp[i]=0;
223         break;  /* match already checked by distance() */
224     case DO_MATCH:
225         DEBUG("MATCH");
226         tokpatlen=(codep[-1]>>5)&07;
227         for(i=0;i<tokpatlen;i++)
228                 getint(tokexp[i],codep);
229         tokexp[i] = 0;
230         tp = &fakestack[stackheight-1];
231         i=0;
232         while (i<tokpatlen && tp>=fakestack) {
233                 size=tsize(tp);
234                 while (i<tokpatlen && (lsize=ssize(tokexp[i]))<=size) {
235                         size -= lsize;
236                         i++;
237                 }
238                 if (i<tokpatlen && size!=0) {
239                         totalcost += stackupto(tp,ply,toplevel);
240                         CHKCOST();
241                         break;
242                 }
243                 tp--;
244         }
245         tp = &fakestack[stackheight-1];
246         i=0;
247         while (i<tokpatlen && tp >= fakestack) {
248                 size = tsize(tp);
249                 lsize= ssize(tokexp[i]);
250                 if (size != lsize) {    /* find coercion */
251 #ifdef MAXSPLIT
252                         sret = split(tp,&tokexp[i],ply,toplevel);
253                         if (sret==0) {
254 #endif /* MAXSPLIT */
255                                 totalcost += stackupto(tp,ply,toplevel);
256                                 CHKCOST();
257                                 break;
258 #ifdef MAXSPLIT
259                         }
260                         i += sret;
261 #endif /* MAXSPLIT */
262                 } else
263                         i += 1;
264                 tp--;
265         }
266     nextmatch:
267         tp = &fakestack[stackheight-1];
268         i=0; nregneeded = 0;
269         while (i<tokpatlen && tp>=fakestack) {
270                 if (!match(tp,&machsets[tokexp[i]],0)) {
271                         register c3_p cp = findcoerc(tp, &machsets[tokexp[i]]);
272                         if (cp==0) {
273                                 for (j=0;j<nregneeded;j++)
274                                         regtp[j] -= (tp-fakestack+1);
275                                 totalcost += stackupto(tp,ply,toplevel);
276                                 CHKCOST();
277                                 break;
278                         } else {
279                                 if (cp->c3_prop==0) {
280                                         totalcost+=docoerc(tp,cp,ply,toplevel,0);
281                                         CHKCOST();
282                                 } else {
283                                         assert(nregneeded<MAXCREG);
284                                         regtp[nregneeded] = tp;
285                                         regcp[nregneeded] = cp;
286                                         regls[nregneeded] = curreglist;
287                                         nregneeded++;
288                                 }
289                         }
290                 }
291                 i++; tp--;
292         }
293         if (tokpatlen>stackheight) {
294                 int k;
295                 stackpad = tokpatlen-stackheight;
296                 for (j=stackheight-1, k = j + stackpad;j>=0;j--, k--) {
297                         fakestack[k] = fakestack[j];
298                         /* fakestack[j+stackpad] = fakestack[j]; does not
299                            compile under Xenix
300                         */
301                 }
302                 for (j=0;j<stackpad;j++)
303                         fakestack[j].t_token=0;
304                 stackheight += stackpad;
305                 for (j=0;j<nregneeded;j++)
306                         regtp[j] += stackpad;
307                 tp = &fakestack[stackpad-1];
308                 while (i<tokpatlen && tp>=fakestack) {
309                         register c3_p cp = findcoerc((token_p) 0, &machsets[tokexp[i]]);
310                         if (cp==0) {
311                                 assert(!toplevel);
312                                 for (j=0;j<nregneeded;j++)
313                                         myfree(regls[j]);
314                                 totalcost=INFINITY;
315                                 BROKE();
316                         }
317                         if (cp->c3_prop==0) {
318                                 totalcost+=docoerc(tp,cp,ply,toplevel,0);
319                                 CHKCOST();
320                         } else {
321                                 assert(nregneeded<MAXCREG);
322                                 regtp[nregneeded] = tp;
323                                 regcp[nregneeded] = cp;
324                                 regls[nregneeded] = curreglist;
325                                 nregneeded++;
326                         }
327                         i++; tp--;
328                 }
329         } else
330                 stackpad=0;
331         assert(i==tokpatlen);
332         if (nregneeded==0)
333                 break;
334         SAVEST;
335         mincost=costlimit-totalcost+1;
336         tup = tuples(regls,nregneeded);
337         besttup=0;
338         for (; tup != 0; tup = ntup) {
339 #ifndef NDEBUG
340 if(Debug>1) { fprintf(stderr,"Next tuple %d,%d,%d,%d\n",
341                         tup->p_rar[0],
342                         tup->p_rar[1],
343                         tup->p_rar[2],
344                         tup->p_rar[3]);
345                 fprintf(stderr, "totalcost = %u, costlimit = %u, mincost = %u\n",
346                         totalcost, costlimit, mincost);
347         }
348 #endif
349                 ntup = tup->p_next;
350                 for (i=0,t=0;i<nregneeded && t<mincost; i++)
351                         t += docoerc(regtp[i],regcp[i],ply,FALSE,tup->p_rar[i]);
352 #ifndef NDEBUG   
353 if (Debug > 1) fprintf(stderr, "cost after coercions: %u\n", t); 
354 #endif
355                 if (t<mincost)
356                         t += codegen(codep,ply,FALSE,mincost<MAXINT?mincost-t:MAXINT,0);
357                 if (t<mincost) {
358                         mincost = t;
359                         besttup = tup;
360                 } else
361                         myfree(tup);
362                 RESTST;
363         }
364         FREEST;
365         for (i=0;i<nregneeded;i++)
366                 myfree(regls[i]);
367         if (totalcost+mincost>costlimit) {
368                 if (besttup)
369                         myfree(besttup);
370                 if (stackpad!=tokpatlen) {
371                         if (stackpad) {
372                                 if (costlimit<MAXINT) {
373                                         totalcost = costlimit+1;
374                                         BROKE();
375                                 }
376                                 for (i=0;i<stackheight-stackpad;i++)
377                                         fakestack[i] = fakestack[i+stackpad];
378                                 stackheight -= stackpad;
379                                 totalcost += stackupto(&fakestack[stackheight-1],ply,toplevel);
380                         } else
381                                 totalcost += stackupto(fakestack,ply,toplevel);
382                         CHKCOST();
383                         goto nextmatch;
384                 }
385                 totalcost += mincost;
386                 BROKE();
387         }
388         for (i=0;i<nregneeded;i++)
389                 totalcost += docoerc(regtp[i],regcp[i],ply,toplevel,besttup->p_rar[i]);
390         myfree(besttup);
391         break;
392     case DO_REMOVE:
393         DEBUG("REMOVE");
394         if (codep[-1]&32) {
395                 getint(texpno,codep);
396                 getint(nodeno,codep);
397         } else {
398                 getint(texpno,codep);
399                 nodeno=0;
400         }
401         for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
402                 if (match(tp,&machsets[texpno],nodeno)) {
403                         /* investigate possible coercion to register */
404                         totalcost += stackupto(tp,ply,toplevel);
405                         CHKCOST();
406                         break;
407                 }
408         for (rp=machregs+2;rp<machregs+NREGS;rp++)
409                 if (match(&rp->r_contents,&machsets[texpno],nodeno))
410                         rp->r_contents.t_token=0;
411         break;
412     case DO_RREMOVE:    /* register remove */
413         DEBUG("RREMOVE");
414         getint(nodeno,codep);
415         result=compute(&enodes[nodeno]);
416         assert(result.e_typ==EV_REG);
417         for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
418                 if (tp->t_token==-1) {
419                         if(tp->t_att[0].ar==result.e_v.e_reg)
420                                 goto gotone;
421                 } else {
422                         tdp = &tokens[tp->t_token];
423                         for(i=0;i<TOKENSIZE;i++)
424                                 if (tdp->t_type[i]==EV_REG &&
425                                     tp->t_att[i].ar==result.e_v.e_reg)
426                                         goto gotone;
427                 }
428         break;
429     gotone:
430         /* investigate possible coercion to register */
431         totalcost += stackupto(tp,ply,toplevel);
432         CHKCOST();
433         break;
434     case DO_DEALLOCATE:
435         DEBUG("DEALLOCATE");
436         getint(tinstno,codep);
437         instance(tinstno,&token);
438         if (token.t_token==-1)
439                 chrefcount(token.t_att[0].ar,-1,TRUE);
440         else {
441                 tdp= &tokens[token.t_token];
442                 for (i=0;i<TOKENSIZE;i++)
443                         if (tdp->t_type[i]==EV_REG)
444                                 chrefcount(token.t_att[i].ar,-1,TRUE);
445         }
446         break;
447     case DO_REALLOCATE:
448         DEBUG("REALLOCATE");
449         for(rp=machregs;rp<machregs+NREGS;rp++)
450                 if(rp->r_tcount) {
451                         rp->r_refcount -= rp->r_tcount;
452                         rp->r_tcount = 0;
453                 }
454         break;
455     case DO_ALLOCATE:
456         DEBUG("ALLOCATE");
457         if (codep[-1]&32) {
458                 getint(propno,codep);
459                 getint(tinstno,codep);
460         } else {
461                 getint(propno,codep);
462                 tinstno=0;
463         }
464         instance(tinstno,&token);
465         if (!forced) {
466                 do {
467                         npos=exactmatch=0;
468                         for(rpp=reglist[propno];rp= *rpp; rpp++)
469                                 if (getrefcount((int)(rp-machregs), FALSE)==0) {
470                                         pos[npos++] = rp-machregs;
471                                         if (eqtoken(&rp->r_contents,&token))
472                                                 exactmatch++;
473                                 }
474                         /*
475                          * Now pos[] contains all free registers with desired
476                          * property. If none then some stacking has to take place.
477                          */
478                         if (npos==0) {
479                                 if (stackheight<=tokpatlen) {
480                                         if (!toplevel) {
481                                                 totalcost = INFINITY;
482                                                 BROKE();
483                                         } else {
484                                                 fatal("No regs available");
485                                         }
486                                 }
487                                 totalcost += stackupto( &fakestack[0],ply,toplevel);
488                                 CHKCOST();
489                         }
490                 } while (npos==0);
491                 if (!exactmatch) {
492                         npos2=npos;
493                         for(i=0;i<npos;i++)
494                                 pos2[i]=pos[i];
495                 } else {
496                         /*
497                          * Now we are reducing the number of possible registers.
498                          * We take only one equally likely register out of every
499                          * equivalence class as given by set of properties.
500                          */
501                         mtoken = token;
502                         npos2=0;
503                         for(i=0;i<npos;i++)
504                                 if (eqtoken(&machregs[pos[i]].r_contents,&mtoken)) {
505                                         pos2[npos2++] = pos[i];
506                                         for(j=0;j<npos2-1;j++)
507                                                 if (eqregclass(pos2[j],pos[i])) {
508                                                         npos2--;
509                                                         break;
510                                                 }
511                                 }
512                 }
513                 /*
514                  * Now pos2[] contains all possibilities to try, if more than
515                  * one, lookahead is necessary.
516                  */
517                 token2.t_token= -1;
518                 for (i=1;i<TOKENSIZE;i++)
519                         token2.t_att[i].aw=0;
520                 if (npos2==1)
521                         decision=pos2[0];
522                 else {
523                         SAVEST;
524                         mincost=costlimit-totalcost+1;
525                         for(j=0;j<npos2;j++) {
526                                 chrefcount(pos2[j],1,FALSE);
527                                 token2.t_att[0].ar=pos2[j];
528                                 allreg[nallreg++] = pos2[j];
529                                 if (token.t_token != 0)
530                                         t=move(&token,&token2,ply,FALSE,mincost);
531                                 else {
532                                         t = 0;
533                                         erasereg(pos2[j]);
534                                 }
535                                 if (t<mincost)
536                                         t += codegen(codep,ply,FALSE,mincost<MAXINT?mincost-t:MAXINT,0);
537                                 if (t<mincost) {
538                                         mincost=t;
539                                         decision=pos2[j];
540                                 }
541                                 RESTST;
542                         }
543                         FREEST;
544                         if (totalcost+mincost>costlimit) {
545                                 totalcost = INFINITY;
546                                 BROKE();
547                         }
548                 }
549         } else {
550                 decision = forced;
551                 if (getrefcount(decision, FALSE)!=0) {
552                         totalcost = INFINITY;
553                         BROKE();
554                 }
555                 token2.t_token = -1;
556         }
557         chrefcount(decision,1,FALSE);
558         token2.t_att[0].ar=decision;
559         if (token.t_token != 0) {
560                 totalcost+=move(&token,&token2,ply,toplevel,MAXINT);
561                 CHKCOST();
562         } else
563                 erasereg(decision);
564         allreg[nallreg++]=decision;
565         break;
566     case DO_LOUTPUT:
567         DEBUG("LOUTPUT");
568         getint(stringno,codep);
569         getint(nodeno,codep);
570         if (toplevel) {
571                 gencode(codestrings[stringno]);
572                 genexpr(nodeno);
573         }
574         break;
575     case DO_ROUTPUT:
576         DEBUG("ROUTPUT");
577         i=((codep[-1]>>5)&07);
578         do {
579                 getint(stringno,codep);
580                 if (toplevel) {
581                         gencode(codestrings[stringno]);
582                         gennl();
583                 }
584         } while (i--);
585         break;
586     case DO_MOVE:
587         DEBUG("MOVE");
588         getint(tinstno,codep);
589         instance(tinstno,&token);
590         getint(tinstno,codep);
591         instance(tinstno,&token2);
592         totalcost += move(&token,&token2,ply,toplevel,costlimit-totalcost+1);
593         CHKCOST();
594         break;
595     case DO_ERASE:
596         DEBUG("ERASE");
597         getint(nodeno,codep);
598         result=compute(&enodes[nodeno]);
599         assert(result.e_typ==EV_REG);
600         erasereg(result.e_v.e_reg);
601         break;
602     case DO_TOKREPLACE:
603         DEBUG("TOKREPLACE");
604         assert(stackheight>=tokpatlen);
605         repllen=(codep[-1]>>5)&07;
606         for(i=0;i<repllen;i++) {
607                 getint(tinstno,codep);
608                 instance(tinstno,&reptoken[i]);
609                 tref(&reptoken[i],1);
610         }
611         for(i=0;i<tokpatlen;i++) {
612                 if (!inscoerc)
613                         tref(&fakestack[stackheight-1],-1);
614                 stackheight--;
615         }
616         for (i=0;i<repllen;i++) {
617                 assert(stackheight<MAXFSTACK);
618                 fakestack[stackheight] = reptoken[i];
619                 stackheight++;
620                 /* do not combine previous two statements; that does not
621                    compile under Xenix V3.2
622                 */
623         }
624         for(i=0;i<nallreg;i++)
625                 chrefcount(allreg[i],-1,FALSE);
626         break;
627     case DO_EMREPLACE:
628         DEBUG("EMREPLACE");
629         emrepllen=(codep[-1]>>5)&07;
630         j=emp-emlines;
631         if (emrepllen>j) {
632                 int k = nemlines + emrepllen - j;
633                 assert(k<MAXEMLINES);
634                 for (i=nemlines;i>=0;i--, k--)
635                         emlines[k] = emlines[i];
636                 nemlines += emrepllen-j;
637                 emp += emrepllen-j;
638         }
639         emp -= emrepllen;
640         for (i=0;i<emrepllen;i++) {
641                 getint(eminstr,codep);
642                 getint(nodeno,codep);
643                 emp[i].em_instr = eminstr;
644                 result = compute(&enodes[nodeno]);
645                 switch(result.e_typ) {
646                 default:
647                         assert(FALSE);
648                 case 0:
649                         emp[i].em_optyp = OPNO;
650                         emp[i].em_soper = 0;
651                         break;
652                 case EV_INT:
653                         emp[i].em_optyp = OPINT;
654                         emp[i].em_soper = tostring(result.e_v.e_con);
655                         emp[i].em_u.em_ioper = result.e_v.e_con;
656                         break;
657                 case EV_STR:
658                         emp[i].em_optyp = OPSYMBOL;
659                         emp[i].em_soper = result.e_v.e_str;
660                         break;
661                 }
662         }
663         if (!toplevel) {
664                 ply += emrepllen;
665         }
666         break;
667     case DO_COST:
668         DEBUG("COST");
669         getint(cost.c_size,codep);
670         getint(cost.c_time,codep);
671         totalcost += costcalc(cost);
672         CHKCOST();
673         break;
674 #ifdef REGVARS
675     case DO_PRETURN:
676         if (toplevel) {
677                 swtxt();
678                 regreturn();    /* in mach.c */
679         }
680         break;
681 #endif
682     case DO_RETURN:
683         DEBUG("RETURN");
684         assert(origcp!=startupcode);
685     doreturn:
686 #ifndef NDEBUG
687         level--;
688 #endif
689         return(totalcost);
690         }
691         }
692 }