static char *sccsid ="%W% (Berkeley) %G%"; # include "mfile2" int maxargs = { -1 }; stoasg( p, o ) register NODE *p; { /* should the assignment op p be stored, given that it lies as the right operand of o (or the left, if o==UNARY MUL) */ /* if( p->in.op == INCR || p->in.op == DECR ) return; if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG); */ } deltest( p ) register NODE *p; { /* should we delay the INCR or DECR operation p */ p = p->in.left; return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG ); } autoincr( p ) NODE *p; { register NODE *q = p->in.left, *r; if( q->in.op == INCR && (r=q->in.left)->in.op == REG && ISPTR(q->in.type) && p->in.type == DECREF(q->in.type) && tlen(p) == q->in.right->tn.lval ) return(1); return(0); } mkadrs(p) register NODE *p; { register o; o = p->in.op; if( asgop(o) ){ if( p->in.left->in.su >= p->in.right->in.su ){ if( p->in.left->in.op == UNARY MUL ){ SETSTO( p->in.left->in.left, INTEMP ); } else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ SETSTO( p->in.left->in.left->in.left, INTEMP ); } else { /* should be only structure assignment */ SETSTO( p->in.left, INTEMP ); } } else SETSTO( p->in.right, INTEMP ); } else { if( p->in.left->in.su > p->in.right->in.su ){ SETSTO( p->in.left, INTEMP ); } else { SETSTO( p->in.right, INTEMP ); } } } notoff( t, r, off, cp) CONSZ off; char *cp; { /* is it legal to make an OREG or NAME entry which has an /* offset of off, (from a register of r), if the /* resulting thing had type t */ /* if( r == R0 ) return( 1 ); /* NO */ return(0); /* YES */ } # define max(x,y) ((x)<(y)?(y):(x)) sucomp( p ) register NODE *p; { /* set the su field in the node to the sethi-ullman number, or local equivalent */ register o, ty, sul, sur, r; o = p->in.op; ty = optype( o ); p->in.su = szty( p->in.type ); /* 2 for float or double, else 1 */; if( ty == LTYPE ){ if( o == OREG ){ r = p->tn.rval; /* oreg cost is (worst case) 1 + number of temp registers used */ if( R2TEST(r) ){ if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su; if( istreg(R2UPK2(r)) ) ++p->in.su; } else { if( istreg( r ) ) ++p->in.su; } } if( p->in.su == szty(p->in.type) && (p->in.op!=REG || !istreg(p->tn.rval)) && (p->in.type==INT || p->in.type==UNSIGNED || p->in.type==DOUBLE) ) p->in.su = 0; return; } else if( ty == UTYPE ){ switch( o ) { case UNARY CALL: case UNARY STCALL: p->in.su = fregs; /* all regs needed */ return; default: p->in.su = p->in.left->in.su + (szty( p->in.type ) > 1 ? 2 : 0) ; return; } } /* If rhs needs n, lhs needs m, regular su computation */ sul = p->in.left->in.su; sur = p->in.right->in.su; if( o == ASSIGN ){ /* computed by doing right, then left (if not in mem), then doing it */ p->in.su = max(sur,sul+1); return; } if( o == CALL || o == STCALL ){ /* in effect, takes all free registers */ p->in.su = fregs; return; } if( o == STASG ){ /* right, then left */ p->in.su = max( max( 1+sul, sur), fregs ); return; } if( asgop(o) ){ /* computed by doing right, doing left address, doing left, op, and store */ p->in.su = max(sur,sul+2); /* if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs); */ return; } switch( o ){ case ANDAND: case OROR: case QUEST: case COLON: case COMOP: p->in.su = max( max(sul,sur), 1); return; case PLUS: case OR: case ER: /* commutative ops; put harder on left */ if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ register NODE *temp; temp = p->in.left; p->in.left = p->in.right; p->in.right = temp; } break; } /* binary op, computed by left, then right, then do op */ p->in.su = max(sul,szty(p->in.right->in.type)+sur); /* if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs); */ } int radebug = 0; rallo( p, down ) NODE *p; { /* do register allocation */ register o, type, down1, down2, ty; if( radebug ) printf( "rallo( %o, %d )\n", p, down ); down2 = NOPREF; p->in.rall = down; down1 = ( down &= ~MUSTDO ); ty = optype( o = p->in.op ); type = p->in.type; if( type == DOUBLE || type == FLOAT ){ if( o == FORCE ) down1 = R0|MUSTDO; } else switch( o ) { case ASSIGN: down1 = NOPREF; down2 = down; break; /* case MUL: case DIV: case MOD: down1 = R3|MUSTDO; down2 = R5|MUSTDO; break; case ASG MUL: case ASG DIV: case ASG MOD: p->in.left->in.rall = down1 = R3|MUSTDO; if( p->in.left->in.op == UNARY MUL ){ rallo( p->in.left->in.left, R4|MUSTDO ); } else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ rallo( p->in.left->in.left->in.left, R4|MUSTDO ); } else rallo( p->in.left, R3|MUSTDO ); rallo( p->in.right, R5|MUSTDO ); return; */ case CALL: case STASG: case EQ: case NE: case GT: case GE: case LT: case LE: case NOT: case ANDAND: case OROR: down1 = NOPREF; break; case FORCE: down1 = R0|MUSTDO; break; } if( ty != LTYPE ) rallo( p->in.left, down1 ); if( ty == BITYPE ) rallo( p->in.right, down2 ); } offstar( p ) register NODE *p; { if( p->in.op == PLUS ) { if( p->in.left->in.su == fregs ) { order( p->in.left, INTAREG|INAREG ); return; } else if( p->in.right->in.su == fregs ) { order( p->in.right, INTAREG|INAREG ); return; } if( p->in.left->in.op==LS && (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) { order( p->in.left->in.left, INTAREG|INAREG ); return; } if( p->in.right->in.op==LS && (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) { order( p->in.right->in.left, INTAREG|INAREG ); return; } if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) { order( p->in.left, INTAREG|INAREG ); return; } else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) { order(p->in.right, INTAREG|INAREG); return; } } } if( p->in.op == PLUS || p->in.op == MINUS ){ if( p->in.right->in.op == ICON ){ p = p->in.left; order( p , INTAREG|INAREG); return; } } if( p->in.op == UNARY MUL && !canaddr(p) ) { offstar( p->in.left ); return; } order( p, INTAREG|INAREG ); } setincr( p ) register NODE *p; { p = p->in.left; if( p->in.op == UNARY MUL ){ offstar( p ); return( 1 ); } return( 0 ); } setbin( p ) register NODE *p; { register ro, rt; rt = p->in.right->in.type; ro = p->in.right->in.op; if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ if( ro == UNARY MUL ) { offstar( p->in.right->in.left ); return(1); } else { order( p->in.right, INAREG|INTAREG|SOREG ); return(1); } } if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); return(1); } else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ offstar( p->in.right->in.left ); return(1); } else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG && ro != NAME && ro != OREG && ro != ICON ) ){ order( p->in.right, INAREG|INBREG ); return(1); } /* else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */ /* order( p->in.right, INAREG ); return( 1 ); } */ return(0); } setstr( p ) register NODE *p; { /* structure assignment */ if( p->in.right->in.op != REG ){ order( p->in.right, INTAREG ); return(1); } p = p->in.left; if( p->in.op != NAME && p->in.op != OREG ){ if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); order( p->in.left, INTAREG ); return( 1 ); } return( 0 ); } setasg( p ) register NODE *p; { /* setup for assignment operator */ if( !canaddr(p->in.right) ) { if( p->in.right->in.op == UNARY MUL ) offstar(p->in.right->in.left); else order( p->in.right, INAREG|INBREG|SOREG ); return(1); } if( p->in.left->in.op == UNARY MUL ) { offstar( p->in.left->in.left ); return(1); } if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ offstar( p->in.left->in.left->in.left ); return(1); } /* FLD patch */ if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) { order( p->in.right, INAREG); return(1); } /* end of FLD patch */ return(0); } setasop( p ) register NODE *p; { /* setup for =ops */ register rt, ro; rt = p->in.right->in.type; ro = p->in.right->in.op; if( ro == UNARY MUL && rt != CHAR ){ offstar( p->in.right->in.left ); return(1); } if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){ order( p->in.right, INAREG|INBREG ); return(1); } /* if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){ order( p->in.right, INAREG ); return(1); } */ p = p->in.left; if( p->in.op == FLD ) p = p->in.left; switch( p->in.op ){ case REG: case ICON: case NAME: case OREG: return(0); case UNARY MUL: if( p->in.left->in.op==OREG ) return(0); else offstar( p->in.left ); return(1); } cerror( "illegal setasop" ); } int crslab = 9999; /* Honeywell */ getlab(){ return( crslab-- ); } deflab( l ){ printf( "L%d:\n", l ); } genargs( p, ptemp ) register NODE *p, *ptemp; { register NODE *pasg; register align; register size; register TWORD type; /* generate code for the arguments */ /* first, do the arguments on the right */ while( p->in.op == CM ){ genargs( p->in.right, ptemp ); p->in.op = FREE; p = p->in.left; } if( p->in.op == STARG ){ /* structure valued argument */ size = p->stn.stsize; align = p->stn.stalign; if( p->in.left->in.op == ICON ){ p->in.op = FREE; p= p->in.left; } else { /* make it look beautiful... */ p->in.op = UNARY MUL; canon( p ); /* turn it into an oreg */ if( p->in.op != OREG ){ offstar( p->in.left ); canon( p ); if( p->in.op != OREG ){ offstar( p->in.left ); canon( p ); if( p->in.op != OREG ) cerror( "stuck starg" ); } } } ptemp->tn.lval = 0; /* all moves to (sp) */ pasg = talloc(); pasg->in.op = STASG; pasg->stn.stsize = size; pasg->stn.stalign = align; pasg->in.right = p; pasg->in.left = tcopy( ptemp ); /* the following line is done only with the knowledge that it will be undone by the STASG node, with the offset (lval) field retained */ if( p->in.op == OREG ) p->in.op = REG; /* only for temporaries */ order( pasg, FORARG ); ptemp->tn.lval += size; return; } /* ordinary case */ order( p, FORARG ); } argsize( p ) register NODE *p; { register t; t = 0; if( p->in.op == CM ){ t = argsize( p->in.left ); p = p->in.right; } if( p->in.type == DOUBLE || p->in.type == FLOAT ){ SETOFF( t, 4 ); return( t+8 ); } else if( p->in.op == STARG ){ SETOFF( t, 4 ); /* alignment */ return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ } else { SETOFF( t, 4 ); return( t+4 ); } }