117739Sralph #ifndef lint 2*32950Sdonn static char *sccsid ="@(#)order.c 1.11 (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; 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 6532948Sdonn /*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 159*32950Sdonn switch( o ){ 160*32950Sdonn case DIV: 161*32950Sdonn case ASG DIV: 162*32950Sdonn case MOD: 163*32950Sdonn case ASG MOD: 164*32950Sdonn /* EDIV instructions require reg pairs */ 165*32950Sdonn if( p->in.left->in.type == UNSIGNED && 166*32950Sdonn p->in.right->in.op == ICON && 167*32950Sdonn p->in.right->tn.name[0] == '\0' && 168*32950Sdonn (unsigned) p->in.right->tn.lval < 0x80000000 ) { 169*32950Sdonn sul += 2; 170*32950Sdonn p->in.su = max(sul, szr+sur); 171*32950Sdonn return; 172*32950Sdonn } 173*32950Sdonn break; 174*32950Sdonn } 175*32950Sdonn 1769704Slinton if( asgop(o) ){ 1779704Slinton /* computed by doing right, doing left address, doing left, op, and store */ 1789704Slinton p->in.su = max(sur,sul+2); 1799704Slinton /* 1809704Slinton if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs); 1819704Slinton */ 1829704Slinton return; 1839704Slinton } 1849704Slinton 1859704Slinton switch( o ){ 1869704Slinton case ANDAND: 1879704Slinton case OROR: 1889704Slinton case QUEST: 1899704Slinton case COLON: 1909704Slinton case COMOP: 1919704Slinton p->in.su = max( max(sul,sur), 1); 1929704Slinton return; 1939704Slinton 19417739Sralph case MUL: 1959704Slinton case PLUS: 1969704Slinton case OR: 1979704Slinton case ER: 1989704Slinton /* commutative ops; put harder on left */ 1999704Slinton if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ 2009704Slinton temp = p->in.left; 2019704Slinton p->in.left = p->in.right; 2029704Slinton p->in.right = temp; 20317739Sralph sul = p->in.left->in.su; 20417739Sralph sur = p->in.right->in.su; 20517739Sralph szr = szty( p->in.right->in.type ); 20617739Sralph if( szty( p->in.type ) > szr && szr >= 1 ) { 20717739Sralph /* implicit conversion in rhs */ 20817739Sralph szr = szty( p->in.type ); 20917739Sralph sur = max( szr, sur ); 21017739Sralph } 2119704Slinton } 2129704Slinton break; 2139704Slinton } 2149704Slinton 2159704Slinton /* binary op, computed by left, then right, then do op */ 21617739Sralph p->in.su = max(sul,szr+sur); 2179704Slinton /* 2189704Slinton if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs); 2199704Slinton */ 2209704Slinton 2219704Slinton } 2229704Slinton 2239704Slinton int radebug = 0; 2249704Slinton 2259704Slinton rallo( p, down ) NODE *p; { 2269704Slinton /* do register allocation */ 2279704Slinton register o, type, down1, down2, ty; 2289704Slinton 2299704Slinton if( radebug ) printf( "rallo( %o, %d )\n", p, down ); 2309704Slinton 2319704Slinton down2 = NOPREF; 2329704Slinton p->in.rall = down; 2339704Slinton down1 = ( down &= ~MUSTDO ); 2349704Slinton 2359704Slinton ty = optype( o = p->in.op ); 2369704Slinton type = p->in.type; 2379704Slinton 2389704Slinton 2399704Slinton if( type == DOUBLE || type == FLOAT ){ 2409704Slinton if( o == FORCE ) down1 = R0|MUSTDO; 2419704Slinton } 2429704Slinton else switch( o ) { 2439704Slinton case ASSIGN: 2449704Slinton down1 = NOPREF; 2459704Slinton down2 = down; 2469704Slinton break; 2479704Slinton 2489704Slinton case CALL: 2499704Slinton case STASG: 2509704Slinton case EQ: 2519704Slinton case NE: 2529704Slinton case GT: 2539704Slinton case GE: 2549704Slinton case LT: 2559704Slinton case LE: 2569704Slinton case NOT: 2579704Slinton case ANDAND: 2589704Slinton case OROR: 2599704Slinton down1 = NOPREF; 2609704Slinton break; 2619704Slinton 2629704Slinton case FORCE: 2639704Slinton down1 = R0|MUSTDO; 2649704Slinton break; 2659704Slinton 2669704Slinton } 2679704Slinton 2689704Slinton if( ty != LTYPE ) rallo( p->in.left, down1 ); 2699704Slinton if( ty == BITYPE ) rallo( p->in.right, down2 ); 2709704Slinton 2719704Slinton } 2729704Slinton 2739704Slinton offstar( p ) register NODE *p; { 2749704Slinton if( p->in.op == PLUS ) { 2759704Slinton if( p->in.left->in.su == fregs ) { 2769704Slinton order( p->in.left, INTAREG|INAREG ); 2779704Slinton return; 2789704Slinton } else if( p->in.right->in.su == fregs ) { 2799704Slinton order( p->in.right, INTAREG|INAREG ); 2809704Slinton return; 2819704Slinton } 2829704Slinton if( p->in.left->in.op==LS && 2839704Slinton (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) { 2849704Slinton order( p->in.left->in.left, INTAREG|INAREG ); 2859704Slinton return; 2869704Slinton } 2879704Slinton if( p->in.right->in.op==LS && 2889704Slinton (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) { 2899704Slinton order( p->in.right->in.left, INTAREG|INAREG ); 2909704Slinton return; 2919704Slinton } 2929704Slinton if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { 2939704Slinton if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) { 2949704Slinton order( p->in.left, INTAREG|INAREG ); 2959704Slinton return; 2969704Slinton } 2979704Slinton else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) { 2989704Slinton order(p->in.right, INTAREG|INAREG); 2999704Slinton return; 3009704Slinton } 3019704Slinton } 3029704Slinton } 3039704Slinton if( p->in.op == PLUS || p->in.op == MINUS ){ 3049704Slinton if( p->in.right->in.op == ICON ){ 3059704Slinton p = p->in.left; 3069704Slinton order( p , INTAREG|INAREG); 3079704Slinton return; 3089704Slinton } 3099704Slinton } 3109704Slinton 3119704Slinton if( p->in.op == UNARY MUL && !canaddr(p) ) { 3129704Slinton offstar( p->in.left ); 3139704Slinton return; 3149704Slinton } 3159704Slinton 3169704Slinton order( p, INTAREG|INAREG ); 3179704Slinton } 3189704Slinton 3199704Slinton setincr( p ) register NODE *p; { 3209704Slinton p = p->in.left; 3219704Slinton if( p->in.op == UNARY MUL ){ 3229704Slinton offstar( p ); 3239704Slinton return( 1 ); 3249704Slinton } 3259704Slinton return( 0 ); 3269704Slinton } 3279704Slinton 3289704Slinton setbin( p ) register NODE *p; { 3299704Slinton register ro, rt; 3309704Slinton 3319704Slinton rt = p->in.right->in.type; 3329704Slinton ro = p->in.right->in.op; 3339704Slinton 3349704Slinton if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ 3359704Slinton if( ro == UNARY MUL ) { 3369704Slinton offstar( p->in.right->in.left ); 3379704Slinton return(1); 3389704Slinton } else { 3399704Slinton order( p->in.right, INAREG|INTAREG|SOREG ); 3409704Slinton return(1); 3419704Slinton } 3429704Slinton } 3439704Slinton if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ 3449704Slinton /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ 3459704Slinton order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); 3469704Slinton return(1); 3479704Slinton } 3489704Slinton else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ 3499704Slinton offstar( p->in.right->in.left ); 3509704Slinton return(1); 3519704Slinton } 35216937Sralph else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || 35316937Sralph rt == FLOAT || (ro != REG && ro != NAME && ro != OREG && ro != ICON ) ){ 3549704Slinton order( p->in.right, INAREG|INBREG ); 3559704Slinton return(1); 3569704Slinton } 3579704Slinton /* 3589704Slinton else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */ 3599704Slinton /* 3609704Slinton order( p->in.right, INAREG ); 3619704Slinton return( 1 ); 3629704Slinton } 3639704Slinton */ 3649704Slinton return(0); 3659704Slinton } 3669704Slinton 3679704Slinton setstr( p ) register NODE *p; { /* structure assignment */ 3689704Slinton if( p->in.right->in.op != REG ){ 3699704Slinton order( p->in.right, INTAREG ); 3709704Slinton return(1); 3719704Slinton } 3729704Slinton p = p->in.left; 3739704Slinton if( p->in.op != NAME && p->in.op != OREG ){ 3749704Slinton if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); 3759704Slinton order( p->in.left, INTAREG ); 3769704Slinton return( 1 ); 3779704Slinton } 3789704Slinton return( 0 ); 3799704Slinton } 3809704Slinton 3819704Slinton setasg( p ) register NODE *p; { 3829704Slinton /* setup for assignment operator */ 3839704Slinton 3849704Slinton if( !canaddr(p->in.right) ) { 3859704Slinton if( p->in.right->in.op == UNARY MUL ) 3869704Slinton offstar(p->in.right->in.left); 3879704Slinton else 3889704Slinton order( p->in.right, INAREG|INBREG|SOREG ); 3899704Slinton return(1); 3909704Slinton } 3919704Slinton if( p->in.left->in.op == UNARY MUL ) { 3929704Slinton offstar( p->in.left->in.left ); 3939704Slinton return(1); 3949704Slinton } 3959704Slinton if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 3969704Slinton offstar( p->in.left->in.left->in.left ); 3979704Slinton return(1); 3989704Slinton } 3999704Slinton /* FLD patch */ 4009704Slinton if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) { 4019704Slinton order( p->in.right, INAREG); 4029704Slinton return(1); 4039704Slinton } 4049704Slinton /* end of FLD patch */ 4059704Slinton return(0); 4069704Slinton } 4079704Slinton 4089704Slinton setasop( p ) register NODE *p; { 4099704Slinton /* setup for =ops */ 4109704Slinton register rt, ro; 4119704Slinton 4129704Slinton rt = p->in.right->in.type; 4139704Slinton ro = p->in.right->in.op; 4149704Slinton 4159704Slinton if( ro == UNARY MUL && rt != CHAR ){ 4169704Slinton offstar( p->in.right->in.left ); 4179704Slinton return(1); 4189704Slinton } 41916937Sralph if( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || 42017739Sralph #ifndef SPRECC 42117739Sralph rt == FLOAT || 42217739Sralph #endif 42317739Sralph ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ){ 4249704Slinton order( p->in.right, INAREG|INBREG ); 4259704Slinton return(1); 4269704Slinton } 4279704Slinton /* 4289704Slinton if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){ 4299704Slinton order( p->in.right, INAREG ); 4309704Slinton return(1); 4319704Slinton } 4329704Slinton */ 4339704Slinton 4349704Slinton 4359704Slinton p = p->in.left; 4369704Slinton if( p->in.op == FLD ) p = p->in.left; 4379704Slinton 4389704Slinton switch( p->in.op ){ 4399704Slinton 4409704Slinton case REG: 4419704Slinton case ICON: 4429704Slinton case NAME: 4439704Slinton case OREG: 4449704Slinton return(0); 4459704Slinton 4469704Slinton case UNARY MUL: 4479704Slinton if( p->in.left->in.op==OREG ) 4489704Slinton return(0); 4499704Slinton else 4509704Slinton offstar( p->in.left ); 4519704Slinton return(1); 4529704Slinton 4539704Slinton } 4549704Slinton cerror( "illegal setasop" ); 45517739Sralph /*NOTREACHED*/ 4569704Slinton } 4579704Slinton 45817739Sralph int crslab = 99999; /* VAX */ 4599704Slinton 4609704Slinton getlab(){ 4619704Slinton return( crslab-- ); 4629704Slinton } 4639704Slinton 46432947Sdonn #ifndef deflab 4659704Slinton deflab( l ){ 4669704Slinton printf( "L%d:\n", l ); 4679704Slinton } 46832947Sdonn #endif 4699704Slinton 47016419Sralph genargs( p ) register NODE *p; { 4719704Slinton register NODE *pasg; 4729704Slinton register align; 4739704Slinton register size; 47425752Sdonn int count; 4759704Slinton 4769704Slinton /* generate code for the arguments */ 4779704Slinton 4789704Slinton /* first, do the arguments on the right */ 4799704Slinton while( p->in.op == CM ){ 48016419Sralph genargs( p->in.right ); 4819704Slinton p->in.op = FREE; 4829704Slinton p = p->in.left; 4839704Slinton } 4849704Slinton 4859704Slinton if( p->in.op == STARG ){ /* structure valued argument */ 4869704Slinton 4879704Slinton size = p->stn.stsize; 4889704Slinton align = p->stn.stalign; 4899704Slinton if( p->in.left->in.op == ICON ){ 4909704Slinton p->in.op = FREE; 49116419Sralph p = p->in.left; 4929704Slinton } 4939704Slinton else { 4949704Slinton /* make it look beautiful... */ 4959704Slinton p->in.op = UNARY MUL; 4969704Slinton canon( p ); /* turn it into an oreg */ 49725752Sdonn for( count = 0; p->in.op != OREG && count < 10; ++count ){ 4989704Slinton offstar( p->in.left ); 4999704Slinton canon( p ); 5009704Slinton } 50125752Sdonn if( p->in.op != OREG ) cerror( "stuck starg" ); 5029704Slinton } 5039704Slinton 5049704Slinton pasg = talloc(); 50516419Sralph pasg->in.op = STARG; 50616409Sralph pasg->in.rall = NOPREF; 5079704Slinton pasg->stn.stsize = size; 5089704Slinton pasg->stn.stalign = align; 50916419Sralph pasg->in.left = p; 5109704Slinton 5119704Slinton order( pasg, FORARG ); 5129704Slinton return; 5139704Slinton } 5149704Slinton 5159704Slinton /* ordinary case */ 5169704Slinton 5179704Slinton order( p, FORARG ); 5189704Slinton } 5199704Slinton 5209704Slinton argsize( p ) register NODE *p; { 5219704Slinton register t; 5229704Slinton t = 0; 5239704Slinton if( p->in.op == CM ){ 5249704Slinton t = argsize( p->in.left ); 5259704Slinton p = p->in.right; 5269704Slinton } 5279704Slinton if( p->in.type == DOUBLE || p->in.type == FLOAT ){ 5289704Slinton SETOFF( t, 4 ); 5299704Slinton return( t+8 ); 5309704Slinton } 5319704Slinton else if( p->in.op == STARG ){ 5329704Slinton SETOFF( t, 4 ); /* alignment */ 5339704Slinton return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ 5349704Slinton } 5359704Slinton else { 5369704Slinton SETOFF( t, 4 ); 5379704Slinton return( t+4 ); 5389704Slinton } 5399704Slinton } 540