2 static char rcsid[] = "$Id: codegen.c,v 0.36 1994/06/24 13:27:01 ceriel Exp $";
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".
20 * Author: Hans van Staveren
23 #define ALLOW_NEXTEM /* code generator is allowed new try of NEXTEM
24 in exceptional cases */
26 byte startupcode[] = { DO_NEXTEM };
39 #define DEBUG(string) {if(Debug) fprintf(stderr,"%-*d%s\n",4*level,level,string);}
42 #define BROKE() {assert(origcp!=startupcode || !paniced);DEBUG("BROKE");totalcost=INFINITY;goto doreturn;}
43 #define CHKCOST() {if (totalcost>=costlimit) BROKE();}
46 int tablelines[MAXTDBUG];
53 unsigned codegen(codep,ply,toplevel,costlimit,forced) byte *codep; unsigned costlimit; {
58 unsigned totalcost = 0;
60 int procarg[MAXPROCARG+1];
66 #define SAVEST savestatus(&state)
67 #define RESTST restorestatus(&state)
68 #define FREEST /* nothing */
70 extern char *tablename;
74 assert(costlimit <= INFINITY);
76 DEBUG("Entering codegen");
77 if (Debug > 1) fprintf(stderr, "toplevel = %d\n", toplevel);
80 switch( (*codep++)&037 ) {
89 tablelines[ntableline++] = n;
90 if (ntableline>=MAXTDBUG)
91 ntableline -= MAXTDBUG;
93 set_val[n>>4] &= ~(1<<(n&017));
96 fprintf(stderr,"code from \"%s\", line %d\n",tablename,n);
104 unsigned mindistance,dist;
107 int npos,pos[MAXRULE];
120 if (stackheight>MAXFSTACK-7) {
123 fprintf(stderr,"Fakestack overflow threatens(%d), action ...\n",stackheight);
125 totalcost += stackupto(&fakestack[6],ply,toplevel);
128 bp = nextem(toplevel);
130 if (toplevel) paniced=0;
131 savebp = nextem(toplevel);
133 if (toplevel) totalcost = 0;
138 * No pattern found, can be pseudo or error
152 ply -= emp-saveemp+1;
153 if (ply <= 0) ply = 1;
156 if (n==0) { /* "procedure" */
160 assert(nargs <= MAXPROCARG);
161 for (j = 0; j < nargs; j++) {
162 getint(procarg[j],bp);
168 assert(n>0 && n<=MAXRULE);
170 mindistance = MAXINT; npos=0;
173 dist=distance(cindex);
176 fprintf(stderr,"distance of pos %d is %u\n",i,dist);
178 if (dist<=mindistance
183 if (dist<mindistance) {
192 pos[npos++] = cindex;
195 assert(mindistance<MAXINT);
198 * More than 1 tokenpattern is a candidate.
199 * Decision has to be made by lookahead.
202 mincost = costlimit-totalcost+1;
203 assert(mincost <= INFINITY);
204 for(i=0;i<npos;i++) {
205 t=codegen(&coderules[pos[i]],ply,FALSE,
206 costlimit<MAXINT?mincost:MAXINT,0);
209 fprintf(stderr,"mincost %u,cost %u,pos %d\n",mincost,t,i);
218 if (totalcost+mincost>costlimit) {
230 * Now cindex contains the code-index of the best candidate
231 * so proceed to use it.
233 codep = &coderules[cindex];
250 tokpatlen=(codep[-1]>>5)&07;
251 for (i=0;i<tokpatlen;i++)
253 break; /* match already checked by distance() */
261 int tokexp[MAXPATLEN];
263 token_p regtp[MAXCREG];
271 struct perm *tup,*ntup,*besttup,*tuples();
274 tokpatlen=(codep[-1]>>5)&07;
275 for(i=0;i<tokpatlen;i++)
276 getint(tokexp[i],codep);
278 tp = &fakestack[stackheight-1];
280 while (i<tokpatlen && tp>=fakestack) {
282 while (i<tokpatlen && (lsize=ssize(tokexp[i]))<=size) {
286 if (i<tokpatlen && size!=0) {
287 totalcost += stackupto(tp,ply,toplevel);
293 tp = &fakestack[stackheight-1];
295 while (i<tokpatlen && tp >= fakestack) {
297 lsize= ssize(tokexp[i]);
298 if (size != lsize) { /* find coercion */
300 sret = split(tp,&tokexp[i],ply,toplevel);
302 #endif /* MAXSPLIT */
303 totalcost += stackupto(tp,ply,toplevel);
309 #endif /* MAXSPLIT */
315 tp = &fakestack[stackheight-1];
317 while (i<tokpatlen && tp>=fakestack) {
318 if (!match(tp,&machsets[tokexp[i]],0)) {
319 cp = findcoerc(tp, &machsets[tokexp[i]]);
321 if (Debug>1) fprintf(stderr,"findcoerc returns 0x%x at position %d\n",(unsigned)cp,i);
324 for (j=0;j<nregneeded;j++)
325 regtp[j] -= (tp-fakestack+1);
326 totalcost += stackupto(tp,ply,toplevel);
331 totalcost+=docoerc(tp,cp,ply,toplevel,0);
335 if(Debug>1) fprintf(stderr,"Register of type %d needed, remembering...\n",cp->c3_prop);
337 assert(nregneeded<MAXCREG);
338 regtp[nregneeded] = tp;
339 regcp[nregneeded] = cp;
340 regls[nregneeded] = curreglist;
347 if (tokpatlen>stackheight) {
349 if(Debug>1) fprintf(stderr,"Pattern too long, %d with only %d items on stack\n",
350 tokpatlen,stackheight);
352 stackpad = tokpatlen-stackheight;
353 for (j=stackheight-1;j>=0;j--)
354 fakestack[j+stackpad] = fakestack[j];
355 for (j=0;j<stackpad;j++)
356 fakestack[j].t_token=0;
357 stackheight += stackpad;
358 for (j=0;j<nregneeded;j++)
359 regtp[j] += stackpad;
360 for (tp = &fakestack[stackpad-1];i<tokpatlen && tp>=fakestack;i++,tp--) {
361 cp = findcoerc((token_p) 0, &machsets[tokexp[i]]);
363 for (j=0;j<nregneeded;j++)
364 myfree((string) (regls[j]));
369 assert(!(toplevel&&paniced));
370 if (paniced) goto normalfailed;
371 totalcost = INFINITY;
372 for (i=0;i<stackheight-stackpad;i++)
373 fakestack[i] = fakestack[i+stackpad];
374 stackheight -= stackpad;
379 totalcost+=docoerc(tp,cp,ply,toplevel,0);
382 assert(nregneeded<MAXCREG);
383 regtp[nregneeded] = tp;
384 regcp[nregneeded] = cp;
385 regls[nregneeded] = curreglist;
391 assert(i==tokpatlen);
395 mincost=costlimit-totalcost+1;
396 tup = tuples(regls,nregneeded);
398 for (; tup != 0; tup = ntup) {
400 if(Debug>1) { fprintf(stderr,"Next tuple %d,%d,%d,%d\n",
405 fprintf(stderr, "totalcost = %u, costlimit = %u, mincost = %u\n",
406 totalcost, costlimit, mincost);
410 for (i=0,t=0;i<nregneeded && t<mincost; i++)
411 t += docoerc(regtp[i],regcp[i],ply,FALSE,tup->p_rar[i]);
413 if (Debug > 1) fprintf(stderr, "cost after coercions: %u\n", t);
415 if ( t<mincost && tokpatlen<=stackheight ) {
418 fprintf(stderr,"Continuing match after coercions\n");
420 t += codegen(codep,ply,FALSE,mincost<MAXINT?mincost-t:MAXINT,0);
422 if ( t<mincost && tokpatlen<=stackheight ) {
426 myfree((string) tup);
430 for (i=0;i<nregneeded;i++)
431 myfree((string)(regls[i]));
432 if (totalcost+mincost>costlimit) {
434 myfree((string)besttup);
435 normalfailed: if (stackpad!=tokpatlen) {
437 for (i=0;i<stackheight-stackpad;i++)
438 fakestack[i] = fakestack[i+stackpad];
439 stackheight -= stackpad;
440 if (costlimit<MAXINT)
442 totalcost += stackupto(&fakestack[stackheight-1],ply,toplevel);
444 totalcost += stackupto(fakestack,ply,toplevel);
448 totalcost += mincost;
449 for (i=0;i<stackheight-stackpad;i++)
450 fakestack[i] = fakestack[i+stackpad];
451 stackheight -= stackpad;
454 for (i=0;i<nregneeded;i++)
455 totalcost += docoerc(regtp[i],regcp[i],ply,toplevel,besttup->p_rar[i]);
456 assert(totalcost <= costlimit);
457 myfree((string)besttup);
465 int doremove = (codep[-1] & 037) == DO_REMOVE;
468 DEBUG(doremove ? "REMOVE" : "TOSTACK");
470 getint(texpno,codep);
471 getint(nodeno,codep);
473 getint(texpno,codep);
476 if (texpno == allsetno) {
477 totalcost += stackupto(&fakestack[stackheight-tokpatlen-1],ply,toplevel);
479 if (doremove) for (rp=machregs;rp<machregs+NREGS;rp++)
480 rp->r_contents.t_token=0;
483 for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
484 if (match(tp,&machsets[texpno],nodeno)) {
485 /* investigate possible coercion to register */
486 totalcost += stackupto(tp,ply,toplevel);
490 if (doremove) for (rp=machregs;rp<machregs+NREGS;rp++) {
491 if (rp->r_contents.t_token != 0 &&
492 match(&rp->r_contents,&machsets[texpno],nodeno)) {
494 if (Debug > 1) fprintf(stderr, "killing reg %ld (%s)\n", (long)(rp-machregs), rp->r_repr ? codestrings[rp->r_repr] : "cc");
496 rp->r_contents.t_token=0;
502 case DO_RREMOVE: { /* register remove */
508 int dokill = (codep[-1] & 037) == DO_KILLREG;
510 DEBUG(dokill ? "KILLREG" : "RREMOVE");
511 getint(nodeno,codep);
512 compute(&enodes[nodeno], &result);
513 if (result.e_typ!=EV_REG)
515 if ( in_stack(result.e_v.e_reg) ) BROKE() ; /* Check aside-stack */
517 /* kill register, and kill condition codes if they are set to
520 machregs[result.e_v.e_reg].r_contents.t_token = 0;
521 if (machregs[0].r_contents.t_token == -1 &&
522 machregs[0].r_contents.t_att[0].ar == result.e_v.e_reg) {
523 machregs[0].r_contents.t_token = 0;
526 for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--)
527 if (tp->t_token==-1) {
528 if(tp->t_att[0].ar==result.e_v.e_reg)
531 tdp = &tokens[tp->t_token];
532 for(i=0;i<TOKENSIZE;i++)
533 if (tdp->t_type[i]==EV_REG &&
534 tp->t_att[i].ar==result.e_v.e_reg)
539 /* investigate possible coercion to register */
540 totalcost += stackupto(tp,ply,toplevel);
544 case DO_DEALLOCATE: {
551 getint(tinstno,codep);
552 instance(tinstno,&token);
553 if (token.t_token==-1)
554 chrefcount(token.t_att[0].ar,-1,TRUE);
556 tdp= &tokens[token.t_token];
557 for (i=0;i<TOKENSIZE;i++)
558 if (tdp->t_type[i]==EV_REG)
559 chrefcount(token.t_att[i].ar,-1,TRUE);
563 case DO_REALLOCATE: {
567 for(rp=machregs+1;rp<machregs+NREGS;rp++)
569 rp->r_refcount -= rp->r_tcount;
578 int npos,npos2,pos[NREGS],pos2[NREGS];
580 struct reginfo *rp,**rpp;
581 token_t token,token2;
587 getint(propno,codep);
588 getint(tinstno,codep);
589 DEBUG("ALLOCATE,INIT");
591 getint(propno,codep);
593 DEBUG("ALLOCATE,EMPTY");
595 instance(tinstno,&token);
599 for(rpp=reglist[propno];rp= *rpp; rpp++)
600 if (getrefcount((int)(rp-machregs), FALSE)==0) {
601 pos[npos++] = rp-machregs;
602 if (eqtoken(&rp->r_contents,&token))
603 pos2[exactmatch++] = rp-machregs;
606 * Now pos[] contains all free registers with desired
607 * property. If none then some stacking has to take place.
610 if (stackheight<=tokpatlen) {
615 fatal("No regs available");
616 totalcost += stackupto( &fakestack[0],ply,toplevel);
620 totalcost += stackupto( &fakestack[0],ply,toplevel);
625 if (!exactmatch && tinstno!=0) {
627 * No exact match, but we were looking for a particular
628 * token. Now try to find registers of which no
629 * known contents is available (the others might still
633 if (machregs[pos[i]].r_contents.t_token == 0) {
634 pos2[exactmatch++] = pos[i];
644 * Now we are reducing the number of possible registers.
645 * We take only one equally likely register out of every
646 * equivalence class as given by set of properties.
649 for(i=0;i<exactmatch;i++) {
650 pos2[npos2++] = pos2[i];
651 for(j=0;j<npos2-1;j++)
652 if (eqregclass(pos2[j],pos2[i])) {
659 * Now pos2[] contains all possibilities to try, if more than
660 * one, lookahead is necessary.
663 for (i=1;i<TOKENSIZE;i++)
664 token2.t_att[i].aw=0;
668 mincost=costlimit-totalcost+1;
669 for(j=0;j<npos2;j++) {
670 chrefcount(pos2[j],1,FALSE);
671 token2.t_att[0].ar=pos2[j];
672 allreg[nallreg++] = pos2[j];
673 if (token.t_token != 0)
674 t=move(&token,&token2,ply,FALSE,mincost);
680 t += codegen(codep,ply,FALSE,mincost<MAXINT?mincost-t:MAXINT,0);
688 if (totalcost+mincost>costlimit)
693 if (getrefcount(decision, FALSE)!=0)
697 chrefcount(decision,1,FALSE);
698 token2.t_att[0].ar=decision;
699 if (token.t_token != 0) {
700 totalcost+=move(&token,&token2,ply,toplevel,MAXINT);
704 allreg[nallreg++]=decision;
715 n=((codep[-1]>>5)&07);
716 getint(stringno,codep);
719 if (stringno>10000) {
720 assert(stringno < 100001 + MAXPROCARG);
721 genstr(procarg[stringno-10001]);
726 getint(tinstno,codep);
727 instance(tinstno,&token);
729 prtoken(&token,i==0 ? ' ' : ',');
731 totalcost += tokens[token.t_token].t_cost.ct_space;
740 token_t token,token2;
743 getint(tinstno,codep);
744 instance(tinstno,&token);
745 getint(tinstno,codep);
746 instance(tinstno,&token2);
747 totalcost += move(&token,&token2,ply,toplevel,costlimit-totalcost+1);
756 getint(tinstno,codep);
757 instance(tinstno,&token);
758 totalcost += test(&token,ply,toplevel,costlimit-totalcost+1);
767 getint(tinstno,codep);
768 instance(tinstno,&token);
777 getint(nodeno,codep);
778 compute(&enodes[nodeno], &result);
779 assert(result.e_typ!=EV_INT && result.e_typ!=EV_ADDR);
780 if (result.e_typ==EV_REG)
781 erasereg(result.e_v.e_reg);
784 case DO_TOKREPLACE: {
788 token_t reptoken[MAXREPLLEN];
791 assert(stackheight>=tokpatlen);
792 repllen=(codep[-1]>>5)&07;
795 fprintf(stderr,"Stackheight=%d, tokpatlen=%d, repllen=%d %s\n",
796 stackheight,tokpatlen,repllen,inscoerc ? "(inscoerc)":"");
798 for(i=0;i<repllen;i++) {
799 getint(tinstno,codep);
800 instance(tinstno,&reptoken[i]);
801 tref(&reptoken[i],1);
803 for(i=0;i<tokpatlen;i++) {
805 tref(&fakestack[stackheight-1],-1);
808 for (i=0;i<repllen;i++) {
809 assert(stackheight<MAXFSTACK);
810 fakestack[stackheight++] = reptoken[i];
812 for(i=0;i<nallreg;i++)
813 chrefcount(allreg[i],-1,FALSE);
820 result_t result[MAXEMREPLLEN];
821 int emrepllen,eminstr;
824 emrepllen=(codep[-1]>>5)&07;
827 assert(nemlines+emrepllen-j<MAXEMLINES);
828 for (i=nemlines;i>=0;i--)
829 emlines[i+emrepllen-j] = emlines[i];
830 nemlines += emrepllen-j;
834 for (i=0;i<emrepllen;i++) {
835 getint(eminstr,codep);
836 getint(nodeno,codep);
837 emp[i].em_instr = eminstr;
838 compute(&enodes[nodeno], &result[i]);
840 for (i=0;i<emrepllen;i++) {
841 switch(result[i].e_typ) {
845 emp[i].em_optyp = OPNO;
849 emp[i].em_optyp = OPINT;
850 emp[i].em_soper = tostring(result[i].e_v.e_con);
851 emp[i].em_u.em_ioper = result[i].e_v.e_con;
854 emp[i].em_optyp = OPSYMBOL;
855 emp[i].em_soper = ad2str(result[i].e_v.e_addr);
863 fprintf(stderr, "ply becomes %d\n", ply);
872 getint(cost.ct_space,codep);
873 getint(cost.ct_time,codep);
874 totalcost += costcalc(cost);
882 regreturn(); /* in mach.c */
889 assert(origcp!=startupcode);
912 if (toplevel && totalcost == INFINITY && ! paniced) {
914 totalcost += stackupto(&fakestack[stackheight-1], ply, toplevel);
917 fprintf(stderr, "Stackheight = %d\n", stackheight);
933 extern int ncodebytes;
935 if ((fd=open("code",0))<0) {
936 error("Can't open code");
938 if (read(fd,coderules,ncodebytes)!=ncodebytes) {
939 error("Short read from code");
946 initlset(f) char *f; {
947 extern char *myalloc();
950 if ((set_fd=open(f+1,2))<0)
951 error("Can't open %s rw",f+1);
952 read(set_fd,&set_size,sizeof(int));
953 set_val=( short *) myalloc(set_size);
954 read(set_fd,set_val,set_size);
960 lseek(set_fd,(long) sizeof(int),0);
961 write(set_fd,set_val,set_size);
963 if (set_flag[0]=='u') {
966 fprintf(stderr,"Unused code rules:\n\n");
967 for(i=0;i<8*set_size;i++)
968 if(set_val[i>>4]&(1<<(i&017)))
969 fprintf(stderr,"\"%s\", line %d\n",tablename,i);