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:     }

Defined functions

allchk defined in line 577; used 4 times
allo defined in line 36; used 1 times
allo0 defined in line 14; used 1 times
freereg defined in line 155; used 2 times
freetemp defined in line 122; used 3 times
ncopy defined in line 520; used 5 times
rbusy defined in line 325; used 9 times
recl2 defined in line 267; used 1 times
reclaim defined in line 381; used 10 times
rfree defined in line 300; used 9 times
rwprint defined in line 348; used 1 times
shareit defined in line 242; used 3 times
tcopy defined in line 545; used 7 times
usable defined in line 190; used 4 times
ushare defined in line 250; used 2 times

Defined variables

busy defined in line 9; used 22 times
maxa defined in line 11; used 4 times
maxb defined in line 11; used 4 times
mina defined in line 11; used 3 times
minb defined in line 11; used 3 times
rdebug defined in line 297; used 4 times
resc defined in line 7; used 24 times
sccsid defined in line 2; never used
Last modified: 1995-01-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4124
Valid CSS Valid XHTML 1.0 Strict