# include "mfile2" int fldsz, fldshf; static int mamask[] = { /* masks for matching dope with shapes */ SIMPFLG, /* OPSIMP */ SIMPFLG|ASGFLG, /* ASG OPSIMP */ COMMFLG, /* OPCOMM */ COMMFLG|ASGFLG, /* ASG OPCOMM */ MULFLG, /* OPMUL */ MULFLG|ASGFLG, /* ASG OPMUL */ DIVFLG, /* OPDIV */ DIVFLG|ASGFLG, /* ASG OPDIV */ UTYPE, /* OPUNARY */ TYFLG, /* ASG OPUNARY is senseless */ LTYPE, /* OPLEAF */ TYFLG, /* ASG OPLEAF is senseless */ 0, /* OPANY */ ASGOPFLG|ASGFLG, /* ASG OPANY */ LOGFLG, /* OPLOG */ TYFLG, /* ASG OPLOG is senseless */ FLOFLG, /* OPFLOAT */ FLOFLG|ASGFLG, /* ASG OPFLOAT */ SHFFLG, /* OPSHFT */ SHFFLG|ASGFLG, /* ASG OPSHIFT */ SPFLG, /* OPLTYPE */ TYFLG, /* ASG OPLTYPE is senseless */ }; int sdebug = 0; tshape( p, shape ) NODE *p; { /* return true if shape is appropriate for the node p side effect for SFLD is to set up fldsz,etc */ register o, mask; o = p->op; if( sdebug ){ printf( "tshape( %o, %o), op = %d\n", p, shape, o ); } if( shape & SPECIAL ){ switch( shape ){ case SZERO: case SONE: case SMONE: if( o != ICON || p->name[0] ) return(0); if( p->lval == 0 && shape == SZERO ) return(1); else if( p->lval == 1 && shape == SONE ) return(1); else if( p->lval == -1 && shape == SMONE ) return(1); else return(0); default: return( special( p, shape ) ); } } if( shape & SANY ) return(1); if( (shape&INTEMP) && shtemp(p) ) return(1); if( (shape&SWADD) && (o==NAME||o==OREG) ){ if( BYTEOFF(p->lval) ) return(0); } switch( o ){ case NAME: return( shape&SNAME ); case ICON: mask = SCON; return( shape & mask ); case FLD: if( shape & SFLD ){ if( !flshape( p->left ) ) return(0); /* it is a FIELD shape; make side-effects */ o = p->rval; fldsz = UPKFSZ(o); # ifdef RTOLBYTES fldshf = UPKFOFF(o); # else fldshf = SZINT - fldsz - UPKFOFF(o); # endif return(1); } return(0); case CCODES: return( shape&SCC ); case REG: /* distinctions: SAREG any scalar register STAREG any temporary scalar register SBREG any lvalue (index) register STBREG any temporary lvalue register */ mask = isbreg( p->rval ) ? SBREG : SAREG; if( istreg( p->rval ) && busy[p->rval]<=1 ) mask |= mask==SAREG ? STAREG : STBREG; return( shape & mask ); case OREG: return( shape & SOREG ); case UNARY MUL: /* return STARNM or STARREG or 0 */ return( shumul(p->left) & shape ); } return(0); } int tdebug = 0; ttype( t, tword ) TWORD t; { /* does the type t match tword */ if( tword & TANY ) return(1); if( tdebug ){ printf( "ttype( %o, %o )\n", t, tword ); } if( ISPTR(t) && (tword&TPTRTO) ) { do { t = DECREF(t); } while ( ISARY(t) ); /* arrays that are left are usually only in structure references... */ return( ttype( t, tword&(~TPTRTO) ) ); } if( t != BTYPE(t) ) return( tword & TPOINT ); /* TPOINT means not simple! */ if( tword & TPTRTO ) return(0); switch( t ){ case CHAR: return( tword & TCHAR ); case SHORT: return( tword & TSHORT ); case STRTY: case UNIONTY: return( tword & TSTRUCT ); case INT: return( tword & TINT ); case UNSIGNED: return( tword & TUNSIGNED ); case USHORT: return( tword & TUSHORT ); case UCHAR: return( tword & TUCHAR ); case ULONG: return( tword & TULONG ); case LONG: return( tword & TLONG ); case FLOAT: return( tword & TFLOAT ); case DOUBLE: return( tword & TDOUBLE ); } return(0); } struct optab *rwtable; struct optab *opptr[DSIZE]; setrew(){ /* set rwtable to first value which allows rewrite */ register struct optab *q; register int i; for( q = table; q->op != FREE; ++q ){ if( q->needs == REWRITE ){ rwtable = q; goto more; } } cerror( "bad setrew" ); more: for( i=0; iop != FREE; ++q ){ /* beware; things like LTYPE that match multiple things in the tree must not try to look at the NIL at this stage of things! Put something else first in table.c */ /* at one point, the operator matching was 15% of the total comile time; thus, the function call that was here was removed... */ if( q->op < OPSIMP ){ if( q->op==i ) break; } else { register opmtemp; if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){ if( i==NAME || i==ICON || i==OREG ) break; else if( shltype( i, NIL ) ) break; } else if( (dope[i]&(opmtemp|ASGFLG)) == opmtemp ) break; } } opptr[i] = q; } } } match( p, cookie ) NODE *p; { /* called by: order, gencall look for match in table and generate code if found unless entry specified REWRITE. returns MDONE, MNOPE, or rewrite specification from table */ register struct optab *q; register NODE *r; rcount(); if( cookie == FORREW ) q = rwtable; else q = opptr[p->op]; for( ; q->op != FREE; ++q ){ /* at one point the call that was here was over 15% of the total time; thus the function call was expanded inline */ if( q->op < OPSIMP ){ if( q->op!=p->op ) continue; } else { register opmtemp; if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){ if( p->op!=NAME && p->op!=ICON && p->op!= OREG && ! shltype( p->op, p ) ) continue; } else if( (dope[p->op]&(opmtemp|ASGFLG)) != opmtemp ) continue; } if( !(q->visit & cookie ) ) continue; r = getlr( p, 'L' ); /* see if left child matches */ if( !tshape( r, q->lshape ) ) continue; if( !ttype( r->type, q->ltype ) ) continue; r = getlr( p, 'R' ); /* see if right child matches */ if( !tshape( r, q->rshape ) ) continue; if( !ttype( r->type, q->rtype ) ) continue; /* REWRITE means no code from this match but go ahead and rewrite node to help future match */ if( q->needs & REWRITE ) return( q->rewrite ); if( !allo( p, q ) ) continue; /* if can't generate code, skip entry */ /* resources are available */ expand( p, cookie, q->cstring ); /* generate code */ reclaim( p, q->rewrite, cookie ); return(MDONE); } return(MNOPE); } int rtyflg = 0; expand( p, cookie, cp ) NODE *p; register char *cp; { /* generate code by interpreting table entry */ CONSZ val; rtyflg = 0; for( ; *cp; ++cp ){ switch( *cp ){ default: PUTCHAR( *cp ); continue; /* this is the usual case... */ case 'T': /* rewrite register type is suppressed */ rtyflg = 1; continue; case 'Z': /* special machine dependent operations */ zzzcode( p, *++cp ); continue; case 'F': /* this line deleted if FOREFF is active */ if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */ continue; case 'S': /* field size */ printf( "%d", fldsz ); continue; case 'H': /* field shift */ printf( "%d", fldshf ); continue; case 'M': /* field mask */ case 'N': /* complement of field mask */ val = 1; val <<= fldsz; --val; val <<= fldshf; adrcon( *cp=='M' ? val : ~val ); continue; case 'L': /* output special label field */ printf( "%d", p->label ); continue; case 'O': /* opcode string */ hopcode( *++cp, p->op ); continue; case 'B': /* byte offset in word */ val = getlr(p,*++cp)->lval; val = BYTEOFF(val); printf( CONFMT, val ); continue; case 'C': /* for constant value only */ conput( getlr( p, *++cp ) ); continue; case 'I': /* in instruction */ insput( getlr( p, *++cp ) ); continue; case 'A': /* address of */ adrput( getlr( p, *++cp ) ); continue; case 'U': /* for upper half of address, only */ upput( getlr( p, *++cp ) ); continue; } } } NODE * getlr( p, c ) NODE *p; { /* return the pointer to the left or right side of p, or p itself, depending on the optype of p */ switch( c ) { case '1': case '2': case '3': return( &resc[c-'1'] ); case 'L': return( optype( p->op ) == LTYPE ? p : p->left ); case 'R': return( optype( p->op ) != BITYPE ? p : p->right ); } cerror( "bad getlr: %c", c ); /* NOTREACHED */ }