1: #if !defined(lint) && defined(DOSCCS) 2: static char *sccsid ="@(#)allo.c 4.8.1 (2.11BSD GTE) 1/17/95"; 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: OFFSZ freetemp(); 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 OFFSZ offsz; 121: 122: OFFSZ 123: freetemp( k ){ /* allocate k integers worth of temp space */ 124: /* we also make the convention that, if the number of words is more than 1, 125: /* it must be aligned for storing doubles... */ 126: 127: # ifndef BACKTEMP 128: OFFSZ t; 129: 130: if( k>1 ){ 131: SETOFF( tmpoff, ALDOUBLE ); 132: } 133: 134: t = tmpoff; 135: tmpoff += k*SZINT; 136: if( tmpoff > maxoff ) maxoff = tmpoff; 137: if( tmpoff >= offsz ) 138: cerror("stack overflow" ); 139: if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff; 140: return(t); 141: 142: # else 143: tmpoff += k*SZINT; 144: if( k>1 ) { 145: SETOFF( tmpoff, ALDOUBLE ); 146: } 147: if( tmpoff > maxoff ) maxoff = tmpoff; 148: if( tmpoff >= offsz ) 149: cerror("stack overflow" ); 150: if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff; 151: return( -tmpoff ); 152: # endif 153: } 154: 155: freereg( p, n ) NODE *p; { 156: /* allocate a register of type n */ 157: /* p gives the type, if floating */ 158: 159: register j; 160: 161: /* not general; means that only one register (the result) OK for call */ 162: if( callop(p->in.op) ){ 163: j = callreg(p); 164: if( usable( p, n, j ) ) return( j ); 165: /* have allocated callreg first */ 166: } 167: j = p->in.rall & ~MUSTDO; 168: if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */ 169: return( j ); 170: } 171: if( n&NAMASK ){ 172: for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){ 173: if( usable(p,n,j) ){ 174: return( j ); 175: } 176: } 177: } 178: else if( n &NBMASK ){ 179: for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){ 180: if( usable(p,n,j) ){ 181: return(j); 182: } 183: } 184: } 185: 186: return( -1 ); 187: } 188: 189: # ifndef USABLE 190: usable( p, n, r ) NODE *p; { 191: /* decide if register r is usable in tree p to satisfy need n */ 192: 193: /* checks, for the moment */ 194: if( !istreg(r) ) cerror("usable asked about nontemp register" ); 195: 196: if( busy[r] > 1 ) return(0); 197: if( isbreg(r) ){ 198: if( n&NAMASK ) return(0); 199: } 200: else { 201: if( n & NBMASK ) return(0); 202: } 203: /* 204: * Some special cases that require register pairs... 205: * Have to check for ==, <=, etc. because the result is type int 206: * but need a register pair temp if either side is wide. 207: * For +=, *= etc. where lhs is narrow and rhs is wide, the temp 208: * register must be wide. 209: */ 210: if( (n&NAMASK) && 211: (szty(p->in.type) == 2 || 212: (logop(p->in.op) && (szty(p->in.left->in.type) == 2 || 213: szty(p->in.right->in.type) == 2)) || 214: (asgop(p->in.op) && szty(p->in.right->in.type) == 2 && 215: szty(p->in.left->in.type) == 1)) 216: ){ 217: #ifndef NOEVENODD 218: if( r&01 ) return(0); 219: #endif 220: if( !istreg(r+1) ) return( 0 ); 221: if( busy[r+1] > 1 ) return( 0 ); 222: if( busy[r] == 0 && busy[r+1] == 0 || 223: busy[r+1] == 0 && 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( szty(t) == 2 ){ 313: #ifdef NOEVENODD 314: if( istreg(r) ^ istreg(r+1) ) cerror("illegal free" ); 315: #else 316: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror("illegal free" ); 317: #endif 318: if( --busy[r+1] < 0 ) cerror("register overfreed" ); 319: } 320: } 321: } 322: # endif 323: 324: # ifndef RBUSY 325: rbusy(r,t) TWORD t; { 326: /* mark register r busy */ 327: /* t is the type */ 328: 329: # ifndef BUG3 330: if( rdebug ){ 331: printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) ); 332: } 333: # endif 334: 335: if( istreg(r) ) ++busy[r]; 336: if( szty(t) == 2 ){ 337: if( istreg(r+1) ) ++busy[r+1]; 338: #ifdef NOEVENODD 339: if( istreg(r) ^ istreg(r+1) ) cerror("illegal register pair freed" ); 340: #else 341: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror("illegal register pair freed" ); 342: #endif 343: } 344: } 345: # endif 346: 347: # ifndef BUG3 348: rwprint( rw ){ /* print rewriting rule */ 349: register i, flag; 350: static char * rwnames[] = { 351: 352: "RLEFT", 353: "RRIGHT", 354: "RESC1", 355: "RESC2", 356: "RESC3", 357: 0, 358: }; 359: 360: if( rw == RNULL ){ 361: printf( "RNULL" ); 362: return; 363: } 364: 365: if( rw == RNOP ){ 366: printf( "RNOP" ); 367: return; 368: } 369: 370: flag = 0; 371: for( i=0; rwnames[i]; ++i ){ 372: if( rw & (1<<i) ){ 373: if( flag ) printf( "|" ); 374: ++flag; 375: printf( rwnames[i] ); 376: } 377: } 378: } 379: # endif 380: 381: reclaim( p, rw, cookie ) NODE *p; { 382: register NODE **qq; 383: register NODE *q; 384: register i; 385: NODE *recres[5]; 386: struct respref *r; 387: 388: /* get back stuff */ 389: 390: # ifndef BUG3 391: if( rdebug ){ 392: printf( "reclaim( %o, ", p ); 393: rwprint( rw ); 394: printf( ", " ); 395: prcook( cookie ); 396: printf( " )\n" ); 397: } 398: # endif 399: 400: if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */ 401: 402: walkf( p, recl2 ); 403: 404: if( callop(p->in.op) ){ 405: /* check that all scratch regs are free */ 406: callchk(p); /* ordinarily, this is the same as allchk() */ 407: } 408: 409: if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */ 410: tfree(p); 411: return; 412: } 413: 414: /* handle condition codes specially */ 415: 416: if( (cookie & FORCC) && (rw&RESCC)) { 417: /* result is CC register */ 418: tfree(p); 419: p->in.op = CCODES; 420: p->tn.lval = 0; 421: p->tn.rval = 0; 422: return; 423: } 424: 425: /* locate results */ 426: 427: qq = recres; 428: 429: if( rw&RLEFT) *qq++ = getlr( p, 'L' ); 430: if( rw&RRIGHT ) *qq++ = getlr( p, 'R' ); 431: if( rw&RESC1 ) *qq++ = &resc[0]; 432: if( rw&RESC2 ) *qq++ = &resc[1]; 433: if( rw&RESC3 ) *qq++ = &resc[2]; 434: 435: if( qq == recres ){ 436: cerror("illegal reclaim"); 437: } 438: 439: *qq = NIL; 440: 441: /* now, select the best result, based on the cookie */ 442: 443: for( r=respref; r->cform; ++r ){ 444: if( cookie & r->cform ){ 445: for( qq=recres; (q= *qq) != NIL; ++qq ){ 446: if( tshape( q, r->mform ) ) goto gotit; 447: } 448: } 449: } 450: 451: /* we can't do it; die */ 452: cerror("cannot reclaim"); 453: 454: gotit: 455: 456: if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */ 457: 458: q->in.type = p->in.type; /* to make multi-register allocations work */ 459: /* maybe there is a better way! */ 460: q = tcopy(q); 461: 462: tfree(p); 463: 464: p->in.op = q->in.op; 465: p->tn.lval = q->tn.lval; 466: p->tn.rval = q->tn.rval; 467: #ifdef FLEXNAMES 468: p->in.name = q->in.name; 469: #ifdef ONEPASS 470: p->in.stalign = q->in.stalign; 471: #endif 472: #else 473: for( i=0; i<NCHNAM; ++i ) 474: p->in.name[i] = q->in.name[i]; 475: #endif 476: 477: q->in.op = FREE; 478: 479: /* if the thing is in a register, adjust the type */ 480: 481: switch( p->in.op ){ 482: 483: case REG: 484: if( !rtyflg ){ 485: /* the C language requires intermediate results to change type */ 486: /* this is inefficient or impossible on some machines */ 487: /* the "T" command in match supresses this type changing */ 488: if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT; 489: else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED; 490: #if !defined(FORT) && !defined(SPRECC) 491: else if( p->in.type == FLOAT ) p->in.type = DOUBLE; 492: #endif 493: } 494: if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */ 495: i = p->in.rall & ~MUSTDO; 496: if( i & NOPREF ) return; 497: if( i != p->tn.rval ){ 498: if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){ 499: cerror("faulty register move" ); 500: } 501: rbusy( i, p->in.type ); 502: rfree( p->tn.rval, p->in.type ); 503: rmove( i, p->tn.rval, p->in.type ); 504: p->tn.rval = i; 505: } 506: 507: case OREG: 508: if( p->in.op == REG || !R2TEST(p->tn.rval) ) { 509: if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror("potential register overwrite"); 510: } 511: else 512: if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) ) 513: || (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) ) 514: cerror("potential register overwrite"); 515: } 516: 517: } 518: 519: #ifndef ncopy 520: ncopy( q, p ) NODE *p, *q; { 521: /* copy the contents of p into q, without any feeling for 522: the contents */ 523: /* this code assume that copying rval and lval does the job; 524: in general, it might be necessary to special case the 525: operator types */ 526: register i; 527: 528: q->in.op = p->in.op; 529: q->in.rall = p->in.rall; 530: q->in.type = p->in.type; 531: q->tn.lval = p->tn.lval; 532: q->tn.rval = p->tn.rval; 533: #ifdef FLEXNAMES 534: q->in.name = p->in.name; 535: #ifdef ONEPASS 536: q->in.stalign = p->in.stalign; 537: #endif 538: #else 539: for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i]; 540: #endif 541: 542: } 543: #endif 544: 545: NODE * 546: tcopy( p ) register NODE *p; { 547: /* make a fresh copy of p */ 548: 549: register NODE *q; 550: register r; 551: 552: ncopy( q=talloc(), p ); 553: 554: r = p->tn.rval; 555: if( p->in.op == REG ) rbusy( r, p->in.type ); 556: else if( p->in.op == OREG ) { 557: if( R2TEST(r) ){ 558: if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT ); 559: rbusy( R2UPK2(r), INT ); 560: } 561: else { 562: rbusy( r, PTR+INT ); 563: } 564: } 565: 566: switch( optype(q->in.op) ){ 567: 568: case BITYPE: 569: q->in.right = tcopy(p->in.right); 570: case UTYPE: 571: q->in.left = tcopy(p->in.left); 572: } 573: 574: return(q); 575: } 576: 577: allchk(){ 578: /* check to ensure that all register are free */ 579: 580: register i; 581: 582: REGLOOP(i){ 583: if( istreg(i) && busy[i] ){ 584: cerror("register allocation error"); 585: } 586: } 587: 588: }