1*9704Slinton static char *sccsid ="@(#)order.c 1.1 (Berkeley) 12/15/82"; 2*9704Slinton # include "mfile2" 3*9704Slinton 4*9704Slinton int maxargs = { -1 }; 5*9704Slinton 6*9704Slinton stoasg( p, o ) register NODE *p; { 7*9704Slinton /* should the assignment op p be stored, 8*9704Slinton given that it lies as the right operand of o 9*9704Slinton (or the left, if o==UNARY MUL) */ 10*9704Slinton /* 11*9704Slinton if( p->in.op == INCR || p->in.op == DECR ) return; 12*9704Slinton if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG); 13*9704Slinton */ 14*9704Slinton } 15*9704Slinton 16*9704Slinton deltest( p ) register NODE *p; { 17*9704Slinton /* should we delay the INCR or DECR operation p */ 18*9704Slinton p = p->in.left; 19*9704Slinton return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG ); 20*9704Slinton } 21*9704Slinton 22*9704Slinton autoincr( p ) NODE *p; { 23*9704Slinton register NODE *q = p->in.left, *r; 24*9704Slinton 25*9704Slinton if( q->in.op == INCR && (r=q->in.left)->in.op == REG && 26*9704Slinton ISPTR(q->in.type) && p->in.type == DECREF(q->in.type) && 27*9704Slinton tlen(p) == q->in.right->tn.lval ) return(1); 28*9704Slinton 29*9704Slinton return(0); 30*9704Slinton } 31*9704Slinton 32*9704Slinton mkadrs(p) register NODE *p; { 33*9704Slinton register o; 34*9704Slinton 35*9704Slinton o = p->in.op; 36*9704Slinton 37*9704Slinton if( asgop(o) ){ 38*9704Slinton if( p->in.left->in.su >= p->in.right->in.su ){ 39*9704Slinton if( p->in.left->in.op == UNARY MUL ){ 40*9704Slinton SETSTO( p->in.left->in.left, INTEMP ); 41*9704Slinton } 42*9704Slinton else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 43*9704Slinton SETSTO( p->in.left->in.left->in.left, INTEMP ); 44*9704Slinton } 45*9704Slinton else { /* should be only structure assignment */ 46*9704Slinton SETSTO( p->in.left, INTEMP ); 47*9704Slinton } 48*9704Slinton } 49*9704Slinton else SETSTO( p->in.right, INTEMP ); 50*9704Slinton } 51*9704Slinton else { 52*9704Slinton if( p->in.left->in.su > p->in.right->in.su ){ 53*9704Slinton SETSTO( p->in.left, INTEMP ); 54*9704Slinton } 55*9704Slinton else { 56*9704Slinton SETSTO( p->in.right, INTEMP ); 57*9704Slinton } 58*9704Slinton } 59*9704Slinton } 60*9704Slinton 61*9704Slinton notoff( t, r, off, cp) CONSZ off; char *cp; { 62*9704Slinton /* is it legal to make an OREG or NAME entry which has an 63*9704Slinton /* offset of off, (from a register of r), if the 64*9704Slinton /* resulting thing had type t */ 65*9704Slinton 66*9704Slinton /* if( r == R0 ) return( 1 ); /* NO */ 67*9704Slinton return(0); /* YES */ 68*9704Slinton } 69*9704Slinton 70*9704Slinton # define max(x,y) ((x)<(y)?(y):(x)) 71*9704Slinton 72*9704Slinton sucomp( p ) register NODE *p; { 73*9704Slinton 74*9704Slinton /* set the su field in the node to the sethi-ullman 75*9704Slinton number, or local equivalent */ 76*9704Slinton 77*9704Slinton register o, ty, sul, sur, r; 78*9704Slinton 79*9704Slinton o = p->in.op; 80*9704Slinton ty = optype( o ); 81*9704Slinton p->in.su = szty( p->in.type ); /* 2 for float or double, else 1 */; 82*9704Slinton 83*9704Slinton if( ty == LTYPE ){ 84*9704Slinton if( o == OREG ){ 85*9704Slinton r = p->tn.rval; 86*9704Slinton /* oreg cost is (worst case) 1 + number of temp registers used */ 87*9704Slinton if( R2TEST(r) ){ 88*9704Slinton if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su; 89*9704Slinton if( istreg(R2UPK2(r)) ) ++p->in.su; 90*9704Slinton } 91*9704Slinton else { 92*9704Slinton if( istreg( r ) ) ++p->in.su; 93*9704Slinton } 94*9704Slinton } 95*9704Slinton if( p->in.su == szty(p->in.type) && 96*9704Slinton (p->in.op!=REG || !istreg(p->tn.rval)) && 97*9704Slinton (p->in.type==INT || p->in.type==UNSIGNED || p->in.type==DOUBLE) ) 98*9704Slinton p->in.su = 0; 99*9704Slinton return; 100*9704Slinton } 101*9704Slinton 102*9704Slinton else if( ty == UTYPE ){ 103*9704Slinton switch( o ) { 104*9704Slinton case UNARY CALL: 105*9704Slinton case UNARY STCALL: 106*9704Slinton p->in.su = fregs; /* all regs needed */ 107*9704Slinton return; 108*9704Slinton 109*9704Slinton default: 110*9704Slinton p->in.su = p->in.left->in.su + (szty( p->in.type ) > 1 ? 2 : 0) ; 111*9704Slinton return; 112*9704Slinton } 113*9704Slinton } 114*9704Slinton 115*9704Slinton 116*9704Slinton /* If rhs needs n, lhs needs m, regular su computation */ 117*9704Slinton 118*9704Slinton sul = p->in.left->in.su; 119*9704Slinton sur = p->in.right->in.su; 120*9704Slinton 121*9704Slinton if( o == ASSIGN ){ 122*9704Slinton /* computed by doing right, then left (if not in mem), then doing it */ 123*9704Slinton p->in.su = max(sur,sul+1); 124*9704Slinton return; 125*9704Slinton } 126*9704Slinton 127*9704Slinton if( o == CALL || o == STCALL ){ 128*9704Slinton /* in effect, takes all free registers */ 129*9704Slinton p->in.su = fregs; 130*9704Slinton return; 131*9704Slinton } 132*9704Slinton 133*9704Slinton if( o == STASG ){ 134*9704Slinton /* right, then left */ 135*9704Slinton p->in.su = max( max( 1+sul, sur), fregs ); 136*9704Slinton return; 137*9704Slinton } 138*9704Slinton 139*9704Slinton if( asgop(o) ){ 140*9704Slinton /* computed by doing right, doing left address, doing left, op, and store */ 141*9704Slinton p->in.su = max(sur,sul+2); 142*9704Slinton /* 143*9704Slinton if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs); 144*9704Slinton */ 145*9704Slinton return; 146*9704Slinton } 147*9704Slinton 148*9704Slinton switch( o ){ 149*9704Slinton case ANDAND: 150*9704Slinton case OROR: 151*9704Slinton case QUEST: 152*9704Slinton case COLON: 153*9704Slinton case COMOP: 154*9704Slinton p->in.su = max( max(sul,sur), 1); 155*9704Slinton return; 156*9704Slinton 157*9704Slinton case PLUS: 158*9704Slinton case OR: 159*9704Slinton case ER: 160*9704Slinton /* commutative ops; put harder on left */ 161*9704Slinton if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ 162*9704Slinton register NODE *temp; 163*9704Slinton temp = p->in.left; 164*9704Slinton p->in.left = p->in.right; 165*9704Slinton p->in.right = temp; 166*9704Slinton } 167*9704Slinton break; 168*9704Slinton } 169*9704Slinton 170*9704Slinton /* binary op, computed by left, then right, then do op */ 171*9704Slinton p->in.su = max(sul,szty(p->in.right->in.type)+sur); 172*9704Slinton /* 173*9704Slinton if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs); 174*9704Slinton */ 175*9704Slinton 176*9704Slinton } 177*9704Slinton 178*9704Slinton int radebug = 0; 179*9704Slinton 180*9704Slinton rallo( p, down ) NODE *p; { 181*9704Slinton /* do register allocation */ 182*9704Slinton register o, type, down1, down2, ty; 183*9704Slinton 184*9704Slinton if( radebug ) printf( "rallo( %o, %d )\n", p, down ); 185*9704Slinton 186*9704Slinton down2 = NOPREF; 187*9704Slinton p->in.rall = down; 188*9704Slinton down1 = ( down &= ~MUSTDO ); 189*9704Slinton 190*9704Slinton ty = optype( o = p->in.op ); 191*9704Slinton type = p->in.type; 192*9704Slinton 193*9704Slinton 194*9704Slinton if( type == DOUBLE || type == FLOAT ){ 195*9704Slinton if( o == FORCE ) down1 = R0|MUSTDO; 196*9704Slinton } 197*9704Slinton else switch( o ) { 198*9704Slinton case ASSIGN: 199*9704Slinton down1 = NOPREF; 200*9704Slinton down2 = down; 201*9704Slinton break; 202*9704Slinton 203*9704Slinton /* 204*9704Slinton case MUL: 205*9704Slinton case DIV: 206*9704Slinton case MOD: 207*9704Slinton down1 = R3|MUSTDO; 208*9704Slinton down2 = R5|MUSTDO; 209*9704Slinton break; 210*9704Slinton 211*9704Slinton case ASG MUL: 212*9704Slinton case ASG DIV: 213*9704Slinton case ASG MOD: 214*9704Slinton p->in.left->in.rall = down1 = R3|MUSTDO; 215*9704Slinton if( p->in.left->in.op == UNARY MUL ){ 216*9704Slinton rallo( p->in.left->in.left, R4|MUSTDO ); 217*9704Slinton } 218*9704Slinton else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 219*9704Slinton rallo( p->in.left->in.left->in.left, R4|MUSTDO ); 220*9704Slinton } 221*9704Slinton else rallo( p->in.left, R3|MUSTDO ); 222*9704Slinton rallo( p->in.right, R5|MUSTDO ); 223*9704Slinton return; 224*9704Slinton */ 225*9704Slinton 226*9704Slinton case CALL: 227*9704Slinton case STASG: 228*9704Slinton case EQ: 229*9704Slinton case NE: 230*9704Slinton case GT: 231*9704Slinton case GE: 232*9704Slinton case LT: 233*9704Slinton case LE: 234*9704Slinton case NOT: 235*9704Slinton case ANDAND: 236*9704Slinton case OROR: 237*9704Slinton down1 = NOPREF; 238*9704Slinton break; 239*9704Slinton 240*9704Slinton case FORCE: 241*9704Slinton down1 = R0|MUSTDO; 242*9704Slinton break; 243*9704Slinton 244*9704Slinton } 245*9704Slinton 246*9704Slinton if( ty != LTYPE ) rallo( p->in.left, down1 ); 247*9704Slinton if( ty == BITYPE ) rallo( p->in.right, down2 ); 248*9704Slinton 249*9704Slinton } 250*9704Slinton 251*9704Slinton offstar( p ) register NODE *p; { 252*9704Slinton if( p->in.op == PLUS ) { 253*9704Slinton if( p->in.left->in.su == fregs ) { 254*9704Slinton order( p->in.left, INTAREG|INAREG ); 255*9704Slinton return; 256*9704Slinton } else if( p->in.right->in.su == fregs ) { 257*9704Slinton order( p->in.right, INTAREG|INAREG ); 258*9704Slinton return; 259*9704Slinton } 260*9704Slinton if( p->in.left->in.op==LS && 261*9704Slinton (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) { 262*9704Slinton order( p->in.left->in.left, INTAREG|INAREG ); 263*9704Slinton return; 264*9704Slinton } 265*9704Slinton if( p->in.right->in.op==LS && 266*9704Slinton (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) { 267*9704Slinton order( p->in.right->in.left, INTAREG|INAREG ); 268*9704Slinton return; 269*9704Slinton } 270*9704Slinton if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { 271*9704Slinton if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) { 272*9704Slinton order( p->in.left, INTAREG|INAREG ); 273*9704Slinton return; 274*9704Slinton } 275*9704Slinton else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) { 276*9704Slinton order(p->in.right, INTAREG|INAREG); 277*9704Slinton return; 278*9704Slinton } 279*9704Slinton } 280*9704Slinton } 281*9704Slinton if( p->in.op == PLUS || p->in.op == MINUS ){ 282*9704Slinton if( p->in.right->in.op == ICON ){ 283*9704Slinton p = p->in.left; 284*9704Slinton order( p , INTAREG|INAREG); 285*9704Slinton return; 286*9704Slinton } 287*9704Slinton } 288*9704Slinton 289*9704Slinton if( p->in.op == UNARY MUL && !canaddr(p) ) { 290*9704Slinton offstar( p->in.left ); 291*9704Slinton return; 292*9704Slinton } 293*9704Slinton 294*9704Slinton order( p, INTAREG|INAREG ); 295*9704Slinton } 296*9704Slinton 297*9704Slinton setincr( p ) register NODE *p; { 298*9704Slinton p = p->in.left; 299*9704Slinton if( p->in.op == UNARY MUL ){ 300*9704Slinton offstar( p ); 301*9704Slinton return( 1 ); 302*9704Slinton } 303*9704Slinton return( 0 ); 304*9704Slinton } 305*9704Slinton 306*9704Slinton setbin( p ) register NODE *p; { 307*9704Slinton register ro, rt; 308*9704Slinton 309*9704Slinton rt = p->in.right->in.type; 310*9704Slinton ro = p->in.right->in.op; 311*9704Slinton 312*9704Slinton if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ 313*9704Slinton if( ro == UNARY MUL ) { 314*9704Slinton offstar( p->in.right->in.left ); 315*9704Slinton return(1); 316*9704Slinton } else { 317*9704Slinton order( p->in.right, INAREG|INTAREG|SOREG ); 318*9704Slinton return(1); 319*9704Slinton } 320*9704Slinton } 321*9704Slinton if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ 322*9704Slinton /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ 323*9704Slinton order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); 324*9704Slinton return(1); 325*9704Slinton } 326*9704Slinton else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ 327*9704Slinton offstar( p->in.right->in.left ); 328*9704Slinton return(1); 329*9704Slinton } 330*9704Slinton else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG && 331*9704Slinton ro != NAME && ro != OREG && ro != ICON ) ){ 332*9704Slinton order( p->in.right, INAREG|INBREG ); 333*9704Slinton return(1); 334*9704Slinton } 335*9704Slinton /* 336*9704Slinton else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */ 337*9704Slinton /* 338*9704Slinton order( p->in.right, INAREG ); 339*9704Slinton return( 1 ); 340*9704Slinton } 341*9704Slinton */ 342*9704Slinton return(0); 343*9704Slinton } 344*9704Slinton 345*9704Slinton setstr( p ) register NODE *p; { /* structure assignment */ 346*9704Slinton if( p->in.right->in.op != REG ){ 347*9704Slinton order( p->in.right, INTAREG ); 348*9704Slinton return(1); 349*9704Slinton } 350*9704Slinton p = p->in.left; 351*9704Slinton if( p->in.op != NAME && p->in.op != OREG ){ 352*9704Slinton if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); 353*9704Slinton order( p->in.left, INTAREG ); 354*9704Slinton return( 1 ); 355*9704Slinton } 356*9704Slinton return( 0 ); 357*9704Slinton } 358*9704Slinton 359*9704Slinton setasg( p ) register NODE *p; { 360*9704Slinton /* setup for assignment operator */ 361*9704Slinton 362*9704Slinton if( !canaddr(p->in.right) ) { 363*9704Slinton if( p->in.right->in.op == UNARY MUL ) 364*9704Slinton offstar(p->in.right->in.left); 365*9704Slinton else 366*9704Slinton order( p->in.right, INAREG|INBREG|SOREG ); 367*9704Slinton return(1); 368*9704Slinton } 369*9704Slinton if( p->in.left->in.op == UNARY MUL ) { 370*9704Slinton offstar( p->in.left->in.left ); 371*9704Slinton return(1); 372*9704Slinton } 373*9704Slinton if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 374*9704Slinton offstar( p->in.left->in.left->in.left ); 375*9704Slinton return(1); 376*9704Slinton } 377*9704Slinton /* FLD patch */ 378*9704Slinton if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) { 379*9704Slinton order( p->in.right, INAREG); 380*9704Slinton return(1); 381*9704Slinton } 382*9704Slinton /* end of FLD patch */ 383*9704Slinton return(0); 384*9704Slinton } 385*9704Slinton 386*9704Slinton setasop( p ) register NODE *p; { 387*9704Slinton /* setup for =ops */ 388*9704Slinton register rt, ro; 389*9704Slinton 390*9704Slinton rt = p->in.right->in.type; 391*9704Slinton ro = p->in.right->in.op; 392*9704Slinton 393*9704Slinton if( ro == UNARY MUL && rt != CHAR ){ 394*9704Slinton offstar( p->in.right->in.left ); 395*9704Slinton return(1); 396*9704Slinton } 397*9704Slinton if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || 398*9704Slinton ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){ 399*9704Slinton order( p->in.right, INAREG|INBREG ); 400*9704Slinton return(1); 401*9704Slinton } 402*9704Slinton /* 403*9704Slinton if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){ 404*9704Slinton order( p->in.right, INAREG ); 405*9704Slinton return(1); 406*9704Slinton } 407*9704Slinton */ 408*9704Slinton 409*9704Slinton 410*9704Slinton p = p->in.left; 411*9704Slinton if( p->in.op == FLD ) p = p->in.left; 412*9704Slinton 413*9704Slinton switch( p->in.op ){ 414*9704Slinton 415*9704Slinton case REG: 416*9704Slinton case ICON: 417*9704Slinton case NAME: 418*9704Slinton case OREG: 419*9704Slinton return(0); 420*9704Slinton 421*9704Slinton case UNARY MUL: 422*9704Slinton if( p->in.left->in.op==OREG ) 423*9704Slinton return(0); 424*9704Slinton else 425*9704Slinton offstar( p->in.left ); 426*9704Slinton return(1); 427*9704Slinton 428*9704Slinton } 429*9704Slinton cerror( "illegal setasop" ); 430*9704Slinton } 431*9704Slinton 432*9704Slinton int crslab = 9999; /* Honeywell */ 433*9704Slinton 434*9704Slinton getlab(){ 435*9704Slinton return( crslab-- ); 436*9704Slinton } 437*9704Slinton 438*9704Slinton deflab( l ){ 439*9704Slinton printf( "L%d:\n", l ); 440*9704Slinton } 441*9704Slinton 442*9704Slinton genargs( p, ptemp ) register NODE *p, *ptemp; { 443*9704Slinton register NODE *pasg; 444*9704Slinton register align; 445*9704Slinton register size; 446*9704Slinton register TWORD type; 447*9704Slinton 448*9704Slinton /* generate code for the arguments */ 449*9704Slinton 450*9704Slinton /* first, do the arguments on the right */ 451*9704Slinton while( p->in.op == CM ){ 452*9704Slinton genargs( p->in.right, ptemp ); 453*9704Slinton p->in.op = FREE; 454*9704Slinton p = p->in.left; 455*9704Slinton } 456*9704Slinton 457*9704Slinton if( p->in.op == STARG ){ /* structure valued argument */ 458*9704Slinton 459*9704Slinton size = p->stn.stsize; 460*9704Slinton align = p->stn.stalign; 461*9704Slinton if( p->in.left->in.op == ICON ){ 462*9704Slinton p->in.op = FREE; 463*9704Slinton p= p->in.left; 464*9704Slinton } 465*9704Slinton else { 466*9704Slinton /* make it look beautiful... */ 467*9704Slinton p->in.op = UNARY MUL; 468*9704Slinton canon( p ); /* turn it into an oreg */ 469*9704Slinton if( p->in.op != OREG ){ 470*9704Slinton offstar( p->in.left ); 471*9704Slinton canon( p ); 472*9704Slinton if( p->in.op != OREG ){ 473*9704Slinton offstar( p->in.left ); 474*9704Slinton canon( p ); 475*9704Slinton if( p->in.op != OREG ) cerror( "stuck starg" ); 476*9704Slinton } 477*9704Slinton } 478*9704Slinton } 479*9704Slinton 480*9704Slinton 481*9704Slinton ptemp->tn.lval = 0; /* all moves to (sp) */ 482*9704Slinton 483*9704Slinton pasg = talloc(); 484*9704Slinton pasg->in.op = STASG; 485*9704Slinton pasg->stn.stsize = size; 486*9704Slinton pasg->stn.stalign = align; 487*9704Slinton pasg->in.right = p; 488*9704Slinton pasg->in.left = tcopy( ptemp ); 489*9704Slinton 490*9704Slinton /* the following line is done only with the knowledge 491*9704Slinton that it will be undone by the STASG node, with the 492*9704Slinton offset (lval) field retained */ 493*9704Slinton 494*9704Slinton if( p->in.op == OREG ) p->in.op = REG; /* only for temporaries */ 495*9704Slinton 496*9704Slinton order( pasg, FORARG ); 497*9704Slinton ptemp->tn.lval += size; 498*9704Slinton return; 499*9704Slinton } 500*9704Slinton 501*9704Slinton /* ordinary case */ 502*9704Slinton 503*9704Slinton order( p, FORARG ); 504*9704Slinton } 505*9704Slinton 506*9704Slinton argsize( p ) register NODE *p; { 507*9704Slinton register t; 508*9704Slinton t = 0; 509*9704Slinton if( p->in.op == CM ){ 510*9704Slinton t = argsize( p->in.left ); 511*9704Slinton p = p->in.right; 512*9704Slinton } 513*9704Slinton if( p->in.type == DOUBLE || p->in.type == FLOAT ){ 514*9704Slinton SETOFF( t, 4 ); 515*9704Slinton return( t+8 ); 516*9704Slinton } 517*9704Slinton else if( p->in.op == STARG ){ 518*9704Slinton SETOFF( t, 4 ); /* alignment */ 519*9704Slinton return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ 520*9704Slinton } 521*9704Slinton else { 522*9704Slinton SETOFF( t, 4 ); 523*9704Slinton return( t+4 ); 524*9704Slinton } 525*9704Slinton } 526*9704Slinton 527*9704Slinton 528