117739Sralph #ifndef lint 2*34357Sdonn static char *sccsid ="@(#)order.c 1.19 (Berkeley) 05/20/88"; 317739Sralph #endif lint 417739Sralph 518557Sralph # include "pass2.h" 69704Slinton 79704Slinton int maxargs = { -1 }; 89704Slinton 932948Sdonn /*ARGSUSED*/ 1032948Sdonn 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 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; { 2317739Sralph register NODE *q = p->in.left; 2432952Sdonn register TWORD t; 259704Slinton 2632952Sdonn if( q->in.op != INCR || 2732952Sdonn q->in.left->in.op != REG || 2832952Sdonn !ISPTR(q->in.type) ) 2932952Sdonn return(0); 3032952Sdonn t = q->in.type; 3132952Sdonn q->in.type = DECREF(t); 3232952Sdonn if( tlen(p) != tlen(q) ) { /* side effects okay? */ 3332952Sdonn q->in.type = t; 3432952Sdonn return(0); 3532952Sdonn } 3632952Sdonn q->in.type = t; 3732952Sdonn if( tlen(p) != q->in.right->tn.lval ) 3832952Sdonn return(0); 399704Slinton 4032952Sdonn return(1); 419704Slinton } 429704Slinton 439704Slinton mkadrs(p) register NODE *p; { 4432955Sdonn register int o; 459704Slinton 469704Slinton o = p->in.op; 479704Slinton 489704Slinton if( asgop(o) ){ 499704Slinton if( p->in.left->in.su >= p->in.right->in.su ){ 509704Slinton if( p->in.left->in.op == UNARY MUL ){ 519704Slinton SETSTO( p->in.left->in.left, INTEMP ); 529704Slinton } 539704Slinton else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 549704Slinton SETSTO( p->in.left->in.left->in.left, INTEMP ); 559704Slinton } 569704Slinton else { /* should be only structure assignment */ 579704Slinton SETSTO( p->in.left, INTEMP ); 589704Slinton } 599704Slinton } 609704Slinton else SETSTO( p->in.right, INTEMP ); 619704Slinton } 629704Slinton else { 639704Slinton if( p->in.left->in.su > p->in.right->in.su ){ 649704Slinton SETSTO( p->in.left, INTEMP ); 659704Slinton } 669704Slinton else { 679704Slinton SETSTO( p->in.right, INTEMP ); 689704Slinton } 699704Slinton } 709704Slinton } 719704Slinton 7232948Sdonn /*ARGSUSED*/ 7317739Sralph notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; { 749704Slinton /* is it legal to make an OREG or NAME entry which has an 759704Slinton /* offset of off, (from a register of r), if the 769704Slinton /* resulting thing had type t */ 779704Slinton 789704Slinton return(0); /* YES */ 799704Slinton } 809704Slinton 819704Slinton # define max(x,y) ((x)<(y)?(y):(x)) 829704Slinton 839704Slinton sucomp( p ) register NODE *p; { 849704Slinton 859704Slinton /* set the su field in the node to the sethi-ullman 869704Slinton number, or local equivalent */ 879704Slinton 8817739Sralph register int o, ty, sul, sur, r; 8917739Sralph int szr; 9017739Sralph NODE *temp; 919704Slinton 929704Slinton o = p->in.op; 939704Slinton ty = optype( o ); 9432955Sdonn p->in.su = szty( p->in.type ); /* 2 for double, else 1 */; 959704Slinton 969704Slinton if( ty == LTYPE ){ 979704Slinton if( o == OREG ){ 989704Slinton r = p->tn.rval; 999704Slinton /* oreg cost is (worst case) 1 + number of temp registers used */ 1009704Slinton if( R2TEST(r) ){ 1019704Slinton if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su; 1029704Slinton if( istreg(R2UPK2(r)) ) ++p->in.su; 1039704Slinton } 1049704Slinton else { 1059704Slinton if( istreg( r ) ) ++p->in.su; 1069704Slinton } 1079704Slinton } 1089704Slinton if( p->in.su == szty(p->in.type) && 1099704Slinton (p->in.op!=REG || !istreg(p->tn.rval)) && 11017739Sralph (p->in.type==INT || 11117739Sralph p->in.type==UNSIGNED || 11217739Sralph #if defined(FORT) || defined(SPRECC) 11317739Sralph p->in.type==FLOAT || 11417739Sralph #endif 11517739Sralph p->in.type==DOUBLE || 11617739Sralph ISPTR(p->in.type) || 11717739Sralph ISARY(p->in.type)) ) 1189704Slinton p->in.su = 0; 1199704Slinton return; 1209704Slinton } 1219704Slinton 1229704Slinton else if( ty == UTYPE ){ 1239704Slinton switch( o ) { 1249704Slinton case UNARY CALL: 1259704Slinton case UNARY STCALL: 1269704Slinton p->in.su = fregs; /* all regs needed */ 1279704Slinton return; 1289704Slinton 1299704Slinton default: 1309704Slinton p->in.su = p->in.left->in.su + (szty( p->in.type ) > 1 ? 2 : 0) ; 1319704Slinton return; 1329704Slinton } 1339704Slinton } 1349704Slinton 1359704Slinton 1369704Slinton /* If rhs needs n, lhs needs m, regular su computation */ 1379704Slinton 1389704Slinton sul = p->in.left->in.su; 1399704Slinton sur = p->in.right->in.su; 14017739Sralph szr = szty( p->in.right->in.type ); 14117739Sralph if( szty( p->in.type ) > szr && szr >= 1 ) { 14217739Sralph /* implicit conversion in rhs */ 14317739Sralph szr = szty( p->in.type ); 14417739Sralph sur = max( szr, sur ); 14517739Sralph } 1469704Slinton 1479704Slinton if( o == ASSIGN ){ 1489704Slinton /* computed by doing right, then left (if not in mem), then doing it */ 1499704Slinton p->in.su = max(sur,sul+1); 1509704Slinton return; 1519704Slinton } 1529704Slinton 1539704Slinton if( o == CALL || o == STCALL ){ 1549704Slinton /* in effect, takes all free registers */ 1559704Slinton p->in.su = fregs; 1569704Slinton return; 1579704Slinton } 1589704Slinton 1599704Slinton if( o == STASG ){ 1609704Slinton /* right, then left */ 1619704Slinton p->in.su = max( max( 1+sul, sur), fregs ); 1629704Slinton return; 1639704Slinton } 1649704Slinton 16532950Sdonn switch( o ){ 16632950Sdonn case DIV: 16732950Sdonn case ASG DIV: 16832950Sdonn case MOD: 16932950Sdonn case ASG MOD: 17032950Sdonn /* EDIV instructions require reg pairs */ 17132950Sdonn if( p->in.left->in.type == UNSIGNED && 17232950Sdonn p->in.right->in.op == ICON && 17332950Sdonn p->in.right->tn.name[0] == '\0' && 17432950Sdonn (unsigned) p->in.right->tn.lval < 0x80000000 ) { 17532951Sdonn p->in.su = sul + 2; 17632950Sdonn return; 17732950Sdonn } 17832950Sdonn break; 17932950Sdonn } 18032950Sdonn 1819704Slinton if( asgop(o) ){ 1829704Slinton /* computed by doing right, doing left address, doing left, op, and store */ 1839704Slinton p->in.su = max(sur,sul+2); 1849704Slinton return; 1859704Slinton } 1869704Slinton 1879704Slinton switch( o ){ 1889704Slinton case ANDAND: 1899704Slinton case OROR: 1909704Slinton case QUEST: 1919704Slinton case COLON: 1929704Slinton case COMOP: 1939704Slinton p->in.su = max( max(sul,sur), 1); 1949704Slinton return; 1959704Slinton 19632955Sdonn case PLUS: 19717739Sralph case MUL: 1989704Slinton case OR: 1999704Slinton case ER: 2009704Slinton /* commutative ops; put harder on left */ 2019704Slinton if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ 2029704Slinton temp = p->in.left; 2039704Slinton p->in.left = p->in.right; 2049704Slinton p->in.right = temp; 20517739Sralph sul = p->in.left->in.su; 20617739Sralph sur = p->in.right->in.su; 20717739Sralph szr = szty( p->in.right->in.type ); 20817739Sralph if( szty( p->in.type ) > szr && szr >= 1 ) { 20917739Sralph /* implicit conversion in rhs */ 21017739Sralph szr = szty( p->in.type ); 21117739Sralph sur = max( szr, sur ); 21217739Sralph } 2139704Slinton } 2149704Slinton break; 2159704Slinton } 2169704Slinton /* binary op, computed by left, then right, then do op */ 21717739Sralph p->in.su = max(sul,szr+sur); 2189704Slinton 2199704Slinton } 2209704Slinton 2219704Slinton int radebug = 0; 2229704Slinton 2239704Slinton rallo( p, down ) NODE *p; { 2249704Slinton /* do register allocation */ 22532955Sdonn register int o, down1, down2, ty; 2269704Slinton 2279704Slinton if( radebug ) printf( "rallo( %o, %d )\n", p, down ); 2289704Slinton 2299704Slinton down2 = NOPREF; 2309704Slinton p->in.rall = down; 2319704Slinton down1 = ( down &= ~MUSTDO ); 2329704Slinton 2339704Slinton ty = optype( o = p->in.op ); 23432955Sdonn switch( o ) { 2359704Slinton case ASSIGN: 2369704Slinton down1 = NOPREF; 2379704Slinton down2 = down; 2389704Slinton break; 2399704Slinton 2409704Slinton case CALL: 2419704Slinton case STASG: 2429704Slinton case EQ: 2439704Slinton case NE: 2449704Slinton case GT: 2459704Slinton case GE: 2469704Slinton case LT: 2479704Slinton case LE: 2489704Slinton case NOT: 2499704Slinton case ANDAND: 2509704Slinton case OROR: 2519704Slinton down1 = NOPREF; 2529704Slinton break; 2539704Slinton 2549704Slinton case FORCE: 2559704Slinton down1 = R0|MUSTDO; 2569704Slinton break; 2579704Slinton 2589704Slinton } 2599704Slinton 2609704Slinton if( ty != LTYPE ) rallo( p->in.left, down1 ); 2619704Slinton if( ty == BITYPE ) rallo( p->in.right, down2 ); 2629704Slinton 2639704Slinton } 2649704Slinton 2659704Slinton offstar( p ) register NODE *p; { 2669704Slinton if( p->in.op == PLUS ) { 26734252Sdonn /* try to create index expressions */ 26834252Sdonn if( p->in.left->in.op==LS && 26934252Sdonn p->in.left->in.left->in.op!=REG && 27034252Sdonn p->in.left->in.right->in.op==ICON && 27134252Sdonn p->in.left->in.right->tn.lval<=3 ){ 27234252Sdonn order( p->in.left->in.left, INTAREG|INAREG ); 27334252Sdonn return; 27434252Sdonn } 2759704Slinton if( p->in.left->in.su == fregs ) { 2769704Slinton order( p->in.left, INTAREG|INAREG ); 2779704Slinton return; 2789704Slinton } 27934252Sdonn if( p->in.right->in.op==LS && 28034252Sdonn p->in.right->in.left->in.op!=REG && 28134252Sdonn p->in.right->in.right->in.op==ICON && 28234252Sdonn p->in.right->in.right->tn.lval<=3 ){ 28334252Sdonn order( p->in.right->in.left, INTAREG|INAREG ); 2849704Slinton return; 2859704Slinton } 28634252Sdonn if( p->in.right->in.su == fregs ) { 28734252Sdonn order( p->in.right, INTAREG|INAREG ); 2889704Slinton return; 2899704Slinton } 2909704Slinton if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { 291*34357Sdonn if( (p->in.left->in.op == ICON || 292*34357Sdonn p->in.left->in.op == NAME) && 293*34357Sdonn p->in.right->in.op != REG ) { 294*34357Sdonn order(p->in.right, INTAREG|INAREG); 295*34357Sdonn return; 296*34357Sdonn } 297*34357Sdonn if( p->in.left->in.op!=REG ) { 2989704Slinton order( p->in.left, INTAREG|INAREG ); 2999704Slinton return; 3009704Slinton } 301*34357Sdonn if( p->in.right->in.op!=REG ) { 3029704Slinton order(p->in.right, INTAREG|INAREG); 3039704Slinton return; 3049704Slinton } 3059704Slinton } 3069704Slinton } 3079704Slinton if( p->in.op == PLUS || p->in.op == MINUS ){ 3089704Slinton if( p->in.right->in.op == ICON ){ 3099704Slinton p = p->in.left; 3109704Slinton order( p , INTAREG|INAREG); 3119704Slinton return; 3129704Slinton } 3139704Slinton } 3149704Slinton 3159704Slinton if( p->in.op == UNARY MUL && !canaddr(p) ) { 3169704Slinton offstar( p->in.left ); 3179704Slinton return; 3189704Slinton } 3199704Slinton 3209704Slinton order( p, INTAREG|INAREG ); 3219704Slinton } 3229704Slinton 3239704Slinton setincr( p ) register NODE *p; { 3249704Slinton p = p->in.left; 3259704Slinton if( p->in.op == UNARY MUL ){ 32632953Sdonn offstar( p->in.left ); 3279704Slinton return( 1 ); 3289704Slinton } 3299704Slinton return( 0 ); 3309704Slinton } 3319704Slinton 3329704Slinton setbin( p ) register NODE *p; { 33332955Sdonn register int ro, rt; 3349704Slinton 3359704Slinton rt = p->in.right->in.type; 3369704Slinton ro = p->in.right->in.op; 3379704Slinton 3389704Slinton if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ 3399704Slinton if( ro == UNARY MUL ) { 3409704Slinton offstar( p->in.right->in.left ); 3419704Slinton return(1); 3429704Slinton } else { 3439704Slinton order( p->in.right, INAREG|INTAREG|SOREG ); 3449704Slinton return(1); 3459704Slinton } 3469704Slinton } 3479704Slinton if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ 3489704Slinton order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); 3499704Slinton return(1); 3509704Slinton } 3519704Slinton else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ 3529704Slinton offstar( p->in.right->in.left ); 3539704Slinton return(1); 3549704Slinton } 35516937Sralph else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || 35632955Sdonn #ifndef SPRECC 35732955Sdonn rt == FLOAT || 35832955Sdonn #endif 35932955Sdonn (ro != REG && ro != NAME && ro != OREG && ro != ICON ) ){ 3609704Slinton order( p->in.right, INAREG|INBREG ); 3619704Slinton return(1); 3629704Slinton } 3639704Slinton return(0); 3649704Slinton } 3659704Slinton 3669704Slinton setstr( p ) register NODE *p; { /* structure assignment */ 3679704Slinton if( p->in.right->in.op != REG ){ 3689704Slinton order( p->in.right, INTAREG ); 3699704Slinton return(1); 3709704Slinton } 3719704Slinton p = p->in.left; 3729704Slinton if( p->in.op != NAME && p->in.op != OREG ){ 3739704Slinton if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); 3749704Slinton order( p->in.left, INTAREG ); 3759704Slinton return( 1 ); 3769704Slinton } 3779704Slinton return( 0 ); 3789704Slinton } 3799704Slinton 3809704Slinton setasg( p ) register NODE *p; { 3819704Slinton /* setup for assignment operator */ 3829704Slinton 3839704Slinton if( !canaddr(p->in.right) ) { 3849704Slinton if( p->in.right->in.op == UNARY MUL ) 3859704Slinton offstar(p->in.right->in.left); 3869704Slinton else 3879704Slinton order( p->in.right, INAREG|INBREG|SOREG ); 3889704Slinton return(1); 3899704Slinton } 3909704Slinton if( p->in.left->in.op == UNARY MUL ) { 3919704Slinton offstar( p->in.left->in.left ); 3929704Slinton return(1); 3939704Slinton } 3949704Slinton if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 3959704Slinton offstar( p->in.left->in.left->in.left ); 3969704Slinton return(1); 3979704Slinton } 3989704Slinton /* FLD patch */ 3999704Slinton if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) { 4009704Slinton order( p->in.right, INAREG); 4019704Slinton return(1); 4029704Slinton } 4039704Slinton /* end of FLD patch */ 4049704Slinton return(0); 4059704Slinton } 4069704Slinton 4079704Slinton setasop( p ) register NODE *p; { 4089704Slinton /* setup for =ops */ 40932955Sdonn register int rt, ro; 4109704Slinton 4119704Slinton rt = p->in.right->in.type; 4129704Slinton ro = p->in.right->in.op; 4139704Slinton 4149704Slinton if( ro == UNARY MUL && rt != CHAR ){ 4159704Slinton offstar( p->in.right->in.left ); 4169704Slinton return(1); 4179704Slinton } 41816937Sralph if( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || 41917739Sralph #ifndef SPRECC 42017739Sralph rt == FLOAT || 42117739Sralph #endif 42217739Sralph ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ){ 4239704Slinton order( p->in.right, INAREG|INBREG ); 4249704Slinton return(1); 4259704Slinton } 4269704Slinton 4279704Slinton 4289704Slinton p = p->in.left; 4299704Slinton if( p->in.op == FLD ) p = p->in.left; 4309704Slinton 4319704Slinton switch( p->in.op ){ 4329704Slinton 4339704Slinton case REG: 4349704Slinton case ICON: 4359704Slinton case NAME: 4369704Slinton case OREG: 4379704Slinton return(0); 4389704Slinton 4399704Slinton case UNARY MUL: 4409704Slinton if( p->in.left->in.op==OREG ) 4419704Slinton return(0); 4429704Slinton else 4439704Slinton offstar( p->in.left ); 4449704Slinton return(1); 4459704Slinton 4469704Slinton } 4479704Slinton cerror( "illegal setasop" ); 44817739Sralph /*NOTREACHED*/ 4499704Slinton } 4509704Slinton 45117739Sralph int crslab = 99999; /* VAX */ 4529704Slinton 4539704Slinton getlab(){ 4549704Slinton return( crslab-- ); 4559704Slinton } 4569704Slinton 45732947Sdonn #ifndef deflab 4589704Slinton deflab( l ){ 4599704Slinton printf( "L%d:\n", l ); 4609704Slinton } 46132947Sdonn #endif 4629704Slinton 46316419Sralph genargs( p ) register NODE *p; { 4649704Slinton register NODE *pasg; 46532955Sdonn register int align; 46632955Sdonn register int size; 46725752Sdonn int count; 4689704Slinton 4699704Slinton /* generate code for the arguments */ 4709704Slinton 4719704Slinton /* first, do the arguments on the right */ 4729704Slinton while( p->in.op == CM ){ 47316419Sralph genargs( p->in.right ); 4749704Slinton p->in.op = FREE; 4759704Slinton p = p->in.left; 4769704Slinton } 4779704Slinton 4789704Slinton if( p->in.op == STARG ){ /* structure valued argument */ 4799704Slinton 4809704Slinton size = p->stn.stsize; 4819704Slinton align = p->stn.stalign; 4829704Slinton if( p->in.left->in.op == ICON ){ 4839704Slinton p->in.op = FREE; 48416419Sralph p = p->in.left; 4859704Slinton } 4869704Slinton else { 4879704Slinton /* make it look beautiful... */ 4889704Slinton p->in.op = UNARY MUL; 4899704Slinton canon( p ); /* turn it into an oreg */ 49025752Sdonn for( count = 0; p->in.op != OREG && count < 10; ++count ){ 4919704Slinton offstar( p->in.left ); 4929704Slinton canon( p ); 4939704Slinton } 49425752Sdonn if( p->in.op != OREG ) cerror( "stuck starg" ); 4959704Slinton } 4969704Slinton 4979704Slinton pasg = talloc(); 49816419Sralph pasg->in.op = STARG; 49916409Sralph pasg->in.rall = NOPREF; 5009704Slinton pasg->stn.stsize = size; 5019704Slinton pasg->stn.stalign = align; 50216419Sralph pasg->in.left = p; 5039704Slinton 5049704Slinton order( pasg, FORARG ); 5059704Slinton return; 5069704Slinton } 5079704Slinton 5089704Slinton /* ordinary case */ 5099704Slinton 5109704Slinton order( p, FORARG ); 5119704Slinton } 5129704Slinton 5139704Slinton argsize( p ) register NODE *p; { 51432955Sdonn register int t; 5159704Slinton t = 0; 5169704Slinton if( p->in.op == CM ){ 5179704Slinton t = argsize( p->in.left ); 5189704Slinton p = p->in.right; 5199704Slinton } 5209704Slinton if( p->in.type == DOUBLE || p->in.type == FLOAT ){ 5219704Slinton SETOFF( t, 4 ); 5229704Slinton return( t+8 ); 5239704Slinton } 5249704Slinton else if( p->in.op == STARG ){ 5259704Slinton SETOFF( t, 4 ); /* alignment */ 5269704Slinton return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ 5279704Slinton } 5289704Slinton else { 5299704Slinton SETOFF( t, 4 ); 5309704Slinton return( t+4 ); 5319704Slinton } 5329704Slinton } 533