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