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