#ifndef NORCSID static char rcsid[] = "$Header$"; #endif #include "assert.h" #include "param.h" #include "tables.h" #include "types.h" #include #include "data.h" #include "result.h" #include "state.h" #include "equiv.h" #include "extern.h" /* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". * * Author: Hans van Staveren */ #define SHORTCUT /* Stop searching at distance 0 */ #if NREGS >= MAXRULE #define MAXPOS NREGS #else #define MAXPOS MAXRULE #endif #define MAXPATTERN 5 #define MAXREPLLEN 5 /* Max length of EM-replacement, should come from boot */ byte startupcode[] = { DO_NEXTEM }; byte *nextem(); unsigned costcalc(); unsigned docoerc(); unsigned stackupto(); string tostring(); #ifdef NDEBUG #define DEBUG() #else #include #define DEBUG(string) {if(Debug) fprintf(stderr,"%-*d%s\n",4*level,level,string);} #endif #define BROKE() {assert(origcp!=startupcode);DEBUG("BROKE");goto doreturn;} #define CHKCOST() {if (totalcost>=costlimit) BROKE();} unsigned codegen(codep,ply,toplevel,costlimit,forced) byte *codep; unsigned costlimit; { #ifndef NDEBUG byte *origcp=codep; static int level=0; #endif unsigned totalcost = 0; byte *bp; int n; unsigned mindistance,dist; register i; int cindex; int npos,npos2,pos[MAXPOS],pos2[MAXPOS]; #ifdef STONSTACK state_t state; #define SAVEST savestatus(&state) #define RESTST restorestatus(&state) #define FREEST /* nothing */ #else state_p state; #define SAVEST state=savestatus() #define RESTST restorestatus(state) #define FREEST freestatus(state) #endif unsigned mincost,t; int texpno,nodeno; token_p tp; tkdef_p tdp; int tinstno; struct reginfo *rp,**rpp; token_t token,mtoken,token2; int propno; int exactmatch; int j; int decision; int stringno; result_t result; cost_t cost; int size,lsize,repllen; int tokexp[MAXPATTERN]; int nregneeded; token_p regtp[MAXCREG]; c3_p regcp[MAXCREG]; rl_p regls[MAXCREG]; c3_p cp,findcoerc(); int sret; token_t reptoken[MAXREPLLEN]; int emrepllen,eminstr; int inscoerc=0; int stackpad; struct perm *tup,*ntup,*besttup,*tuples(); #ifndef NDEBUG level++; DEBUG("Entering codegen"); #endif for (;;) { switch( (*codep++)&037 ) { default: assert(FALSE); /* NOTREACHED */ case DO_NEXTEM: DEBUG("NEXTEM"); tokpatlen = 0; nallreg=0; if (toplevel) { garbage_collect(); totalcost=0; } else { if (--ply <= 0) goto doreturn; } if (stackheight>MAXFSTACK-7) totalcost += stackupto(&fakestack[6],ply,toplevel); bp = nextem(toplevel); if (bp == 0) { /* * No pattern found, can be pseudo or error * in table. */ if (toplevel) { codep--; DEBUG("pseudo"); dopseudo(); } else goto doreturn; } else { #ifndef NDEBUG chkregs(); #endif n = *bp++; assert(n>0 && n<=MAXRULE); if (n>1) { mindistance = MAXINT; npos=0; for(i=0;i1) { /* * More than 1 tokenpattern is a candidate. * Decision has to be made by lookahead. */ SAVEST; mincost = costlimit-totalcost+1; for(i=0;icostlimit) { totalcost += mincost; BROKE(); } } else { cindex = pos[0]; } } else { getint(cindex,bp); } gotit: /* * Now cindex contains the code-index of the best candidate * so proceed to use it. */ codep = &coderules[cindex]; } break; case DO_COERC: DEBUG("COERC"); tokpatlen=1; inscoerc=1; break; case DO_XXMATCH: DEBUG("XXMATCH"); case DO_XMATCH: DEBUG("XMATCH"); tokpatlen=(codep[-1]>>5)&07; for (i=0;i>5)&07; for(i=0;i=fakestack) { size=tsize(tp); while (i= fakestack) { size = tsize(tp); lsize= ssize(tokexp[i]); if (size != lsize) { /* find coercion */ #ifdef MAXSPLIT sret = split(tp,&tokexp[i],ply,toplevel); if (sret==0) { #endif MAXSPLIT totalcost += stackupto(tp,ply,toplevel); CHKCOST(); break; #ifdef MAXSPLIT } i += sret; #endif MAXSPLIT } else i += 1; tp--; } nextmatch: tp = &fakestack[stackheight-1]; i=0; nregneeded = 0; while (i=fakestack) { if (!match(tp,&machsets[tokexp[i]],0)) { cp = findcoerc(tp, &machsets[tokexp[i]]); if (cp==0) { for (j=0;jc3_prop==0) { totalcost+=docoerc(tp,cp,ply,toplevel,0); CHKCOST(); } else { assert(nregneededstackheight) { stackpad = tokpatlen-stackheight; for (j=stackheight-1;j>=0;j--) fakestack[j+stackpad] = fakestack[j]; for (j=0;j=fakestack) { cp = findcoerc((token_p) 0, &machsets[tokexp[i]]); if (cp==0) { assert(!toplevel); for (j=0;jc3_prop==0) { totalcost+=docoerc(tp,cp,ply,toplevel,0); CHKCOST(); } else { assert(nregneededp_next; for (i=0,t=0;ip_rar[i]); if (tcostlimit) { if (besttup) myfree(besttup); if (stackpad!=tokpatlen) { if (stackpad) { if (costlimitp_rar[i]); myfree(besttup); break; case DO_REMOVE: DEBUG("REMOVE"); if (codep[-1]&32) { getint(texpno,codep); getint(nodeno,codep); } else { getint(texpno,codep); nodeno=0; } for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--) if (match(tp,&machsets[texpno],nodeno)) { /* investigate possible coercion to register */ totalcost += stackupto(tp,ply,toplevel); CHKCOST(); break; } for (rp=machregs+2;rpr_contents,&machsets[texpno],nodeno)) rp->r_contents.t_token=0; break; case DO_RREMOVE: /* register remove */ getint(nodeno,codep); result=compute(&enodes[nodeno]); assert(result.e_typ==EV_REG); for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--) if (tp->t_token==-1) { if(tp->t_att[0].ar==result.e_v.e_reg) goto gotone; } else { tdp = &tokens[tp->t_token]; for(i=0;it_type[i]==EV_REG && tp->t_att[i].ar==result.e_v.e_reg) goto gotone; } break; gotone: /* investigate possible coercion to register */ totalcost += stackupto(tp,ply,toplevel); CHKCOST(); break; case DO_DEALLOCATE: DEBUG("DEALLOCATE"); getint(tinstno,codep); instance(tinstno,&token); if (token.t_token==-1) chrefcount(token.t_att[0].ar,-1,TRUE); else { tdp= &tokens[token.t_token]; for (i=0;it_type[i]==EV_REG) chrefcount(token.t_att[i].ar,-1,TRUE); } break; case DO_REALLOCATE: DEBUG("REALLOCATE"); for(rp=machregs;rpr_tcount) { rp->r_refcount -= rp->r_tcount; rp->r_tcount = 0; } break; case DO_ALLOCATE: DEBUG("ALLOCATE"); if (codep[-1]&32) { getint(propno,codep); getint(tinstno,codep); } else { getint(propno,codep); tinstno=0; } instance(tinstno,&token); if (!forced) { do { npos=exactmatch=0; for(rpp=reglist[propno];rp= *rpp; rpp++) if (getrefcount(rp-machregs)==0) { pos[npos++] = rp-machregs; if (eqtoken(&rp->r_contents,&token)) exactmatch++; } /* * Now pos[] contains all free registers with desired * property. If none then some stacking has to take place. */ if (npos==0) { if (stackheight<=tokpatlen) { if (!toplevel) { totalcost = INFINITY; BROKE(); } else { fatal("No regs available"); } } totalcost += stackupto( &fakestack[0],ply,toplevel); CHKCOST(); } } while (npos==0); if (!exactmatch) { npos2=npos; for(i=0;icostlimit) { totalcost = INFINITY; BROKE(); } } } else { decision = forced; if (getrefcount(decision)!=0) { totalcost = INFINITY; BROKE(); } token2.t_token = -1; } chrefcount(decision,1,FALSE); token2.t_att[0].ar=decision; if (token.t_token != 0) { totalcost+=move(&token,&token2,ply,toplevel,MAXINT); CHKCOST(); } else erasereg(decision); allreg[nallreg++]=decision; break; case DO_LOUTPUT: DEBUG("LOUTPUT"); getint(stringno,codep); getint(nodeno,codep); if (toplevel) { gencode(codestrings[stringno]); genexpr(nodeno); } break; case DO_ROUTPUT: DEBUG("ROUTPUT"); i=((codep[-1]>>5)&07); do { getint(stringno,codep); if (toplevel) { gencode(codestrings[stringno]); gennl(); } } while (i--); break; case DO_MOVE: DEBUG("MOVE"); getint(tinstno,codep); instance(tinstno,&token); getint(tinstno,codep); instance(tinstno,&token2); totalcost += move(&token,&token2,ply,toplevel,costlimit-totalcost+1); CHKCOST(); break; case DO_ERASE: DEBUG("ERASE"); getint(nodeno,codep); result=compute(&enodes[nodeno]); assert(result.e_typ==EV_REG); erasereg(result.e_v.e_reg); break; case DO_TOKREPLACE: DEBUG("TOKREPLACE"); assert(stackheight>=tokpatlen); repllen=(codep[-1]>>5)&07; for(i=0;i>5)&07; j=emp-emlines; if (emrepllen>j) { assert(nemlines+emrepllen-j=0;i--) emlines[i+emrepllen-j] = emlines[i]; nemlines += emrepllen-j; emp += emrepllen-j; } emp -= emrepllen; for (i=0;i