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