117739Sralph #ifndef lint 2*32951Sdonn static char *sccsid ="@(#)order.c 1.12 (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 15932950Sdonn switch( o ){ 16032950Sdonn case DIV: 16132950Sdonn case ASG DIV: 16232950Sdonn case MOD: 16332950Sdonn case ASG MOD: 16432950Sdonn /* EDIV instructions require reg pairs */ 16532950Sdonn if( p->in.left->in.type == UNSIGNED && 16632950Sdonn p->in.right->in.op == ICON && 16732950Sdonn p->in.right->tn.name[0] == '\0' && 16832950Sdonn (unsigned) p->in.right->tn.lval < 0x80000000 ) { 169*32951Sdonn p->in.su = sul + 2; 17032950Sdonn return; 17132950Sdonn } 17232950Sdonn break; 17332950Sdonn } 17432950Sdonn 1759704Slinton if( asgop(o) ){ 1769704Slinton /* computed by doing right, doing left address, doing left, op, and store */ 1779704Slinton p->in.su = max(sur,sul+2); 1789704Slinton /* 1799704Slinton if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs); 1809704Slinton */ 1819704Slinton return; 1829704Slinton } 1839704Slinton 1849704Slinton switch( o ){ 1859704Slinton case ANDAND: 1869704Slinton case OROR: 1879704Slinton case QUEST: 1889704Slinton case COLON: 1899704Slinton case COMOP: 1909704Slinton p->in.su = max( max(sul,sur), 1); 1919704Slinton return; 1929704Slinton 19317739Sralph case MUL: 1949704Slinton case PLUS: 1959704Slinton case OR: 1969704Slinton case ER: 1979704Slinton /* commutative ops; put harder on left */ 1989704Slinton if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ 1999704Slinton temp = p->in.left; 2009704Slinton p->in.left = p->in.right; 2019704Slinton p->in.right = temp; 20217739Sralph sul = p->in.left->in.su; 20317739Sralph sur = p->in.right->in.su; 20417739Sralph szr = szty( p->in.right->in.type ); 20517739Sralph if( szty( p->in.type ) > szr && szr >= 1 ) { 20617739Sralph /* implicit conversion in rhs */ 20717739Sralph szr = szty( p->in.type ); 20817739Sralph sur = max( szr, sur ); 20917739Sralph } 2109704Slinton } 2119704Slinton break; 2129704Slinton } 2139704Slinton 2149704Slinton /* binary op, computed by left, then right, then do op */ 21517739Sralph p->in.su = max(sul,szr+sur); 2169704Slinton /* 2179704Slinton if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs); 2189704Slinton */ 2199704Slinton 2209704Slinton } 2219704Slinton 2229704Slinton int radebug = 0; 2239704Slinton 2249704Slinton rallo( p, down ) NODE *p; { 2259704Slinton /* do register allocation */ 2269704Slinton register o, type, down1, down2, ty; 2279704Slinton 2289704Slinton if( radebug ) printf( "rallo( %o, %d )\n", p, down ); 2299704Slinton 2309704Slinton down2 = NOPREF; 2319704Slinton p->in.rall = down; 2329704Slinton down1 = ( down &= ~MUSTDO ); 2339704Slinton 2349704Slinton ty = optype( o = p->in.op ); 2359704Slinton type = p->in.type; 2369704Slinton 2379704Slinton 2389704Slinton if( type == DOUBLE || type == FLOAT ){ 2399704Slinton if( o == FORCE ) down1 = R0|MUSTDO; 2409704Slinton } 2419704Slinton else switch( o ) { 2429704Slinton case ASSIGN: 2439704Slinton down1 = NOPREF; 2449704Slinton down2 = down; 2459704Slinton break; 2469704Slinton 2479704Slinton case CALL: 2489704Slinton case STASG: 2499704Slinton case EQ: 2509704Slinton case NE: 2519704Slinton case GT: 2529704Slinton case GE: 2539704Slinton case LT: 2549704Slinton case LE: 2559704Slinton case NOT: 2569704Slinton case ANDAND: 2579704Slinton case OROR: 2589704Slinton down1 = NOPREF; 2599704Slinton break; 2609704Slinton 2619704Slinton case FORCE: 2629704Slinton down1 = R0|MUSTDO; 2639704Slinton break; 2649704Slinton 2659704Slinton } 2669704Slinton 2679704Slinton if( ty != LTYPE ) rallo( p->in.left, down1 ); 2689704Slinton if( ty == BITYPE ) rallo( p->in.right, down2 ); 2699704Slinton 2709704Slinton } 2719704Slinton 2729704Slinton offstar( p ) register NODE *p; { 2739704Slinton if( p->in.op == PLUS ) { 2749704Slinton if( p->in.left->in.su == fregs ) { 2759704Slinton order( p->in.left, INTAREG|INAREG ); 2769704Slinton return; 2779704Slinton } else if( p->in.right->in.su == fregs ) { 2789704Slinton order( p->in.right, INTAREG|INAREG ); 2799704Slinton return; 2809704Slinton } 2819704Slinton if( p->in.left->in.op==LS && 2829704Slinton (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) { 2839704Slinton order( p->in.left->in.left, INTAREG|INAREG ); 2849704Slinton return; 2859704Slinton } 2869704Slinton if( p->in.right->in.op==LS && 2879704Slinton (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) { 2889704Slinton order( p->in.right->in.left, INTAREG|INAREG ); 2899704Slinton return; 2909704Slinton } 2919704Slinton if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { 2929704Slinton if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) { 2939704Slinton order( p->in.left, INTAREG|INAREG ); 2949704Slinton return; 2959704Slinton } 2969704Slinton else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) { 2979704Slinton order(p->in.right, INTAREG|INAREG); 2989704Slinton return; 2999704Slinton } 3009704Slinton } 3019704Slinton } 3029704Slinton if( p->in.op == PLUS || p->in.op == MINUS ){ 3039704Slinton if( p->in.right->in.op == ICON ){ 3049704Slinton p = p->in.left; 3059704Slinton order( p , INTAREG|INAREG); 3069704Slinton return; 3079704Slinton } 3089704Slinton } 3099704Slinton 3109704Slinton if( p->in.op == UNARY MUL && !canaddr(p) ) { 3119704Slinton offstar( p->in.left ); 3129704Slinton return; 3139704Slinton } 3149704Slinton 3159704Slinton order( p, INTAREG|INAREG ); 3169704Slinton } 3179704Slinton 3189704Slinton setincr( p ) register NODE *p; { 3199704Slinton p = p->in.left; 3209704Slinton if( p->in.op == UNARY MUL ){ 3219704Slinton offstar( p ); 3229704Slinton return( 1 ); 3239704Slinton } 3249704Slinton return( 0 ); 3259704Slinton } 3269704Slinton 3279704Slinton setbin( p ) register NODE *p; { 3289704Slinton register ro, rt; 3299704Slinton 3309704Slinton rt = p->in.right->in.type; 3319704Slinton ro = p->in.right->in.op; 3329704Slinton 3339704Slinton if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ 3349704Slinton if( ro == UNARY MUL ) { 3359704Slinton offstar( p->in.right->in.left ); 3369704Slinton return(1); 3379704Slinton } else { 3389704Slinton order( p->in.right, INAREG|INTAREG|SOREG ); 3399704Slinton return(1); 3409704Slinton } 3419704Slinton } 3429704Slinton if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ 3439704Slinton /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ 3449704Slinton order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); 3459704Slinton return(1); 3469704Slinton } 3479704Slinton else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ 3489704Slinton offstar( p->in.right->in.left ); 3499704Slinton return(1); 3509704Slinton } 35116937Sralph else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || 35216937Sralph rt == FLOAT || (ro != REG && ro != NAME && ro != OREG && ro != ICON ) ){ 3539704Slinton order( p->in.right, INAREG|INBREG ); 3549704Slinton return(1); 3559704Slinton } 3569704Slinton /* 3579704Slinton else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */ 3589704Slinton /* 3599704Slinton order( p->in.right, INAREG ); 3609704Slinton return( 1 ); 3619704Slinton } 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 */ 4099704Slinton register 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 if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){ 4289704Slinton order( p->in.right, INAREG ); 4299704Slinton return(1); 4309704Slinton } 4319704Slinton */ 4329704Slinton 4339704Slinton 4349704Slinton p = p->in.left; 4359704Slinton if( p->in.op == FLD ) p = p->in.left; 4369704Slinton 4379704Slinton switch( p->in.op ){ 4389704Slinton 4399704Slinton case REG: 4409704Slinton case ICON: 4419704Slinton case NAME: 4429704Slinton case OREG: 4439704Slinton return(0); 4449704Slinton 4459704Slinton case UNARY MUL: 4469704Slinton if( p->in.left->in.op==OREG ) 4479704Slinton return(0); 4489704Slinton else 4499704Slinton offstar( p->in.left ); 4509704Slinton return(1); 4519704Slinton 4529704Slinton } 4539704Slinton cerror( "illegal setasop" ); 45417739Sralph /*NOTREACHED*/ 4559704Slinton } 4569704Slinton 45717739Sralph int crslab = 99999; /* VAX */ 4589704Slinton 4599704Slinton getlab(){ 4609704Slinton return( crslab-- ); 4619704Slinton } 4629704Slinton 46332947Sdonn #ifndef deflab 4649704Slinton deflab( l ){ 4659704Slinton printf( "L%d:\n", l ); 4669704Slinton } 46732947Sdonn #endif 4689704Slinton 46916419Sralph genargs( p ) register NODE *p; { 4709704Slinton register NODE *pasg; 4719704Slinton register align; 4729704Slinton register size; 47325752Sdonn int count; 4749704Slinton 4759704Slinton /* generate code for the arguments */ 4769704Slinton 4779704Slinton /* first, do the arguments on the right */ 4789704Slinton while( p->in.op == CM ){ 47916419Sralph genargs( p->in.right ); 4809704Slinton p->in.op = FREE; 4819704Slinton p = p->in.left; 4829704Slinton } 4839704Slinton 4849704Slinton if( p->in.op == STARG ){ /* structure valued argument */ 4859704Slinton 4869704Slinton size = p->stn.stsize; 4879704Slinton align = p->stn.stalign; 4889704Slinton if( p->in.left->in.op == ICON ){ 4899704Slinton p->in.op = FREE; 49016419Sralph p = p->in.left; 4919704Slinton } 4929704Slinton else { 4939704Slinton /* make it look beautiful... */ 4949704Slinton p->in.op = UNARY MUL; 4959704Slinton canon( p ); /* turn it into an oreg */ 49625752Sdonn for( count = 0; p->in.op != OREG && count < 10; ++count ){ 4979704Slinton offstar( p->in.left ); 4989704Slinton canon( p ); 4999704Slinton } 50025752Sdonn if( p->in.op != OREG ) cerror( "stuck starg" ); 5019704Slinton } 5029704Slinton 5039704Slinton pasg = talloc(); 50416419Sralph pasg->in.op = STARG; 50516409Sralph pasg->in.rall = NOPREF; 5069704Slinton pasg->stn.stsize = size; 5079704Slinton pasg->stn.stalign = align; 50816419Sralph pasg->in.left = p; 5099704Slinton 5109704Slinton order( pasg, FORARG ); 5119704Slinton return; 5129704Slinton } 5139704Slinton 5149704Slinton /* ordinary case */ 5159704Slinton 5169704Slinton order( p, FORARG ); 5179704Slinton } 5189704Slinton 5199704Slinton argsize( p ) register NODE *p; { 5209704Slinton register t; 5219704Slinton t = 0; 5229704Slinton if( p->in.op == CM ){ 5239704Slinton t = argsize( p->in.left ); 5249704Slinton p = p->in.right; 5259704Slinton } 5269704Slinton if( p->in.type == DOUBLE || p->in.type == FLOAT ){ 5279704Slinton SETOFF( t, 4 ); 5289704Slinton return( t+8 ); 5299704Slinton } 5309704Slinton else if( p->in.op == STARG ){ 5319704Slinton SETOFF( t, 4 ); /* alignment */ 5329704Slinton return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ 5339704Slinton } 5349704Slinton else { 5359704Slinton SETOFF( t, 4 ); 5369704Slinton return( t+4 ); 5379704Slinton } 5389704Slinton } 539