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