1*16409Sralph static char *sccsid ="@(#)order.c 1.2 (Berkeley) 04/23/84"; 29704Slinton # include "mfile2" 39704Slinton 49704Slinton int maxargs = { -1 }; 59704Slinton 69704Slinton stoasg( p, o ) register NODE *p; { 79704Slinton /* should the assignment op p be stored, 89704Slinton given that it lies as the right operand of o 99704Slinton (or the left, if o==UNARY MUL) */ 109704Slinton /* 119704Slinton if( p->in.op == INCR || p->in.op == DECR ) return; 129704Slinton if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG); 139704Slinton */ 149704Slinton } 159704Slinton 169704Slinton deltest( p ) register NODE *p; { 179704Slinton /* should we delay the INCR or DECR operation p */ 189704Slinton p = p->in.left; 199704Slinton return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG ); 209704Slinton } 219704Slinton 229704Slinton autoincr( p ) NODE *p; { 239704Slinton register NODE *q = p->in.left, *r; 249704Slinton 259704Slinton if( q->in.op == INCR && (r=q->in.left)->in.op == REG && 269704Slinton ISPTR(q->in.type) && p->in.type == DECREF(q->in.type) && 279704Slinton tlen(p) == q->in.right->tn.lval ) return(1); 289704Slinton 299704Slinton return(0); 309704Slinton } 319704Slinton 329704Slinton mkadrs(p) register NODE *p; { 339704Slinton register o; 349704Slinton 359704Slinton o = p->in.op; 369704Slinton 379704Slinton if( asgop(o) ){ 389704Slinton if( p->in.left->in.su >= p->in.right->in.su ){ 399704Slinton if( p->in.left->in.op == UNARY MUL ){ 409704Slinton SETSTO( p->in.left->in.left, INTEMP ); 419704Slinton } 429704Slinton else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 439704Slinton SETSTO( p->in.left->in.left->in.left, INTEMP ); 449704Slinton } 459704Slinton else { /* should be only structure assignment */ 469704Slinton SETSTO( p->in.left, INTEMP ); 479704Slinton } 489704Slinton } 499704Slinton else SETSTO( p->in.right, INTEMP ); 509704Slinton } 519704Slinton else { 529704Slinton if( p->in.left->in.su > p->in.right->in.su ){ 539704Slinton SETSTO( p->in.left, INTEMP ); 549704Slinton } 559704Slinton else { 569704Slinton SETSTO( p->in.right, INTEMP ); 579704Slinton } 589704Slinton } 599704Slinton } 609704Slinton 619704Slinton notoff( t, r, off, cp) CONSZ off; char *cp; { 629704Slinton /* is it legal to make an OREG or NAME entry which has an 639704Slinton /* offset of off, (from a register of r), if the 649704Slinton /* resulting thing had type t */ 659704Slinton 669704Slinton /* if( r == R0 ) return( 1 ); /* NO */ 679704Slinton return(0); /* YES */ 689704Slinton } 699704Slinton 709704Slinton # define max(x,y) ((x)<(y)?(y):(x)) 719704Slinton 729704Slinton sucomp( p ) register NODE *p; { 739704Slinton 749704Slinton /* set the su field in the node to the sethi-ullman 759704Slinton number, or local equivalent */ 769704Slinton 779704Slinton register o, ty, sul, sur, r; 789704Slinton 799704Slinton o = p->in.op; 809704Slinton ty = optype( o ); 819704Slinton p->in.su = szty( p->in.type ); /* 2 for float or double, else 1 */; 829704Slinton 839704Slinton if( ty == LTYPE ){ 849704Slinton if( o == OREG ){ 859704Slinton r = p->tn.rval; 869704Slinton /* oreg cost is (worst case) 1 + number of temp registers used */ 879704Slinton if( R2TEST(r) ){ 889704Slinton if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su; 899704Slinton if( istreg(R2UPK2(r)) ) ++p->in.su; 909704Slinton } 919704Slinton else { 929704Slinton if( istreg( r ) ) ++p->in.su; 939704Slinton } 949704Slinton } 959704Slinton if( p->in.su == szty(p->in.type) && 969704Slinton (p->in.op!=REG || !istreg(p->tn.rval)) && 979704Slinton (p->in.type==INT || p->in.type==UNSIGNED || p->in.type==DOUBLE) ) 989704Slinton p->in.su = 0; 999704Slinton return; 1009704Slinton } 1019704Slinton 1029704Slinton else if( ty == UTYPE ){ 1039704Slinton switch( o ) { 1049704Slinton case UNARY CALL: 1059704Slinton case UNARY STCALL: 1069704Slinton p->in.su = fregs; /* all regs needed */ 1079704Slinton return; 1089704Slinton 1099704Slinton default: 1109704Slinton p->in.su = p->in.left->in.su + (szty( p->in.type ) > 1 ? 2 : 0) ; 1119704Slinton return; 1129704Slinton } 1139704Slinton } 1149704Slinton 1159704Slinton 1169704Slinton /* If rhs needs n, lhs needs m, regular su computation */ 1179704Slinton 1189704Slinton sul = p->in.left->in.su; 1199704Slinton sur = p->in.right->in.su; 1209704Slinton 1219704Slinton if( o == ASSIGN ){ 1229704Slinton /* computed by doing right, then left (if not in mem), then doing it */ 1239704Slinton p->in.su = max(sur,sul+1); 1249704Slinton return; 1259704Slinton } 1269704Slinton 1279704Slinton if( o == CALL || o == STCALL ){ 1289704Slinton /* in effect, takes all free registers */ 1299704Slinton p->in.su = fregs; 1309704Slinton return; 1319704Slinton } 1329704Slinton 1339704Slinton if( o == STASG ){ 1349704Slinton /* right, then left */ 1359704Slinton p->in.su = max( max( 1+sul, sur), fregs ); 1369704Slinton return; 1379704Slinton } 1389704Slinton 1399704Slinton if( asgop(o) ){ 1409704Slinton /* computed by doing right, doing left address, doing left, op, and store */ 1419704Slinton p->in.su = max(sur,sul+2); 1429704Slinton /* 1439704Slinton if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs); 1449704Slinton */ 1459704Slinton return; 1469704Slinton } 1479704Slinton 1489704Slinton switch( o ){ 1499704Slinton case ANDAND: 1509704Slinton case OROR: 1519704Slinton case QUEST: 1529704Slinton case COLON: 1539704Slinton case COMOP: 1549704Slinton p->in.su = max( max(sul,sur), 1); 1559704Slinton return; 1569704Slinton 1579704Slinton case PLUS: 1589704Slinton case OR: 1599704Slinton case ER: 1609704Slinton /* commutative ops; put harder on left */ 1619704Slinton if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ 1629704Slinton register NODE *temp; 1639704Slinton temp = p->in.left; 1649704Slinton p->in.left = p->in.right; 1659704Slinton p->in.right = temp; 1669704Slinton } 1679704Slinton break; 1689704Slinton } 1699704Slinton 1709704Slinton /* binary op, computed by left, then right, then do op */ 1719704Slinton p->in.su = max(sul,szty(p->in.right->in.type)+sur); 1729704Slinton /* 1739704Slinton if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs); 1749704Slinton */ 1759704Slinton 1769704Slinton } 1779704Slinton 1789704Slinton int radebug = 0; 1799704Slinton 1809704Slinton rallo( p, down ) NODE *p; { 1819704Slinton /* do register allocation */ 1829704Slinton register o, type, down1, down2, ty; 1839704Slinton 1849704Slinton if( radebug ) printf( "rallo( %o, %d )\n", p, down ); 1859704Slinton 1869704Slinton down2 = NOPREF; 1879704Slinton p->in.rall = down; 1889704Slinton down1 = ( down &= ~MUSTDO ); 1899704Slinton 1909704Slinton ty = optype( o = p->in.op ); 1919704Slinton type = p->in.type; 1929704Slinton 1939704Slinton 1949704Slinton if( type == DOUBLE || type == FLOAT ){ 1959704Slinton if( o == FORCE ) down1 = R0|MUSTDO; 1969704Slinton } 1979704Slinton else switch( o ) { 1989704Slinton case ASSIGN: 1999704Slinton down1 = NOPREF; 2009704Slinton down2 = down; 2019704Slinton break; 2029704Slinton 2039704Slinton /* 2049704Slinton case MUL: 2059704Slinton case DIV: 2069704Slinton case MOD: 2079704Slinton down1 = R3|MUSTDO; 2089704Slinton down2 = R5|MUSTDO; 2099704Slinton break; 2109704Slinton 2119704Slinton case ASG MUL: 2129704Slinton case ASG DIV: 2139704Slinton case ASG MOD: 2149704Slinton p->in.left->in.rall = down1 = R3|MUSTDO; 2159704Slinton if( p->in.left->in.op == UNARY MUL ){ 2169704Slinton rallo( p->in.left->in.left, R4|MUSTDO ); 2179704Slinton } 2189704Slinton else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 2199704Slinton rallo( p->in.left->in.left->in.left, R4|MUSTDO ); 2209704Slinton } 2219704Slinton else rallo( p->in.left, R3|MUSTDO ); 2229704Slinton rallo( p->in.right, R5|MUSTDO ); 2239704Slinton return; 2249704Slinton */ 2259704Slinton 2269704Slinton case CALL: 2279704Slinton case STASG: 2289704Slinton case EQ: 2299704Slinton case NE: 2309704Slinton case GT: 2319704Slinton case GE: 2329704Slinton case LT: 2339704Slinton case LE: 2349704Slinton case NOT: 2359704Slinton case ANDAND: 2369704Slinton case OROR: 2379704Slinton down1 = NOPREF; 2389704Slinton break; 2399704Slinton 2409704Slinton case FORCE: 2419704Slinton down1 = R0|MUSTDO; 2429704Slinton break; 2439704Slinton 2449704Slinton } 2459704Slinton 2469704Slinton if( ty != LTYPE ) rallo( p->in.left, down1 ); 2479704Slinton if( ty == BITYPE ) rallo( p->in.right, down2 ); 2489704Slinton 2499704Slinton } 2509704Slinton 2519704Slinton offstar( p ) register NODE *p; { 2529704Slinton if( p->in.op == PLUS ) { 2539704Slinton if( p->in.left->in.su == fregs ) { 2549704Slinton order( p->in.left, INTAREG|INAREG ); 2559704Slinton return; 2569704Slinton } else if( p->in.right->in.su == fregs ) { 2579704Slinton order( p->in.right, INTAREG|INAREG ); 2589704Slinton return; 2599704Slinton } 2609704Slinton if( p->in.left->in.op==LS && 2619704Slinton (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) { 2629704Slinton order( p->in.left->in.left, INTAREG|INAREG ); 2639704Slinton return; 2649704Slinton } 2659704Slinton if( p->in.right->in.op==LS && 2669704Slinton (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) { 2679704Slinton order( p->in.right->in.left, INTAREG|INAREG ); 2689704Slinton return; 2699704Slinton } 2709704Slinton if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { 2719704Slinton if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) { 2729704Slinton order( p->in.left, INTAREG|INAREG ); 2739704Slinton return; 2749704Slinton } 2759704Slinton else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) { 2769704Slinton order(p->in.right, INTAREG|INAREG); 2779704Slinton return; 2789704Slinton } 2799704Slinton } 2809704Slinton } 2819704Slinton if( p->in.op == PLUS || p->in.op == MINUS ){ 2829704Slinton if( p->in.right->in.op == ICON ){ 2839704Slinton p = p->in.left; 2849704Slinton order( p , INTAREG|INAREG); 2859704Slinton return; 2869704Slinton } 2879704Slinton } 2889704Slinton 2899704Slinton if( p->in.op == UNARY MUL && !canaddr(p) ) { 2909704Slinton offstar( p->in.left ); 2919704Slinton return; 2929704Slinton } 2939704Slinton 2949704Slinton order( p, INTAREG|INAREG ); 2959704Slinton } 2969704Slinton 2979704Slinton setincr( p ) register NODE *p; { 2989704Slinton p = p->in.left; 2999704Slinton if( p->in.op == UNARY MUL ){ 3009704Slinton offstar( p ); 3019704Slinton return( 1 ); 3029704Slinton } 3039704Slinton return( 0 ); 3049704Slinton } 3059704Slinton 3069704Slinton setbin( p ) register NODE *p; { 3079704Slinton register ro, rt; 3089704Slinton 3099704Slinton rt = p->in.right->in.type; 3109704Slinton ro = p->in.right->in.op; 3119704Slinton 3129704Slinton if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ 3139704Slinton if( ro == UNARY MUL ) { 3149704Slinton offstar( p->in.right->in.left ); 3159704Slinton return(1); 3169704Slinton } else { 3179704Slinton order( p->in.right, INAREG|INTAREG|SOREG ); 3189704Slinton return(1); 3199704Slinton } 3209704Slinton } 3219704Slinton if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ 3229704Slinton /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ 3239704Slinton order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); 3249704Slinton return(1); 3259704Slinton } 3269704Slinton else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ 3279704Slinton offstar( p->in.right->in.left ); 3289704Slinton return(1); 3299704Slinton } 3309704Slinton else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG && 3319704Slinton ro != NAME && ro != OREG && ro != ICON ) ){ 3329704Slinton order( p->in.right, INAREG|INBREG ); 3339704Slinton return(1); 3349704Slinton } 3359704Slinton /* 3369704Slinton else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */ 3379704Slinton /* 3389704Slinton order( p->in.right, INAREG ); 3399704Slinton return( 1 ); 3409704Slinton } 3419704Slinton */ 3429704Slinton return(0); 3439704Slinton } 3449704Slinton 3459704Slinton setstr( p ) register NODE *p; { /* structure assignment */ 3469704Slinton if( p->in.right->in.op != REG ){ 3479704Slinton order( p->in.right, INTAREG ); 3489704Slinton return(1); 3499704Slinton } 3509704Slinton p = p->in.left; 3519704Slinton if( p->in.op != NAME && p->in.op != OREG ){ 3529704Slinton if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); 3539704Slinton order( p->in.left, INTAREG ); 3549704Slinton return( 1 ); 3559704Slinton } 3569704Slinton return( 0 ); 3579704Slinton } 3589704Slinton 3599704Slinton setasg( p ) register NODE *p; { 3609704Slinton /* setup for assignment operator */ 3619704Slinton 3629704Slinton if( !canaddr(p->in.right) ) { 3639704Slinton if( p->in.right->in.op == UNARY MUL ) 3649704Slinton offstar(p->in.right->in.left); 3659704Slinton else 3669704Slinton order( p->in.right, INAREG|INBREG|SOREG ); 3679704Slinton return(1); 3689704Slinton } 3699704Slinton if( p->in.left->in.op == UNARY MUL ) { 3709704Slinton offstar( p->in.left->in.left ); 3719704Slinton return(1); 3729704Slinton } 3739704Slinton if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 3749704Slinton offstar( p->in.left->in.left->in.left ); 3759704Slinton return(1); 3769704Slinton } 3779704Slinton /* FLD patch */ 3789704Slinton if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) { 3799704Slinton order( p->in.right, INAREG); 3809704Slinton return(1); 3819704Slinton } 3829704Slinton /* end of FLD patch */ 3839704Slinton return(0); 3849704Slinton } 3859704Slinton 3869704Slinton setasop( p ) register NODE *p; { 3879704Slinton /* setup for =ops */ 3889704Slinton register rt, ro; 3899704Slinton 3909704Slinton rt = p->in.right->in.type; 3919704Slinton ro = p->in.right->in.op; 3929704Slinton 3939704Slinton if( ro == UNARY MUL && rt != CHAR ){ 3949704Slinton offstar( p->in.right->in.left ); 3959704Slinton return(1); 3969704Slinton } 3979704Slinton if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || 3989704Slinton ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){ 3999704Slinton order( p->in.right, INAREG|INBREG ); 4009704Slinton return(1); 4019704Slinton } 4029704Slinton /* 4039704Slinton if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){ 4049704Slinton order( p->in.right, INAREG ); 4059704Slinton return(1); 4069704Slinton } 4079704Slinton */ 4089704Slinton 4099704Slinton 4109704Slinton p = p->in.left; 4119704Slinton if( p->in.op == FLD ) p = p->in.left; 4129704Slinton 4139704Slinton switch( p->in.op ){ 4149704Slinton 4159704Slinton case REG: 4169704Slinton case ICON: 4179704Slinton case NAME: 4189704Slinton case OREG: 4199704Slinton return(0); 4209704Slinton 4219704Slinton case UNARY MUL: 4229704Slinton if( p->in.left->in.op==OREG ) 4239704Slinton return(0); 4249704Slinton else 4259704Slinton offstar( p->in.left ); 4269704Slinton return(1); 4279704Slinton 4289704Slinton } 4299704Slinton cerror( "illegal setasop" ); 4309704Slinton } 4319704Slinton 4329704Slinton int crslab = 9999; /* Honeywell */ 4339704Slinton 4349704Slinton getlab(){ 4359704Slinton return( crslab-- ); 4369704Slinton } 4379704Slinton 4389704Slinton deflab( l ){ 4399704Slinton printf( "L%d:\n", l ); 4409704Slinton } 4419704Slinton 4429704Slinton genargs( p, ptemp ) register NODE *p, *ptemp; { 4439704Slinton register NODE *pasg; 4449704Slinton register align; 4459704Slinton register size; 4469704Slinton register TWORD type; 4479704Slinton 4489704Slinton /* generate code for the arguments */ 4499704Slinton 4509704Slinton /* first, do the arguments on the right */ 4519704Slinton while( p->in.op == CM ){ 4529704Slinton genargs( p->in.right, ptemp ); 4539704Slinton p->in.op = FREE; 4549704Slinton p = p->in.left; 4559704Slinton } 4569704Slinton 4579704Slinton if( p->in.op == STARG ){ /* structure valued argument */ 4589704Slinton 4599704Slinton size = p->stn.stsize; 4609704Slinton align = p->stn.stalign; 4619704Slinton if( p->in.left->in.op == ICON ){ 4629704Slinton p->in.op = FREE; 4639704Slinton p= p->in.left; 4649704Slinton } 4659704Slinton else { 4669704Slinton /* make it look beautiful... */ 4679704Slinton p->in.op = UNARY MUL; 4689704Slinton canon( p ); /* turn it into an oreg */ 4699704Slinton if( p->in.op != OREG ){ 4709704Slinton offstar( p->in.left ); 4719704Slinton canon( p ); 4729704Slinton if( p->in.op != OREG ){ 4739704Slinton offstar( p->in.left ); 4749704Slinton canon( p ); 4759704Slinton if( p->in.op != OREG ) cerror( "stuck starg" ); 4769704Slinton } 4779704Slinton } 4789704Slinton } 4799704Slinton 4809704Slinton 4819704Slinton ptemp->tn.lval = 0; /* all moves to (sp) */ 4829704Slinton 4839704Slinton pasg = talloc(); 4849704Slinton pasg->in.op = STASG; 485*16409Sralph pasg->in.rall = NOPREF; 4869704Slinton pasg->stn.stsize = size; 4879704Slinton pasg->stn.stalign = align; 4889704Slinton pasg->in.right = p; 4899704Slinton pasg->in.left = tcopy( ptemp ); 4909704Slinton 4919704Slinton /* the following line is done only with the knowledge 4929704Slinton that it will be undone by the STASG node, with the 4939704Slinton offset (lval) field retained */ 4949704Slinton 4959704Slinton if( p->in.op == OREG ) p->in.op = REG; /* only for temporaries */ 4969704Slinton 4979704Slinton order( pasg, FORARG ); 4989704Slinton ptemp->tn.lval += size; 4999704Slinton return; 5009704Slinton } 5019704Slinton 5029704Slinton /* ordinary case */ 5039704Slinton 5049704Slinton order( p, FORARG ); 5059704Slinton } 5069704Slinton 5079704Slinton argsize( p ) register NODE *p; { 5089704Slinton register t; 5099704Slinton t = 0; 5109704Slinton if( p->in.op == CM ){ 5119704Slinton t = argsize( p->in.left ); 5129704Slinton p = p->in.right; 5139704Slinton } 5149704Slinton if( p->in.type == DOUBLE || p->in.type == FLOAT ){ 5159704Slinton SETOFF( t, 4 ); 5169704Slinton return( t+8 ); 5179704Slinton } 5189704Slinton else if( p->in.op == STARG ){ 5199704Slinton SETOFF( t, 4 ); /* alignment */ 5209704Slinton return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ 5219704Slinton } 5229704Slinton else { 5239704Slinton SETOFF( t, 4 ); 5249704Slinton return( t+4 ); 5259704Slinton } 5269704Slinton } 5279704Slinton 5289704Slinton 529