1 #ifndef lint 2 static char *sccsid ="@(#)allo.c 4.10 (Berkeley) 12/09/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 } 594