1 #ifndef lint 2 static char *sccsid ="@(#)allo.c 4.7 (Berkeley) 08/22/85"; 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 * Have to check for ==, <=, etc. because the result is type INT 203 * but need a register pair temp if either side is real. 204 */ 205 if( (n&NAMASK) && (szty(p->in.type) == 2 || 206 logop(p->in.op) && (szty(p->in.left->in.type) == 2 || 207 szty(p->in.right->in.type) == 2)) ){ /* only do the pairing for real regs */ 208 #ifndef NOEVENODD 209 if( r&01 ) return(0); 210 #endif 211 if( !istreg(r+1) ) return( 0 ); 212 if( busy[r+1] > 1 ) return( 0 ); 213 if( busy[r] == 0 && busy[r+1] == 0 || 214 busy[r+1] == 0 && shareit( p, r, n ) || 215 busy[r] == 0 && shareit( p, r+1, n ) ){ 216 busy[r] |= TBUSY; 217 busy[r+1] |= TBUSY; 218 return(1); 219 } 220 else return(0); 221 } 222 if( busy[r] == 0 ) { 223 busy[r] |= TBUSY; 224 return(1); 225 } 226 227 /* busy[r] is 1: is there chance for sharing */ 228 return( shareit( p, r, n ) ); 229 230 } 231 # endif 232 233 shareit( p, r, n ) NODE *p; { 234 /* can we make register r available by sharing from p 235 given that the need is n */ 236 if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1); 237 if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1); 238 return(0); 239 } 240 241 ushare( p, f, r ) NODE *p; { 242 /* can we find a register r to share on the left or right 243 (as f=='L' or 'R', respectively) of p */ 244 p = getlr( p, f ); 245 if( p->in.op == UNARY MUL ) p = p->in.left; 246 if( p->in.op == OREG ){ 247 if( R2TEST(p->tn.rval) ){ 248 return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) ); 249 } 250 else return( r == p->tn.rval ); 251 } 252 if( p->in.op == REG ){ 253 return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) ); 254 } 255 return(0); 256 } 257 258 recl2( p ) register NODE *p; { 259 register r = p->tn.rval; 260 #ifndef OLD 261 int op = p->in.op; 262 if (op == REG && r >= REGSZ) 263 op = OREG; 264 if( op == REG ) rfree( r, p->in.type ); 265 else if( op == OREG ) { 266 if( R2TEST( r ) ) { 267 if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT ); 268 rfree( R2UPK2( r ), INT ); 269 } 270 else { 271 rfree( r, PTR+INT ); 272 } 273 } 274 #else 275 if( p->in.op == REG ) rfree( r, p->in.type ); 276 else if( p->in.op == OREG ) { 277 if( R2TEST( r ) ) { 278 if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT ); 279 rfree( R2UPK2( r ), INT ); 280 } 281 else { 282 rfree( r, PTR+INT ); 283 } 284 } 285 #endif 286 } 287 288 int rdebug = 0; 289 290 # ifndef RFREE 291 rfree( r, t ) TWORD t; { 292 /* mark register r free, if it is legal to do so */ 293 /* t is the type */ 294 295 # ifndef BUG3 296 if( rdebug ){ 297 printf( "rfree( %s ), size %d\n", rnames[r], szty(t) ); 298 } 299 # endif 300 301 if( istreg(r) ){ 302 if( --busy[r] < 0 ) cerror( "register overfreed"); 303 if( szty(t) == 2 ){ 304 #ifdef NOEVENODD 305 if( istreg(r) ^ istreg(r+1) ) cerror( "illegal free" ); 306 #else 307 if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" ); 308 #endif 309 if( --busy[r+1] < 0 ) cerror( "register overfreed" ); 310 } 311 } 312 } 313 # endif 314 315 # ifndef RBUSY 316 rbusy(r,t) TWORD t; { 317 /* mark register r busy */ 318 /* t is the type */ 319 320 # ifndef BUG3 321 if( rdebug ){ 322 printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) ); 323 } 324 # endif 325 326 if( istreg(r) ) ++busy[r]; 327 if( szty(t) == 2 ){ 328 if( istreg(r+1) ) ++busy[r+1]; 329 #ifdef NOEVENODD 330 if( istreg(r) ^ istreg(r+1) ) cerror( "illegal register pair freed" ); 331 #else 332 if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" ); 333 #endif 334 } 335 } 336 # endif 337 338 # ifndef BUG3 339 rwprint( rw ){ /* print rewriting rule */ 340 register i, flag; 341 static char * rwnames[] = { 342 343 "RLEFT", 344 "RRIGHT", 345 "RESC1", 346 "RESC2", 347 "RESC3", 348 0, 349 }; 350 351 if( rw == RNULL ){ 352 printf( "RNULL" ); 353 return; 354 } 355 356 if( rw == RNOP ){ 357 printf( "RNOP" ); 358 return; 359 } 360 361 flag = 0; 362 for( i=0; rwnames[i]; ++i ){ 363 if( rw & (1<<i) ){ 364 if( flag ) printf( "|" ); 365 ++flag; 366 printf( rwnames[i] ); 367 } 368 } 369 } 370 # endif 371 372 reclaim( p, rw, cookie ) NODE *p; { 373 register NODE **qq; 374 register NODE *q; 375 register i; 376 NODE *recres[5]; 377 struct respref *r; 378 379 /* get back stuff */ 380 381 # ifndef BUG3 382 if( rdebug ){ 383 printf( "reclaim( %o, ", p ); 384 rwprint( rw ); 385 printf( ", " ); 386 prcook( cookie ); 387 printf( " )\n" ); 388 } 389 # endif 390 391 if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */ 392 393 walkf( p, recl2 ); 394 395 if( callop(p->in.op) ){ 396 /* check that all scratch regs are free */ 397 callchk(p); /* ordinarily, this is the same as allchk() */ 398 } 399 400 if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */ 401 tfree(p); 402 return; 403 } 404 405 /* handle condition codes specially */ 406 407 if( (cookie & FORCC) && (rw&RESCC)) { 408 /* result is CC register */ 409 tfree(p); 410 p->in.op = CCODES; 411 p->tn.lval = 0; 412 p->tn.rval = 0; 413 return; 414 } 415 416 /* locate results */ 417 418 qq = recres; 419 420 if( rw&RLEFT) *qq++ = getlr( p, 'L' );; 421 if( rw&RRIGHT ) *qq++ = getlr( p, 'R' ); 422 if( rw&RESC1 ) *qq++ = &resc[0]; 423 if( rw&RESC2 ) *qq++ = &resc[1]; 424 if( rw&RESC3 ) *qq++ = &resc[2]; 425 426 if( qq == recres ){ 427 cerror( "illegal reclaim"); 428 } 429 430 *qq = NIL; 431 432 /* now, select the best result, based on the cookie */ 433 434 for( r=respref; r->cform; ++r ){ 435 if( cookie & r->cform ){ 436 for( qq=recres; (q= *qq) != NIL; ++qq ){ 437 if( tshape( q, r->mform ) ) goto gotit; 438 } 439 } 440 } 441 442 /* we can't do it; die */ 443 cerror( "cannot reclaim"); 444 445 gotit: 446 447 if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */ 448 449 q->in.type = p->in.type; /* to make multi-register allocations work */ 450 /* maybe there is a better way! */ 451 q = tcopy(q); 452 453 tfree(p); 454 455 p->in.op = q->in.op; 456 p->tn.lval = q->tn.lval; 457 p->tn.rval = q->tn.rval; 458 #ifdef FLEXNAMES 459 p->in.name = q->in.name; 460 #ifdef ONEPASS 461 p->in.stalign = q->in.stalign; 462 #endif 463 #else 464 for( i=0; i<NCHNAM; ++i ) 465 p->in.name[i] = q->in.name[i]; 466 #endif 467 468 q->in.op = FREE; 469 470 /* if the thing is in a register, adjust the type */ 471 472 switch( p->in.op ){ 473 474 case REG: 475 if( !rtyflg ){ 476 /* the C language requires intermediate results to change type */ 477 /* this is inefficient or impossible on some machines */ 478 /* the "T" command in match supresses this type changing */ 479 if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT; 480 else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED; 481 #if !defined(FORT) && !defined(SPRECC) 482 else if( p->in.type == FLOAT ) p->in.type = DOUBLE; 483 #endif 484 } 485 if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */ 486 i = p->in.rall & ~MUSTDO; 487 if( i & NOPREF ) return; 488 if( i != p->tn.rval ){ 489 if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){ 490 cerror( "faulty register move" ); 491 } 492 rbusy( i, p->in.type ); 493 rfree( p->tn.rval, p->in.type ); 494 rmove( i, p->tn.rval, p->in.type ); 495 p->tn.rval = i; 496 } 497 498 case OREG: 499 if( p->in.op == REG || !R2TEST(p->tn.rval) ) { 500 if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror( "potential register overwrite"); 501 } 502 else 503 if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) ) 504 || (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) ) 505 cerror( "potential register overwrite"); 506 } 507 508 } 509 510 #ifndef ncopy 511 ncopy( q, p ) NODE *p, *q; { 512 /* copy the contents of p into q, without any feeling for 513 the contents */ 514 /* this code assume that copying rval and lval does the job; 515 in general, it might be necessary to special case the 516 operator types */ 517 register i; 518 519 q->in.op = p->in.op; 520 q->in.rall = p->in.rall; 521 q->in.type = p->in.type; 522 q->tn.lval = p->tn.lval; 523 q->tn.rval = p->tn.rval; 524 #ifdef FLEXNAMES 525 q->in.name = p->in.name; 526 #ifdef ONEPASS 527 q->in.stalign = p->in.stalign; 528 #endif 529 #else 530 for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i]; 531 #endif 532 533 } 534 #endif 535 536 NODE * 537 tcopy( p ) register NODE *p; { 538 /* make a fresh copy of p */ 539 540 register NODE *q; 541 register r; 542 543 ncopy( q=talloc(), p ); 544 545 r = p->tn.rval; 546 if( p->in.op == REG ) rbusy( r, p->in.type ); 547 else if( p->in.op == OREG ) { 548 if( R2TEST(r) ){ 549 if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT ); 550 rbusy( R2UPK2(r), INT ); 551 } 552 else { 553 rbusy( r, PTR+INT ); 554 } 555 } 556 557 switch( optype(q->in.op) ){ 558 559 case BITYPE: 560 q->in.right = tcopy(p->in.right); 561 case UTYPE: 562 q->in.left = tcopy(p->in.left); 563 } 564 565 return(q); 566 } 567 568 allchk(){ 569 /* check to ensure that all register are free */ 570 571 register i; 572 573 REGLOOP(i){ 574 if( istreg(i) && busy[i] ){ 575 cerror( "register allocation error"); 576 } 577 } 578 579 } 580