|
|
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 &= ~NEVEN; /* NEVEN is used only by ediv */ ! 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 || (n&NEVEN)) ){ /* do the pairing */ ! 201: if( r&01 ) return(0); ! 202: if( !istreg(r+1) ) return( 0 ); ! 203: if( busy[r+1] > 1 ) return( 0 ); ! 204: if( (busy[r] == 0 || shareit( p, r, n )) && ! 205: (busy[r+1] == 0 || shareit( p, r+1, n )) ){ ! 206: busy[r] |= TBUSY; ! 207: busy[r+1] |= TBUSY; ! 208: return(1); ! 209: } ! 210: else return(0); ! 211: } ! 212: if( busy[r] == 0 ) { ! 213: busy[r] |= TBUSY; ! 214: return(1); ! 215: } ! 216: ! 217: /* busy[r] is 1: is there chance for sharing */ ! 218: return( shareit( p, r, n ) ); ! 219: ! 220: } ! 221: # endif ! 222: ! 223: shareit( p, r, n ) NODE *p; { ! 224: /* can we make register r available by sharing from p ! 225: given that the need is n */ ! 226: if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1); ! 227: if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1); ! 228: return(0); ! 229: } ! 230: ! 231: ushare( p, f, r ) NODE *p; { ! 232: /* can we find a register r to share on the left or right ! 233: (as f=='L' or 'R', respectively) of p */ ! 234: p = getlr( p, f ); ! 235: if( p->in.op == UNARY MUL ) p = p->in.left; ! 236: if( p->in.op == OREG ){ ! 237: if( R2TEST(p->tn.rval) ){ ! 238: return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) ); ! 239: } ! 240: else return( r == p->tn.rval ); ! 241: } ! 242: if( p->in.op == REG ){ ! 243: return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) ); ! 244: } ! 245: return(0); ! 246: } ! 247: ! 248: recl2( p ) register NODE *p; { ! 249: register r = p->tn.rval; ! 250: #ifndef OLD ! 251: int op = p->in.op; ! 252: if (op == REG && r >= REGSZ) ! 253: op = OREG; ! 254: if( op == REG ) rfree( r, p->in.type ); ! 255: else if( op == OREG ) { ! 256: if( R2TEST( r ) ) { ! 257: if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT ); ! 258: rfree( R2UPK2( r ), INT ); ! 259: } ! 260: else { ! 261: rfree( r, PTR+INT ); ! 262: } ! 263: } ! 264: #else ! 265: if( p->in.op == REG ) rfree( r, p->in.type ); ! 266: else if( p->in.op == OREG ) { ! 267: if( R2TEST( r ) ) { ! 268: if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT ); ! 269: rfree( R2UPK2( r ), INT ); ! 270: } ! 271: else { ! 272: rfree( r, PTR+INT ); ! 273: } ! 274: } ! 275: #endif ! 276: } ! 277: ! 278: int rdebug = 0; ! 279: ! 280: # ifndef RFREE ! 281: rfree( r, t ) TWORD t; { ! 282: /* mark register r free, if it is legal to do so */ ! 283: /* t is the type */ ! 284: ! 285: # ifndef BUG3 ! 286: if( rdebug ){ ! 287: printf( "rfree( %s ), size %d\n", rnames[r], szty(t) ); ! 288: } ! 289: # endif ! 290: ! 291: if( istreg(r) ){ ! 292: if( --busy[r] < 0 ) cerror( "register overfreed"); ! 293: if( szty(t) == 2 ){ ! 294: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" ); ! 295: if( --busy[r+1] < 0 ) cerror( "register overfreed" ); ! 296: } ! 297: } ! 298: } ! 299: # endif ! 300: ! 301: # ifndef RBUSY ! 302: rbusy(r,t) TWORD t; { ! 303: /* mark register r busy */ ! 304: /* t is the type */ ! 305: ! 306: # ifndef BUG3 ! 307: if( rdebug ){ ! 308: printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) ); ! 309: } ! 310: # endif ! 311: ! 312: if( istreg(r) ) ++busy[r]; ! 313: if( szty(t) == 2 ){ ! 314: if( istreg(r+1) ) ++busy[r+1]; ! 315: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" ); ! 316: } ! 317: } ! 318: # endif ! 319: ! 320: # ifndef BUG3 ! 321: rwprint( rw ){ /* print rewriting rule */ ! 322: register i, flag; ! 323: static char * rwnames[] = { ! 324: ! 325: "RLEFT", ! 326: "RRIGHT", ! 327: "RESC1", ! 328: "RESC2", ! 329: "RESC3", ! 330: 0, ! 331: }; ! 332: ! 333: if( rw == RNULL ){ ! 334: printf( "RNULL" ); ! 335: return; ! 336: } ! 337: ! 338: if( rw == RNOP ){ ! 339: printf( "RNOP" ); ! 340: return; ! 341: } ! 342: ! 343: flag = 0; ! 344: for( i=0; rwnames[i]; ++i ){ ! 345: if( rw & (1<<i) ){ ! 346: if( flag ) printf( "|" ); ! 347: ++flag; ! 348: printf( rwnames[i] ); ! 349: } ! 350: } ! 351: } ! 352: # endif ! 353: ! 354: reclaim( p, rw, cookie ) NODE *p; { ! 355: register NODE **qq; ! 356: register NODE *q; ! 357: register i; ! 358: NODE *recres[5]; ! 359: struct respref *r; ! 360: ! 361: /* get back stuff */ ! 362: ! 363: # ifndef BUG3 ! 364: if( rdebug ){ ! 365: printf( "reclaim( %o, ", p ); ! 366: rwprint( rw ); ! 367: printf( ", " ); ! 368: prcook( cookie ); ! 369: printf( " )\n" ); ! 370: } ! 371: # endif ! 372: ! 373: if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */ ! 374: ! 375: walkf( p, recl2 ); ! 376: ! 377: if( callop(p->in.op) ){ ! 378: /* check that all scratch regs are free */ ! 379: callchk(p); /* ordinarily, this is the same as allchk() */ ! 380: } ! 381: ! 382: if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */ ! 383: tfree(p); ! 384: return; ! 385: } ! 386: ! 387: /* handle condition codes specially */ ! 388: ! 389: if( (cookie & FORCC) && (rw&RESCC)) { ! 390: /* result is CC register */ ! 391: tfree(p); ! 392: p->in.op = CCODES; ! 393: p->tn.lval = 0; ! 394: p->tn.rval = 0; ! 395: return; ! 396: } ! 397: ! 398: /* locate results */ ! 399: ! 400: qq = recres; ! 401: ! 402: if( rw&RLEFT) *qq++ = getlr( p, 'L' );; ! 403: if( rw&RRIGHT ) *qq++ = getlr( p, 'R' ); ! 404: if( rw&RESC1 ) *qq++ = &resc[0]; ! 405: if( rw&RESC2 ) *qq++ = &resc[1]; ! 406: if( rw&RESC3 ) *qq++ = &resc[2]; ! 407: ! 408: if( qq == recres ){ ! 409: cerror( "illegal reclaim"); ! 410: } ! 411: ! 412: *qq = NIL; ! 413: ! 414: /* now, select the best result, based on the cookie */ ! 415: ! 416: for( r=respref; r->cform; ++r ){ ! 417: if( cookie & r->cform ){ ! 418: for( qq=recres; (q= *qq) != NIL; ++qq ){ ! 419: if( tshape( q, r->mform ) ) goto gotit; ! 420: } ! 421: } ! 422: } ! 423: ! 424: /* we can't do it; die */ ! 425: cerror( "cannot reclaim"); ! 426: ! 427: gotit: ! 428: ! 429: if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */ ! 430: ! 431: q->in.type = p->in.type; /* to make multi-register allocations work */ ! 432: /* maybe there is a better way! */ ! 433: q = tcopy(q); ! 434: ! 435: tfree(p); ! 436: ! 437: p->in.op = q->in.op; ! 438: p->tn.lval = q->tn.lval; ! 439: p->tn.rval = q->tn.rval; ! 440: #ifdef FLEXNAMES ! 441: p->in.name = q->in.name; ! 442: #ifdef ONEPASS ! 443: p->in.stalign = q->in.stalign; ! 444: #endif ! 445: #else ! 446: for( i=0; i<NCHNAM; ++i ) ! 447: p->in.name[i] = q->in.name[i]; ! 448: #endif ! 449: ! 450: q->in.op = FREE; ! 451: ! 452: /* if the thing is in a register, adjust the type */ ! 453: ! 454: switch( p->in.op ){ ! 455: ! 456: case REG: ! 457: if( !rtyflg ){ ! 458: /* the C language requires intermediate results to change type */ ! 459: /* this is inefficient or impossible on some machines */ ! 460: /* the "T" command in match supresses this type changing */ ! 461: if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT; ! 462: else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED; ! 463: else if( p->in.type == FLOAT ) p->in.type = DOUBLE; ! 464: } ! 465: if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */ ! 466: i = p->in.rall & ~MUSTDO; ! 467: if( i & NOPREF ) return; ! 468: if( i != p->tn.rval ){ ! 469: if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){ ! 470: cerror( "faulty register move" ); ! 471: } ! 472: rbusy( i, p->in.type ); ! 473: rfree( p->tn.rval, p->in.type ); ! 474: rmove( i, p->tn.rval, p->in.type ); ! 475: p->tn.rval = i; ! 476: } ! 477: ! 478: case OREG: ! 479: if( p->in.op == REG || !R2TEST(p->tn.rval) ) { ! 480: if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror( "potential register overwrite"); ! 481: } ! 482: else ! 483: if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) ) ! 484: || (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) ) ! 485: cerror( "potential register overwrite"); ! 486: } ! 487: ! 488: } ! 489: ! 490: ncopy( q, p ) NODE *p, *q; { ! 491: /* copy the contents of p into q, without any feeling for ! 492: the contents */ ! 493: /* this code assume that copying rval and lval does the job; ! 494: in general, it might be necessary to special case the ! 495: operator types */ ! 496: register i; ! 497: ! 498: q->in.op = p->in.op; ! 499: q->in.rall = p->in.rall; ! 500: q->in.type = p->in.type; ! 501: q->tn.lval = p->tn.lval; ! 502: q->tn.rval = p->tn.rval; ! 503: #ifdef FLEXNAMES ! 504: q->in.name = p->in.name; ! 505: #ifdef ONEPASS ! 506: q->in.stalign = p->in.stalign; ! 507: #endif ! 508: #else ! 509: for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i]; ! 510: #endif ! 511: ! 512: } ! 513: ! 514: NODE * ! 515: tcopy( p ) register NODE *p; { ! 516: /* make a fresh copy of p */ ! 517: ! 518: register NODE *q; ! 519: register r; ! 520: ! 521: ncopy( q=talloc(), p ); ! 522: ! 523: r = p->tn.rval; ! 524: if( p->in.op == REG ) rbusy( r, p->in.type ); ! 525: else if( p->in.op == OREG ) { ! 526: if( R2TEST(r) ){ ! 527: if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT ); ! 528: rbusy( R2UPK2(r), INT ); ! 529: } ! 530: else { ! 531: rbusy( r, PTR+INT ); ! 532: } ! 533: } ! 534: ! 535: switch( optype(q->in.op) ){ ! 536: ! 537: case BITYPE: ! 538: q->in.right = tcopy(p->in.right); ! 539: case UTYPE: ! 540: q->in.left = tcopy(p->in.left); ! 541: } ! 542: ! 543: return(q); ! 544: } ! 545: ! 546: allchk(){ ! 547: /* check to ensure that all register are free */ ! 548: ! 549: register i; ! 550: ! 551: REGLOOP(i){ ! 552: if( istreg(i) && busy[i] ){ ! 553: cerror( "register allocation error"); ! 554: } ! 555: } ! 556: ! 557: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.