|
|
1.1 ! root 1: # include "mfile2" ! 2: ! 3: NODE resc[3]; ! 4: ! 5: int busy[REGSZ]; ! 6: ! 7: int maxa, mina, maxb, minb; ! 8: ! 9: allo0(){ /* free everything */ ! 10: ! 11: register i; ! 12: ! 13: maxa = maxb = -1; ! 14: mina = minb = 0; ! 15: ! 16: REGLOOP(i){ ! 17: busy[i] = 0; ! 18: if( rstatus[i] & STAREG ){ ! 19: if( maxa<0 ) mina = i; ! 20: maxa = i; ! 21: } ! 22: if( rstatus[i] & STBREG ){ ! 23: if( maxb<0 ) minb = i; ! 24: maxb = i; ! 25: } ! 26: } ! 27: } ! 28: ! 29: # define TBUSY 01000 ! 30: ! 31: allo( p, q ) NODE *p; struct optab *q; { ! 32: ! 33: register n, i, j; ! 34: ! 35: n = q->needs; ! 36: i = 0; ! 37: ! 38: while( n & NACOUNT ){ ! 39: resc[i].op = REG; ! 40: resc[i].rval = freereg( p, n&NAMASK ); ! 41: resc[i].lval = 0; ! 42: resc[i].name[0] = '\0'; ! 43: n -= NAREG; ! 44: ++i; ! 45: } ! 46: ! 47: while( n & NBCOUNT ){ ! 48: resc[i].op = REG; ! 49: resc[i].rval = freereg( p, n&NBMASK ); ! 50: resc[i].lval = 0; ! 51: resc[i].name[0] = '\0'; ! 52: n -= NBREG; ! 53: ++i; ! 54: } ! 55: ! 56: if( n & NTMASK ){ ! 57: resc[i].op = OREG; ! 58: resc[i].rval = TMPREG; ! 59: if( p->op == STCALL || p->op == STARG || p->op == UNARY STCALL || p->op == STASG ){ ! 60: resc[i].lval = freetemp( (SZCHAR*p->stsize + (SZINT-1))/SZINT ); ! 61: } ! 62: else { ! 63: resc[i].lval = freetemp( (n&NTMASK)/NTEMP ); ! 64: } ! 65: resc[i].name[0] = '\0'; ! 66: resc[i].lval = BITOOR(resc[i].lval); ! 67: ++i; ! 68: } ! 69: ! 70: /* turn off "temporarily busy" bit */ ! 71: ! 72: REGLOOP(j){ ! 73: busy[j] &= ~TBUSY; ! 74: } ! 75: ! 76: for( j=0; j<i; ++j ) if( resc[j].rval < 0 ) return(0); ! 77: return(1); ! 78: ! 79: } ! 80: ! 81: freetemp( k ){ /* allocate k integers worth of temp space */ ! 82: /* we also make the convention that, if the number of words is more than 1, ! 83: /* it must be aligned for storing doubles... */ ! 84: ! 85: # ifndef BACKTEMP ! 86: int t; ! 87: ! 88: if( k>1 ){ ! 89: SETOFF( tmpoff, ALDOUBLE ); ! 90: } ! 91: ! 92: t = tmpoff; ! 93: tmpoff += k*SZINT; ! 94: if( tmpoff > maxoff ) maxoff = tmpoff; ! 95: if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff; ! 96: return(t); ! 97: ! 98: # else ! 99: tmpoff += k*SZINT; ! 100: if( k>1 ) { ! 101: SETOFF( tmpoff, ALDOUBLE ); ! 102: } ! 103: if( tmpoff > maxoff ) maxoff = tmpoff; ! 104: if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff; ! 105: return( -tmpoff ); ! 106: # endif ! 107: } ! 108: ! 109: freereg( p, n ) NODE *p; { ! 110: /* allocate a register of type n */ ! 111: /* p gives the type, if floating */ ! 112: ! 113: register j; ! 114: ! 115: /* not general; means that only one register (the result) OK for call */ ! 116: if( callop(p->op) ){ ! 117: j = callreg(p); ! 118: if( usable( p, n, j ) ) return( j ); ! 119: /* have allocated callreg first */ ! 120: } ! 121: j = p->rall & ~MUSTDO; ! 122: if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */ ! 123: return( j ); ! 124: } ! 125: if( n&NAMASK ){ ! 126: for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){ ! 127: if( usable(p,n,j) ){ ! 128: return( j ); ! 129: } ! 130: } ! 131: } ! 132: else if( n &NBMASK ){ ! 133: for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){ ! 134: if( usable(p,n,j) ){ ! 135: return(j); ! 136: } ! 137: } ! 138: } ! 139: ! 140: return( -1 ); ! 141: } ! 142: ! 143: usable( p, n, r ) NODE *p; { ! 144: /* decide if register r is usable in tree p to satisfy need n */ ! 145: ! 146: /* checks, for the moment */ ! 147: if( !istreg(r) ) cerror( "usable asked about nontemp register" ); ! 148: ! 149: if( busy[r] > 1 ) return(0); ! 150: if( isbreg(r) ){ ! 151: if( n&NAMASK ) return(0); ! 152: } ! 153: else { ! 154: if( n & NBMASK ) return(0); ! 155: } ! 156: if( (n&NAMASK) && (szty(p->type) == 2) ){ /* only do the pairing for real regs */ ! 157: if( !istreg(r+1) ) return( 0 ); ! 158: if( busy[r+1] > 1 ) return( 0 ); ! 159: if( busy[r] == 0 && busy[r+1] == 0 || ! 160: busy[r+1] == 0 && shareit( p, r, n ) || ! 161: busy[r] == 0 && shareit( p, r+1, n ) || ! 162: shareit( p, r, n ) && shareit( p, r+1, n ) ){ ! 163: busy[r] |= TBUSY; ! 164: busy[r+1] |= TBUSY; ! 165: return(1); ! 166: } ! 167: else return(0); ! 168: } ! 169: if( busy[r] == 0 ) { ! 170: busy[r] |= TBUSY; ! 171: return(1); ! 172: } ! 173: ! 174: /* busy[r] is 1: is there chance for sharing */ ! 175: return( shareit( p, r, n ) ); ! 176: ! 177: } ! 178: ! 179: shareit( p, r, n ) NODE *p; { ! 180: /* can we make register r available by sharing from p ! 181: given that the need is n */ ! 182: if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1); ! 183: if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1); ! 184: return(0); ! 185: } ! 186: ! 187: ushare( p, f, r ) NODE *p; { ! 188: /* can we find a register r to share on the left or right ! 189: (as f=='L' or 'R', respectively) of p */ ! 190: p = getlr( p, f ); ! 191: if( p->op == UNARY MUL ) p = p->left; ! 192: if( p->op == OREG ){ ! 193: if( R2TEST(p->rval) ){ ! 194: return( r==R2UPK1(p->rval) || r==R2UPK2(p->rval) ); ! 195: } ! 196: else return( r == p->rval ); ! 197: } ! 198: if( p->op == REG ){ ! 199: return( r == p->rval || ( szty(p->type) == 2 && r==p->rval+1 ) ); ! 200: } ! 201: return(0); ! 202: } ! 203: ! 204: recl2( p ) register NODE *p; { ! 205: register r = p->rval; ! 206: if( p->op == REG ) rfree( r, p->type ); ! 207: else if( p->op == OREG ) { ! 208: if( R2TEST( r ) ) { ! 209: if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT ); ! 210: rfree( R2UPK2( r ), INT ); ! 211: } ! 212: else { ! 213: rfree( r, PTR+INT ); ! 214: } ! 215: } ! 216: } ! 217: ! 218: int rdebug = 0; ! 219: ! 220: rfree( r, t ) TWORD t; { ! 221: /* mark register r free, if it is legal to do so */ ! 222: /* t is the type */ ! 223: ! 224: if( rdebug ){ ! 225: printf( "rfree( %s ), size %d\n", rnames[r], szty(t) ); ! 226: } ! 227: ! 228: if( istreg(r) ){ ! 229: if( --busy[r] < 0 ) cerror( "register overfreed"); ! 230: if( szty(t) == 2 ){ ! 231: if( (istreg(r)^istreg(r+1)) ) cerror( "illegal free" ); ! 232: if( --busy[r+1] < 0 ) cerror( "register overfreed" ); ! 233: } ! 234: } ! 235: } ! 236: ! 237: rbusy(r,t) TWORD t; { ! 238: /* mark register r busy */ ! 239: /* t is the type */ ! 240: ! 241: if( rdebug ){ ! 242: printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) ); ! 243: } ! 244: ! 245: if( istreg(r) ) ++busy[r]; ! 246: if( szty(t) == 2 ){ ! 247: if( istreg(r+1) ) ++busy[r+1]; ! 248: if( (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" ); ! 249: } ! 250: } ! 251: ! 252: rwprint( rw ){ /* print rewriting rule */ ! 253: register i, flag; ! 254: static char * rwnames[] = { ! 255: ! 256: "RLEFT", ! 257: "RRIGHT", ! 258: "RESC1", ! 259: "RESC2", ! 260: "RESC3", ! 261: 0, ! 262: }; ! 263: ! 264: if( rw == RNULL ){ ! 265: printf( "RNULL" ); ! 266: return; ! 267: } ! 268: ! 269: if( rw == RNOP ){ ! 270: printf( "RNOP" ); ! 271: return; ! 272: } ! 273: ! 274: flag = 0; ! 275: for( i=0; rwnames[i]; ++i ){ ! 276: if( rw & (1<<i) ){ ! 277: if( flag ) printf( "|" ); ! 278: ++flag; ! 279: printf( rwnames[i] ); ! 280: } ! 281: } ! 282: } ! 283: ! 284: reclaim( p, rw, cookie ) NODE *p; { ! 285: register NODE **qq; ! 286: register NODE *q; ! 287: register i; ! 288: NODE *recres[5]; ! 289: struct respref *r; ! 290: ! 291: /* get back stuff */ ! 292: ! 293: if( rdebug ){ ! 294: printf( "reclaim( %o, ", p ); ! 295: rwprint( rw ); ! 296: printf( ", " ); ! 297: prcook( cookie ); ! 298: printf( " )\n" ); ! 299: } ! 300: ! 301: if( rw == RNOP || ( p->op==FREE && rw==RNULL ) ) return; /* do nothing */ ! 302: ! 303: walkf( p, recl2 ); ! 304: ! 305: if( callop(p->op) ){ ! 306: /* check that all scratch regs are free */ ! 307: callchk(p); /* ordinarily, this is the same as allchk */ ! 308: } ! 309: ! 310: if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */ ! 311: tfree(p); ! 312: return; ! 313: } ! 314: ! 315: /* handle condition codes specially */ ! 316: ! 317: if( (cookie & FORCC) && (rw&RESCC)) { ! 318: /* result is CC register */ ! 319: tfree(p); ! 320: p->op = CCODES; ! 321: p->lval = 0; ! 322: p->rval = 0; ! 323: return; ! 324: } ! 325: ! 326: /* locate results */ ! 327: ! 328: qq = recres; ! 329: ! 330: if( rw&RLEFT) *qq++ = p->left; ! 331: if( rw&RRIGHT ) *qq++ = p->right; ! 332: if( rw&RESC1 ) *qq++ = &resc[0]; ! 333: if( rw&RESC2 ) *qq++ = &resc[1]; ! 334: if( rw&RESC3 ) *qq++ = &resc[2]; ! 335: ! 336: if( qq == recres ){ ! 337: cerror( "illegal reclaim"); ! 338: } ! 339: ! 340: *qq = NIL; ! 341: ! 342: /* now, select the best result, based on the cookie */ ! 343: ! 344: for( r=respref; r->cform; ++r ){ ! 345: if( cookie & r->cform ){ ! 346: for( qq=recres; (q= *qq) != NIL; ++qq ){ ! 347: if( tshape( q, r->mform ) ) goto gotit; ! 348: } ! 349: } ! 350: } ! 351: ! 352: /* we can't do it; die */ ! 353: cerror( "cannot reclaim"); ! 354: ! 355: gotit: ! 356: ! 357: if( p->op == STARG ) p = p->left; /* STARGs are still STARGS */ ! 358: ! 359: /* q->type = p->type; /* to make multi-register allocations work */ ! 360: q->type = p->type==FLOAT && q->op==REG ? DOUBLE : p->type; ! 361: /* maybe there is a better way! */ ! 362: q = tcopy(q); ! 363: ! 364: tfree(p); ! 365: ! 366: p->op = q->op; ! 367: p->lval = q->lval; ! 368: p->rval = q->rval; ! 369: for( i=0; i<NCHNAM; ++i ) ! 370: p->name[i] = q->name[i]; ! 371: ! 372: q->op = FREE; ! 373: ! 374: /* if the thing is in a register, adjust the type */ ! 375: ! 376: switch( p->op ){ ! 377: ! 378: case REG: ! 379: if( p->type == CHAR || p->type == SHORT ) p->type = INT; ! 380: else if( p->type == UCHAR || p->type == USHORT ) p->type = UNSIGNED; ! 381: else if( p->type == FLOAT ) p->type = DOUBLE; ! 382: if( ! (p->rall & MUSTDO ) ) return; /* unless necessary, ignore it */ ! 383: i = p->rall & ~MUSTDO; ! 384: if( i & NOPREF ) return; ! 385: if( i != p->rval ){ ! 386: if( busy[i] || ( szty(p->type)==2 && busy[i+1] ) ){ ! 387: cerror( "faulty register move" ); ! 388: } ! 389: rbusy( i, p->type ); ! 390: rfree( p->rval, p->type ); ! 391: rmove( i, p->rval, p->type ); ! 392: p->rval = i; ! 393: } ! 394: ! 395: case OREG: ! 396: if( p->op == REG || !R2TEST(p->rval) ) { ! 397: if( busy[p->rval]>1 && istreg(p->rval) ) cerror( "potential register overwrite"); ! 398: } ! 399: else ! 400: if( (R2UPK1(p->rval) != 100 && busy[R2UPK1(p->rval)]>1 && istreg(R2UPK1(p->rval)) ) ! 401: || (busy[R2UPK2(p->rval)]>1 && istreg(R2UPK2(p->rval)) ) ) ! 402: cerror( "potential register overwrite"); ! 403: } ! 404: ! 405: } ! 406: ! 407: ncopy( q, p ) NODE *p, *q; { ! 408: /* copy the contents of p into q, without any feeling for ! 409: the contents */ ! 410: /* this code assume that copying rval and lval does the job; ! 411: in general, it might be necessary to special case the ! 412: operator types */ ! 413: register i; ! 414: ! 415: q->op = p->op; ! 416: q->rall = p->rall; ! 417: q->type = p->type; ! 418: q->lval = p->lval; ! 419: q->rval = p->rval; ! 420: for( i=0; i<NCHNAM; ++i ) q->name[i] = p->name[i]; ! 421: ! 422: } ! 423: ! 424: NODE * ! 425: tcopy( p ) register NODE *p; { ! 426: /* make a fresh copy of p */ ! 427: ! 428: register NODE *q; ! 429: register r; ! 430: ! 431: ncopy( q=talloc(), p ); ! 432: ! 433: r = p->rval; ! 434: if( p->op == REG ) rbusy( r, p->type ); ! 435: else if( p->op == OREG ) { ! 436: if( R2TEST(r) ){ ! 437: if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT ); ! 438: rbusy( R2UPK2(r), INT ); ! 439: } ! 440: else { ! 441: rbusy( r, PTR+INT ); ! 442: } ! 443: } ! 444: ! 445: switch( optype(q->op) ){ ! 446: ! 447: case BITYPE: ! 448: q->right = tcopy(p->right); ! 449: case UTYPE: ! 450: q->left = tcopy(p->left); ! 451: } ! 452: ! 453: return(q); ! 454: } ! 455: ! 456: allchk(){ ! 457: /* check to ensure that all register are free */ ! 458: ! 459: register i; ! 460: ! 461: REGLOOP(i){ ! 462: if( istreg(i) && busy[i] ){ ! 463: cerror( "register allocation error"); ! 464: } ! 465: } ! 466: ! 467: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.