117739Sralph #ifndef lint 2*32952Sdonn static char *sccsid ="@(#)order.c 1.13 (Berkeley) 12/11/87"; 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 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; 28*32952Sdonn register TWORD t; 299704Slinton 30*32952Sdonn if( q->in.op != INCR || 31*32952Sdonn q->in.left->in.op != REG || 32*32952Sdonn !ISPTR(q->in.type) ) 33*32952Sdonn return(0); 34*32952Sdonn t = q->in.type; 35*32952Sdonn q->in.type = DECREF(t); 36*32952Sdonn if( tlen(p) != tlen(q) ) { /* side effects okay? */ 37*32952Sdonn q->in.type = t; 38*32952Sdonn return(0); 39*32952Sdonn } 40*32952Sdonn q->in.type = t; 41*32952Sdonn if( tlen(p) != q->in.right->tn.lval ) 42*32952Sdonn return(0); 439704Slinton 44*32952Sdonn return(1); 459704Slinton } 469704Slinton 479704Slinton mkadrs(p) register NODE *p; { 489704Slinton register o; 499704Slinton 509704Slinton o = p->in.op; 519704Slinton 529704Slinton if( asgop(o) ){ 539704Slinton if( p->in.left->in.su >= p->in.right->in.su ){ 549704Slinton if( p->in.left->in.op == UNARY MUL ){ 559704Slinton SETSTO( p->in.left->in.left, INTEMP ); 569704Slinton } 579704Slinton else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 589704Slinton SETSTO( p->in.left->in.left->in.left, INTEMP ); 599704Slinton } 609704Slinton else { /* should be only structure assignment */ 619704Slinton SETSTO( p->in.left, INTEMP ); 629704Slinton } 639704Slinton } 649704Slinton else SETSTO( p->in.right, INTEMP ); 659704Slinton } 669704Slinton else { 679704Slinton if( p->in.left->in.su > p->in.right->in.su ){ 689704Slinton SETSTO( p->in.left, INTEMP ); 699704Slinton } 709704Slinton else { 719704Slinton SETSTO( p->in.right, INTEMP ); 729704Slinton } 739704Slinton } 749704Slinton } 759704Slinton 7632948Sdonn /*ARGSUSED*/ 7717739Sralph notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; { 789704Slinton /* is it legal to make an OREG or NAME entry which has an 799704Slinton /* offset of off, (from a register of r), if the 809704Slinton /* resulting thing had type t */ 819704Slinton 829704Slinton /* if( r == R0 ) return( 1 ); /* NO */ 839704Slinton return(0); /* YES */ 849704Slinton } 859704Slinton 869704Slinton # define max(x,y) ((x)<(y)?(y):(x)) 879704Slinton 889704Slinton sucomp( p ) register NODE *p; { 899704Slinton 909704Slinton /* set the su field in the node to the sethi-ullman 919704Slinton number, or local equivalent */ 929704Slinton 9317739Sralph register int o, ty, sul, sur, r; 9417739Sralph int szr; 9517739Sralph NODE *temp; 969704Slinton 979704Slinton o = p->in.op; 989704Slinton ty = optype( o ); 999704Slinton p->in.su = szty( p->in.type ); /* 2 for float or double, else 1 */; 1009704Slinton 1019704Slinton if( ty == LTYPE ){ 1029704Slinton if( o == OREG ){ 1039704Slinton r = p->tn.rval; 1049704Slinton /* oreg cost is (worst case) 1 + number of temp registers used */ 1059704Slinton if( R2TEST(r) ){ 1069704Slinton if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su; 1079704Slinton if( istreg(R2UPK2(r)) ) ++p->in.su; 1089704Slinton } 1099704Slinton else { 1109704Slinton if( istreg( r ) ) ++p->in.su; 1119704Slinton } 1129704Slinton } 1139704Slinton if( p->in.su == szty(p->in.type) && 1149704Slinton (p->in.op!=REG || !istreg(p->tn.rval)) && 11517739Sralph (p->in.type==INT || 11617739Sralph p->in.type==UNSIGNED || 11717739Sralph #if defined(FORT) || defined(SPRECC) 11817739Sralph p->in.type==FLOAT || 11917739Sralph #endif 12017739Sralph p->in.type==DOUBLE || 12117739Sralph ISPTR(p->in.type) || 12217739Sralph ISARY(p->in.type)) ) 1239704Slinton p->in.su = 0; 1249704Slinton return; 1259704Slinton } 1269704Slinton 1279704Slinton else if( ty == UTYPE ){ 1289704Slinton switch( o ) { 1299704Slinton case UNARY CALL: 1309704Slinton case UNARY STCALL: 1319704Slinton p->in.su = fregs; /* all regs needed */ 1329704Slinton return; 1339704Slinton 1349704Slinton default: 1359704Slinton p->in.su = p->in.left->in.su + (szty( p->in.type ) > 1 ? 2 : 0) ; 1369704Slinton return; 1379704Slinton } 1389704Slinton } 1399704Slinton 1409704Slinton 1419704Slinton /* If rhs needs n, lhs needs m, regular su computation */ 1429704Slinton 1439704Slinton sul = p->in.left->in.su; 1449704Slinton sur = p->in.right->in.su; 14517739Sralph szr = szty( p->in.right->in.type ); 14617739Sralph if( szty( p->in.type ) > szr && szr >= 1 ) { 14717739Sralph /* implicit conversion in rhs */ 14817739Sralph szr = szty( p->in.type ); 14917739Sralph sur = max( szr, sur ); 15017739Sralph } 1519704Slinton 1529704Slinton if( o == ASSIGN ){ 1539704Slinton /* computed by doing right, then left (if not in mem), then doing it */ 1549704Slinton p->in.su = max(sur,sul+1); 1559704Slinton return; 1569704Slinton } 1579704Slinton 1589704Slinton if( o == CALL || o == STCALL ){ 1599704Slinton /* in effect, takes all free registers */ 1609704Slinton p->in.su = fregs; 1619704Slinton return; 1629704Slinton } 1639704Slinton 1649704Slinton if( o == STASG ){ 1659704Slinton /* right, then left */ 1669704Slinton p->in.su = max( max( 1+sul, sur), fregs ); 1679704Slinton return; 1689704Slinton } 1699704Slinton 17032950Sdonn switch( o ){ 17132950Sdonn case DIV: 17232950Sdonn case ASG DIV: 17332950Sdonn case MOD: 17432950Sdonn case ASG MOD: 17532950Sdonn /* EDIV instructions require reg pairs */ 17632950Sdonn if( p->in.left->in.type == UNSIGNED && 17732950Sdonn p->in.right->in.op == ICON && 17832950Sdonn p->in.right->tn.name[0] == '\0' && 17932950Sdonn (unsigned) p->in.right->tn.lval < 0x80000000 ) { 18032951Sdonn p->in.su = sul + 2; 18132950Sdonn return; 18232950Sdonn } 18332950Sdonn break; 18432950Sdonn } 18532950Sdonn 1869704Slinton if( asgop(o) ){ 1879704Slinton /* computed by doing right, doing left address, doing left, op, and store */ 1889704Slinton p->in.su = max(sur,sul+2); 1899704Slinton /* 1909704Slinton if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs); 1919704Slinton */ 1929704Slinton return; 1939704Slinton } 1949704Slinton 1959704Slinton switch( o ){ 1969704Slinton case ANDAND: 1979704Slinton case OROR: 1989704Slinton case QUEST: 1999704Slinton case COLON: 2009704Slinton case COMOP: 2019704Slinton p->in.su = max( max(sul,sur), 1); 2029704Slinton return; 2039704Slinton 20417739Sralph case MUL: 2059704Slinton case PLUS: 2069704Slinton case OR: 2079704Slinton case ER: 2089704Slinton /* commutative ops; put harder on left */ 2099704Slinton if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ 2109704Slinton temp = p->in.left; 2119704Slinton p->in.left = p->in.right; 2129704Slinton p->in.right = temp; 21317739Sralph sul = p->in.left->in.su; 21417739Sralph sur = p->in.right->in.su; 21517739Sralph szr = szty( p->in.right->in.type ); 21617739Sralph if( szty( p->in.type ) > szr && szr >= 1 ) { 21717739Sralph /* implicit conversion in rhs */ 21817739Sralph szr = szty( p->in.type ); 21917739Sralph sur = max( szr, sur ); 22017739Sralph } 2219704Slinton } 2229704Slinton break; 2239704Slinton } 2249704Slinton 2259704Slinton /* binary op, computed by left, then right, then do op */ 22617739Sralph p->in.su = max(sul,szr+sur); 2279704Slinton /* 2289704Slinton if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs); 2299704Slinton */ 2309704Slinton 2319704Slinton } 2329704Slinton 2339704Slinton int radebug = 0; 2349704Slinton 2359704Slinton rallo( p, down ) NODE *p; { 2369704Slinton /* do register allocation */ 2379704Slinton register o, type, down1, down2, ty; 2389704Slinton 2399704Slinton if( radebug ) printf( "rallo( %o, %d )\n", p, down ); 2409704Slinton 2419704Slinton down2 = NOPREF; 2429704Slinton p->in.rall = down; 2439704Slinton down1 = ( down &= ~MUSTDO ); 2449704Slinton 2459704Slinton ty = optype( o = p->in.op ); 2469704Slinton type = p->in.type; 2479704Slinton 2489704Slinton 2499704Slinton if( type == DOUBLE || type == FLOAT ){ 2509704Slinton if( o == FORCE ) down1 = R0|MUSTDO; 2519704Slinton } 2529704Slinton else switch( o ) { 2539704Slinton case ASSIGN: 2549704Slinton down1 = NOPREF; 2559704Slinton down2 = down; 2569704Slinton break; 2579704Slinton 2589704Slinton case CALL: 2599704Slinton case STASG: 2609704Slinton case EQ: 2619704Slinton case NE: 2629704Slinton case GT: 2639704Slinton case GE: 2649704Slinton case LT: 2659704Slinton case LE: 2669704Slinton case NOT: 2679704Slinton case ANDAND: 2689704Slinton case OROR: 2699704Slinton down1 = NOPREF; 2709704Slinton break; 2719704Slinton 2729704Slinton case FORCE: 2739704Slinton down1 = R0|MUSTDO; 2749704Slinton break; 2759704Slinton 2769704Slinton } 2779704Slinton 2789704Slinton if( ty != LTYPE ) rallo( p->in.left, down1 ); 2799704Slinton if( ty == BITYPE ) rallo( p->in.right, down2 ); 2809704Slinton 2819704Slinton } 2829704Slinton 2839704Slinton offstar( p ) register NODE *p; { 2849704Slinton if( p->in.op == PLUS ) { 2859704Slinton if( p->in.left->in.su == fregs ) { 2869704Slinton order( p->in.left, INTAREG|INAREG ); 2879704Slinton return; 2889704Slinton } else if( p->in.right->in.su == fregs ) { 2899704Slinton order( p->in.right, INTAREG|INAREG ); 2909704Slinton return; 2919704Slinton } 2929704Slinton if( p->in.left->in.op==LS && 2939704Slinton (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) { 2949704Slinton order( p->in.left->in.left, INTAREG|INAREG ); 2959704Slinton return; 2969704Slinton } 2979704Slinton if( p->in.right->in.op==LS && 2989704Slinton (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) { 2999704Slinton order( p->in.right->in.left, INTAREG|INAREG ); 3009704Slinton return; 3019704Slinton } 3029704Slinton if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { 3039704Slinton if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) { 3049704Slinton order( p->in.left, INTAREG|INAREG ); 3059704Slinton return; 3069704Slinton } 3079704Slinton else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) { 3089704Slinton order(p->in.right, INTAREG|INAREG); 3099704Slinton return; 3109704Slinton } 3119704Slinton } 3129704Slinton } 3139704Slinton if( p->in.op == PLUS || p->in.op == MINUS ){ 3149704Slinton if( p->in.right->in.op == ICON ){ 3159704Slinton p = p->in.left; 3169704Slinton order( p , INTAREG|INAREG); 3179704Slinton return; 3189704Slinton } 3199704Slinton } 3209704Slinton 3219704Slinton if( p->in.op == UNARY MUL && !canaddr(p) ) { 3229704Slinton offstar( p->in.left ); 3239704Slinton return; 3249704Slinton } 3259704Slinton 3269704Slinton order( p, INTAREG|INAREG ); 3279704Slinton } 3289704Slinton 3299704Slinton setincr( p ) register NODE *p; { 3309704Slinton p = p->in.left; 3319704Slinton if( p->in.op == UNARY MUL ){ 3329704Slinton offstar( p ); 3339704Slinton return( 1 ); 3349704Slinton } 3359704Slinton return( 0 ); 3369704Slinton } 3379704Slinton 3389704Slinton setbin( p ) register NODE *p; { 3399704Slinton register ro, rt; 3409704Slinton 3419704Slinton rt = p->in.right->in.type; 3429704Slinton ro = p->in.right->in.op; 3439704Slinton 3449704Slinton if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ 3459704Slinton if( ro == UNARY MUL ) { 3469704Slinton offstar( p->in.right->in.left ); 3479704Slinton return(1); 3489704Slinton } else { 3499704Slinton order( p->in.right, INAREG|INTAREG|SOREG ); 3509704Slinton return(1); 3519704Slinton } 3529704Slinton } 3539704Slinton if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ 3549704Slinton /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ 3559704Slinton order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); 3569704Slinton return(1); 3579704Slinton } 3589704Slinton else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ 3599704Slinton offstar( p->in.right->in.left ); 3609704Slinton return(1); 3619704Slinton } 36216937Sralph else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || 36316937Sralph rt == FLOAT || (ro != REG && ro != NAME && ro != OREG && ro != ICON ) ){ 3649704Slinton order( p->in.right, INAREG|INBREG ); 3659704Slinton return(1); 3669704Slinton } 3679704Slinton /* 3689704Slinton else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */ 3699704Slinton /* 3709704Slinton order( p->in.right, INAREG ); 3719704Slinton return( 1 ); 3729704Slinton } 3739704Slinton */ 3749704Slinton return(0); 3759704Slinton } 3769704Slinton 3779704Slinton setstr( p ) register NODE *p; { /* structure assignment */ 3789704Slinton if( p->in.right->in.op != REG ){ 3799704Slinton order( p->in.right, INTAREG ); 3809704Slinton return(1); 3819704Slinton } 3829704Slinton p = p->in.left; 3839704Slinton if( p->in.op != NAME && p->in.op != OREG ){ 3849704Slinton if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); 3859704Slinton order( p->in.left, INTAREG ); 3869704Slinton return( 1 ); 3879704Slinton } 3889704Slinton return( 0 ); 3899704Slinton } 3909704Slinton 3919704Slinton setasg( p ) register NODE *p; { 3929704Slinton /* setup for assignment operator */ 3939704Slinton 3949704Slinton if( !canaddr(p->in.right) ) { 3959704Slinton if( p->in.right->in.op == UNARY MUL ) 3969704Slinton offstar(p->in.right->in.left); 3979704Slinton else 3989704Slinton order( p->in.right, INAREG|INBREG|SOREG ); 3999704Slinton return(1); 4009704Slinton } 4019704Slinton if( p->in.left->in.op == UNARY MUL ) { 4029704Slinton offstar( p->in.left->in.left ); 4039704Slinton return(1); 4049704Slinton } 4059704Slinton if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 4069704Slinton offstar( p->in.left->in.left->in.left ); 4079704Slinton return(1); 4089704Slinton } 4099704Slinton /* FLD patch */ 4109704Slinton if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) { 4119704Slinton order( p->in.right, INAREG); 4129704Slinton return(1); 4139704Slinton } 4149704Slinton /* end of FLD patch */ 4159704Slinton return(0); 4169704Slinton } 4179704Slinton 4189704Slinton setasop( p ) register NODE *p; { 4199704Slinton /* setup for =ops */ 4209704Slinton register rt, ro; 4219704Slinton 4229704Slinton rt = p->in.right->in.type; 4239704Slinton ro = p->in.right->in.op; 4249704Slinton 4259704Slinton if( ro == UNARY MUL && rt != CHAR ){ 4269704Slinton offstar( p->in.right->in.left ); 4279704Slinton return(1); 4289704Slinton } 42916937Sralph if( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || 43017739Sralph #ifndef SPRECC 43117739Sralph rt == FLOAT || 43217739Sralph #endif 43317739Sralph ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ){ 4349704Slinton order( p->in.right, INAREG|INBREG ); 4359704Slinton return(1); 4369704Slinton } 4379704Slinton /* 4389704Slinton if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){ 4399704Slinton order( p->in.right, INAREG ); 4409704Slinton return(1); 4419704Slinton } 4429704Slinton */ 4439704Slinton 4449704Slinton 4459704Slinton p = p->in.left; 4469704Slinton if( p->in.op == FLD ) p = p->in.left; 4479704Slinton 4489704Slinton switch( p->in.op ){ 4499704Slinton 4509704Slinton case REG: 4519704Slinton case ICON: 4529704Slinton case NAME: 4539704Slinton case OREG: 4549704Slinton return(0); 4559704Slinton 4569704Slinton case UNARY MUL: 4579704Slinton if( p->in.left->in.op==OREG ) 4589704Slinton return(0); 4599704Slinton else 4609704Slinton offstar( p->in.left ); 4619704Slinton return(1); 4629704Slinton 4639704Slinton } 4649704Slinton cerror( "illegal setasop" ); 46517739Sralph /*NOTREACHED*/ 4669704Slinton } 4679704Slinton 46817739Sralph int crslab = 99999; /* VAX */ 4699704Slinton 4709704Slinton getlab(){ 4719704Slinton return( crslab-- ); 4729704Slinton } 4739704Slinton 47432947Sdonn #ifndef deflab 4759704Slinton deflab( l ){ 4769704Slinton printf( "L%d:\n", l ); 4779704Slinton } 47832947Sdonn #endif 4799704Slinton 48016419Sralph genargs( p ) register NODE *p; { 4819704Slinton register NODE *pasg; 4829704Slinton register align; 4839704Slinton register size; 48425752Sdonn int count; 4859704Slinton 4869704Slinton /* generate code for the arguments */ 4879704Slinton 4889704Slinton /* first, do the arguments on the right */ 4899704Slinton while( p->in.op == CM ){ 49016419Sralph genargs( p->in.right ); 4919704Slinton p->in.op = FREE; 4929704Slinton p = p->in.left; 4939704Slinton } 4949704Slinton 4959704Slinton if( p->in.op == STARG ){ /* structure valued argument */ 4969704Slinton 4979704Slinton size = p->stn.stsize; 4989704Slinton align = p->stn.stalign; 4999704Slinton if( p->in.left->in.op == ICON ){ 5009704Slinton p->in.op = FREE; 50116419Sralph p = p->in.left; 5029704Slinton } 5039704Slinton else { 5049704Slinton /* make it look beautiful... */ 5059704Slinton p->in.op = UNARY MUL; 5069704Slinton canon( p ); /* turn it into an oreg */ 50725752Sdonn for( count = 0; p->in.op != OREG && count < 10; ++count ){ 5089704Slinton offstar( p->in.left ); 5099704Slinton canon( p ); 5109704Slinton } 51125752Sdonn if( p->in.op != OREG ) cerror( "stuck starg" ); 5129704Slinton } 5139704Slinton 5149704Slinton pasg = talloc(); 51516419Sralph pasg->in.op = STARG; 51616409Sralph pasg->in.rall = NOPREF; 5179704Slinton pasg->stn.stsize = size; 5189704Slinton pasg->stn.stalign = align; 51916419Sralph pasg->in.left = p; 5209704Slinton 5219704Slinton order( pasg, FORARG ); 5229704Slinton return; 5239704Slinton } 5249704Slinton 5259704Slinton /* ordinary case */ 5269704Slinton 5279704Slinton order( p, FORARG ); 5289704Slinton } 5299704Slinton 5309704Slinton argsize( p ) register NODE *p; { 5319704Slinton register t; 5329704Slinton t = 0; 5339704Slinton if( p->in.op == CM ){ 5349704Slinton t = argsize( p->in.left ); 5359704Slinton p = p->in.right; 5369704Slinton } 5379704Slinton if( p->in.type == DOUBLE || p->in.type == FLOAT ){ 5389704Slinton SETOFF( t, 4 ); 5399704Slinton return( t+8 ); 5409704Slinton } 5419704Slinton else if( p->in.op == STARG ){ 5429704Slinton SETOFF( t, 4 ); /* alignment */ 5439704Slinton return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ 5449704Slinton } 5459704Slinton else { 5469704Slinton SETOFF( t, 4 ); 5479704Slinton return( t+4 ); 5489704Slinton } 5499704Slinton } 550