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