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