/* * (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 */ #include #include #include #include "assert.h" #include #include "param.h" #include "tables.h" #include "types.h" #include #include "data.h" #include "result.h" #include "extern.h" #include "subr.h" #include "reg.h" #include "salloc.h" #include "gencode.h" #include "regvar.h" unsigned codegen(); extern unsigned cc1,cc2,cc3,cc4; int match(register token_p tp, register set_p tep, int optexp) { register int bitno; token_p ct; result_t result; if (tp->t_token == -1) { /* register frame */ bitno = tp->t_att[0].ar+1; if (tep->set_val[bitno>>4]&(1<<(bitno&017))) if (tep->set_val[0]&1 || getrefcount(tp->t_att[0].ar, FALSE)<=1) goto oklabel; return(0); } else { /* token frame */ bitno = tp->t_token+NREGS+1; if ((tep->set_val[bitno>>4]&(1<<(bitno&017)))==0) return(0); } oklabel: if (optexp==0) return(1); ct=curtoken; curtoken=tp; result=compute(&enodes[optexp]); curtoken=ct; return(result.e_v.e_con); } void instance(int instno,register token_p token) { register inst_p inp; int i; token_p tp; struct reginfo *rp; int regno; result_t result; if (instno==0) { token->t_token = 0; for(i=0;it_att[i].aw=0; return; } inp= &tokeninstances[instno]; switch(inp->in_which) { default: assert(FALSE); case IN_COPY: tp= &fakestack[stackheight-inp->in_info[0]]; if (inp->in_info[1]==0) { *token = *tp; } else { token->t_token= -1; #if MAXMEMBERS!=0 if (tp->t_token == -1) { rp = &machregs[tp->t_att[0].ar]; token->t_att[0].ar=rp->r_members[inp->in_info[1]-1]; } else { #endif assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG); token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar; #if MAXMEMBERS!=0 } #endif } return; case IN_RIDENT: token->t_token= -1; token->t_att[0].ar= inp->in_info[0]; return; #ifdef REGVARS case IN_REGVAR: result=compute(&enodes[inp->in_info[0]]); i=isregvar((long)result.e_v.e_con); assert(i>0); token->t_token= -1; token->t_att[0].ar = i; return; #endif case IN_ALLOC: token->t_token= -1; regno=allreg[inp->in_info[0]]; #if MAXMEMBERS!=0 if (inp->in_info[1]) regno=machregs[regno].r_members[inp->in_info[1]-1]; #endif token->t_att[0].ar = regno; return; case IN_DESCR: token->t_token=inp->in_info[0]; for (i=0;iin_info[i+1]==0) { assert(tokens[token->t_token].t_type[i]==0); token->t_att[i].aw=0; } else { result=compute(&enodes[inp->in_info[i+1]]); assert(tokens[token->t_token].t_type[i]==result.e_typ); if (result.e_typ==EV_INT) token->t_att[i].aw=result.e_v.e_con; else if (result.e_typ==EV_STR) token->t_att[i].as= result.e_v.e_str; else token->t_att[i].ar=result.e_v.e_reg; } return; } } void cinstance(int instno,register token_p token, register token_p tp,int regno) { register inst_p inp; int i; struct reginfo *rp; result_t result; int sh; /* saved stackheight */ assert(instno!=0); inp= &tokeninstances[instno]; switch(inp->in_which) { default: assert(FALSE); case IN_COPY: assert(inp->in_info[0] == 1); if (inp->in_info[1]==0) { *token = *tp; } else { token->t_token= -1; #if MAXMEMBERS!=0 if (tp->t_token == -1) { rp = &machregs[tp->t_att[0].ar]; token->t_att[0].ar=rp->r_members[inp->in_info[1]-1]; } else { #endif assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG); token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar; #if MAXMEMBERS!=0 } #endif } return; case IN_RIDENT: token->t_token= -1; token->t_att[0].ar= inp->in_info[0]; return; case IN_ALLOC: token->t_token= -1; assert(inp->in_info[0]==0); #if MAXMEMBERS!=0 if (inp->in_info[1]) regno=machregs[regno].r_members[inp->in_info[1]-1]; #endif token->t_att[0].ar = regno; return; case IN_DESCR: sh = stackheight; stackheight = tp - fakestack + 1; token->t_token=inp->in_info[0]; for (i=0;iin_info[i+1]==0) { assert(tokens[token->t_token].t_type[i]==0); token->t_att[i].aw=0; } else { result=compute(&enodes[inp->in_info[i+1]]); assert(tokens[token->t_token].t_type[i]==result.e_typ); if (result.e_typ==EV_INT) token->t_att[i].aw=result.e_v.e_con; else if (result.e_typ==EV_STR) token->t_att[i].as= result.e_v.e_str; else token->t_att[i].ar=result.e_v.e_reg; } stackheight = sh; return; } } int eqtoken(token_p tp1,token_p tp2) { register int i; register tkdef_p tdp; if (tp1->t_token!=tp2->t_token) return(0); if (tp1->t_token==0) return(1); if (tp1->t_token==-1) { if (tp1->t_att[0].ar!=tp2->t_att[0].ar) return(0); return(1); } tdp = &tokens[tp1->t_token]; for (i=0;it_type[i]) { default: return(1); case EV_INT: if (tp1->t_att[i].aw != tp2->t_att[i].aw) return(0); break; case EV_REG: if (tp1->t_att[i].ar != tp2->t_att[i].ar) return(0); break; case EV_STR: if (strcmp(tp1->t_att[i].as, tp2->t_att[i].as)) return(0); break; } return(1); } int distance(int cindex) { register byte *bp; register int i; register token_p tp; int tokexp,tpl; int expsize,toksize,exact; int xsekt=0; bp = &coderules[cindex]; switch( (*bp)&037 ) { default: return(stackheight==0 ? 0 : 100); case DO_MATCH: break; case DO_XXMATCH: xsekt++; case DO_XMATCH: xsekt++; break; } tpl= ((*bp++)>>5)&07; if (stackheight < tpl) { if (xsekt) return(MAXINT); tpl = stackheight; } else if (stackheight != tpl && xsekt==2) return(MAXINT); exact=0; tp= &fakestack[stackheight-1]; for (i=0;itoksize) return(100); if (expsizet_token==-1) return(machregs[tp->t_att[0].ar].r_size); return(tokens[tp->t_token].t_size); } #ifdef MAXSPLIT int instsize(int tinstno,token_p tp) { inst_p inp; struct reginfo *rp; inp = &tokeninstances[tinstno]; switch(inp->in_which) { default: assert(FALSE); case IN_COPY: assert(inp->in_info[0]==1); #if MAXMEMBERS!=0 if (inp->in_info[1]==0) #endif return(tsize(tp)); #if MAXMEMBERS!=0 else { assert(tp->t_token == -1); rp = &machregs[tp->t_att[0].ar]; return(machregs[rp->r_members[inp->in_info[1]-1]].r_size); } #endif case IN_RIDENT: return(machregs[inp->in_info[0]].r_size); case IN_ALLOC: assert(FALSE); /* cannot occur in splitting coercion */ case IN_DESCR: return(tokens[inp->in_info[0]].t_size); } } #endif /* MAXSPLIT */ void tref(register token_p tp,int amount) { register int i; register tkdef_p tdp; if (tp->t_token==-1) chrefcount(tp->t_att[0].ar,amount,FALSE); else { tdp= &tokens[tp->t_token]; for(i=0;it_type[i]==EV_REG) chrefcount(tp->t_att[i].ar,amount,FALSE); } } #define MAXSAVE 10 #ifdef MAXSPLIT int split(token_p tp,int *ip,int ply,int toplevel) { c2_p cp; token_t savestack[MAXSAVE]; int ok; register int i; int diff; token_p stp; int tpl; for (cp=c2coercs;cp< &c2coercs[NC2]; cp++) { if (!match(tp,&machsets[cp->c2_texpno],0)) continue; ok=1; for (i=0; ok && ic2_nsplit;i++) { if (ip[i]==0) goto found; if (instsize(cp->c2_repl[i],tp) != ssize(ip[i])) ok=0; } goto found; } return(0); found: assert(stackheight+cp->c2_nsplit-1c2_codep],ply,toplevel,MAXINT,0); tokpatlen = tpl; for (i=0;ic2_nsplit); } #endif /* MAXSPLIT */ unsigned docoerc(token_p tp,c3_p cp,int ply,int toplevel,int forced) { token_t savestack[MAXSAVE]; token_p stp; int i,diff; unsigned int cost; int tpl; /* saved tokpatlen */ stp = &fakestack[stackheight-1]; diff = stp -tp; assert(diff<=MAXSAVE); for (i=1;i<=diff;i++) savestack[i-1] = tp[i]; stackheight -= diff; tpl = tokpatlen; tokpatlen = 1; cost = codegen(&coderules[cp->c3_codep],ply,toplevel,MAXINT,forced); tokpatlen = tpl; for (i=0;ic1_texpno],cp->c1_expr)) { if (cp->c1_prop>=0) { for (rpp=reglist[cp->c1_prop]; (rp = *rpp)!=0 && getrefcount((int)(rp-machregs), TRUE)!=0; rpp++) ; if (rp==0) continue; /* look for other possibility */ } stp = &fakestack[stackheight-1]; diff = stp -tp; assert(diff<=MAXFSTACK); for (i=1;i<=diff;i++) savestack[i-1] = tp[i]; stackheight -= diff; tpl = tokpatlen; tokpatlen = 1; nareg = nallreg; for (i=0;ic1_prop>=0) { nallreg=1; allreg[0] = rp-machregs; chrefcount(allreg[0],1,FALSE); } else nallreg=0; totalcost+= codegen(&coderules[cp->c1_codep],ply,toplevel,MAXINT,0); totalcost+= costcalc(cp->c1_cost); tokpatlen = tpl; for (i=0;ic3_texpno],0)) continue; } else { if (cp->c3_texpno!=0) continue; } if (cp->c3_prop==0) { /* no reg needed */ cinstance(cp->c3_repl,&rtoken,tp,0); if (match(&rtoken,tep,0)) return(cp); } else { curreglist = (rl_p) myalloc(sizeof (rl_t)); curreglist->rl_n = 0; for (rpp=reglist[cp->c3_prop];*rpp;rpp++) { i = *rpp - machregs; cinstance(cp->c3_repl,&rtoken,tp,i); if (match(&rtoken,tep,0)) curreglist->rl_list[curreglist->rl_n++] = i; } if (curreglist->rl_n != 0) return(cp); myfree(curreglist); } } return(0); /* nothing found */ } static void error_str(char *s, va_list argptr) { fprintf(stderr,"Error: "); vfprintf(stderr, s, argptr); fprintf(stderr,"\n"); out_finish(); abort(); exit(EXIT_FAILURE); } void error(char *s, ...) { va_list ap; va_start(ap, s); error_str(s, ap); va_end(ap); } void fatal(char *s, ...) { va_list ap; va_start(ap, s); error_str(s, ap); va_end(ap); } #ifndef NDEBUG void badassertion(char* asstr,char *file,int line) { fatal("Assertion \"%s\" failed %s(%d)",asstr,file,line); } #endif int max(int a,int b) { return(a>b ? a : b); }