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