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