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