1 #ifndef lint 2 static char *sccsid ="@(#)allo.c 4.5 (Berkeley) 03/19/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 # define TBUSY 01000 36 37 # ifndef ALLO 38 allo( p, q ) NODE *p; struct optab *q; { 39 40 register n, i, j; 41 int either; 42 43 n = q->needs; 44 either = ( EITHER & n ); 45 i = 0; 46 47 while( n & NACOUNT ){ 48 resc[i].in.op = REG; 49 resc[i].tn.rval = freereg( p, n&NAMASK ); 50 resc[i].tn.lval = 0; 51 #ifdef FLEXNAMES 52 resc[i].in.name = ""; 53 #else 54 resc[i].in.name[0] = '\0'; 55 #endif 56 n -= NAREG; 57 ++i; 58 } 59 60 if (either) { /* all or nothing at all */ 61 for( j = 0; j < i; j++ ) 62 if( resc[j].tn.rval < 0 ) { /* nothing */ 63 i = 0; 64 break; 65 } 66 if( i != 0 ) goto ok; /* all */ 67 } 68 69 while( n & NBCOUNT ){ 70 resc[i].in.op = REG; 71 resc[i].tn.rval = freereg( p, n&NBMASK ); 72 resc[i].tn.lval = 0; 73 #ifdef FLEXNAMES 74 resc[i].in.name = ""; 75 #else 76 resc[i].in.name[0] = '\0'; 77 #endif 78 n -= NBREG; 79 ++i; 80 } 81 if (either) { /* all or nothing at all */ 82 for( j = 0; j < i; j++ ) 83 if( resc[j].tn.rval < 0 ) { /* nothing */ 84 i = 0; 85 break; 86 } 87 if( i != 0 ) goto ok; /* all */ 88 } 89 90 if( n & NTMASK ){ 91 resc[i].in.op = OREG; 92 resc[i].tn.rval = TMPREG; 93 if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){ 94 resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT ); 95 } 96 else { 97 resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP ); 98 } 99 #ifdef FLEXNAMES 100 resc[i].in.name = ""; 101 #else 102 resc[i].in.name[0] = '\0'; 103 #endif 104 105 resc[i].tn.lval = BITOOR(resc[i].tn.lval); 106 ++i; 107 } 108 109 /* turn off "temporarily busy" bit */ 110 111 ok: 112 REGLOOP(j){ 113 busy[j] &= ~TBUSY; 114 } 115 116 for( j=0; j<i; ++j ) if( resc[j].tn.rval < 0 ) return(0); 117 return(1); 118 119 } 120 # endif 121 122 extern unsigned int 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 int 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 * Have to check for ==, <=, etc. because the result is type INT 205 * but need a register pair temp if either side is real. 206 */ 207 if( (n&NAMASK) && (szty(p->in.type) == 2 || 208 logop(p->in.op) && (szty(p->in.left->in.type) == 2 || 209 szty(p->in.right->in.type) == 2)) ){ /* only do the pairing for real regs */ 210 #ifndef NOEVENODD 211 if( r&01 ) return(0); 212 #endif 213 if( !istreg(r+1) ) return( 0 ); 214 if( busy[r+1] > 1 ) return( 0 ); 215 if( busy[r] == 0 && busy[r+1] == 0 || 216 busy[r+1] == 0 && shareit( p, r, n ) || 217 busy[r] == 0 && shareit( p, r+1, n ) ){ 218 busy[r] |= TBUSY; 219 busy[r+1] |= TBUSY; 220 return(1); 221 } 222 else return(0); 223 } 224 if( busy[r] == 0 ) { 225 busy[r] |= TBUSY; 226 return(1); 227 } 228 229 /* busy[r] is 1: is there chance for sharing */ 230 return( shareit( p, r, n ) ); 231 232 } 233 # endif 234 235 shareit( p, r, n ) NODE *p; { 236 /* can we make register r available by sharing from p 237 given that the need is n */ 238 if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1); 239 if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1); 240 return(0); 241 } 242 243 ushare( p, f, r ) NODE *p; { 244 /* can we find a register r to share on the left or right 245 (as f=='L' or 'R', respectively) of p */ 246 p = getlr( p, f ); 247 if( p->in.op == UNARY MUL ) p = p->in.left; 248 if( p->in.op == OREG ){ 249 if( R2TEST(p->tn.rval) ){ 250 return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) ); 251 } 252 else return( r == p->tn.rval ); 253 } 254 if( p->in.op == REG ){ 255 return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) ); 256 } 257 return(0); 258 } 259 260 recl2( p ) register NODE *p; { 261 register r = p->tn.rval; 262 #ifndef OLD 263 int op = p->in.op; 264 if (op == REG && r >= REGSZ) 265 op = OREG; 266 if( op == REG ) rfree( r, p->in.type ); 267 else if( op == OREG ) { 268 if( R2TEST( r ) ) { 269 if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT ); 270 rfree( R2UPK2( r ), INT ); 271 } 272 else { 273 rfree( r, PTR+INT ); 274 } 275 } 276 #else 277 if( p->in.op == REG ) rfree( r, p->in.type ); 278 else if( p->in.op == OREG ) { 279 if( R2TEST( r ) ) { 280 if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT ); 281 rfree( R2UPK2( r ), INT ); 282 } 283 else { 284 rfree( r, PTR+INT ); 285 } 286 } 287 #endif 288 } 289 290 int rdebug = 0; 291 292 # ifndef RFREE 293 rfree( r, t ) TWORD t; { 294 /* mark register r free, if it is legal to do so */ 295 /* t is the type */ 296 297 # ifndef BUG3 298 if( rdebug ){ 299 printf( "rfree( %s ), size %d\n", rnames[r], szty(t) ); 300 } 301 # endif 302 303 if( istreg(r) ){ 304 if( --busy[r] < 0 ) cerror( "register overfreed"); 305 if( szty(t) == 2 ){ 306 #ifdef NOEVENODD 307 if( istreg(r) ^ istreg(r+1) ) cerror( "illegal free" ); 308 #else 309 if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" ); 310 #endif 311 if( --busy[r+1] < 0 ) cerror( "register overfreed" ); 312 } 313 } 314 } 315 # endif 316 317 # ifndef RBUSY 318 rbusy(r,t) TWORD t; { 319 /* mark register r busy */ 320 /* t is the type */ 321 322 # ifndef BUG3 323 if( rdebug ){ 324 printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) ); 325 } 326 # endif 327 328 if( istreg(r) ) ++busy[r]; 329 if( szty(t) == 2 ){ 330 if( istreg(r+1) ) ++busy[r+1]; 331 #ifdef NOEVENODD 332 if( istreg(r) ^ istreg(r+1) ) cerror( "illegal register pair freed" ); 333 #else 334 if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" ); 335 #endif 336 } 337 } 338 # endif 339 340 # ifndef BUG3 341 rwprint( rw ){ /* print rewriting rule */ 342 register i, flag; 343 static char * rwnames[] = { 344 345 "RLEFT", 346 "RRIGHT", 347 "RESC1", 348 "RESC2", 349 "RESC3", 350 0, 351 }; 352 353 if( rw == RNULL ){ 354 printf( "RNULL" ); 355 return; 356 } 357 358 if( rw == RNOP ){ 359 printf( "RNOP" ); 360 return; 361 } 362 363 flag = 0; 364 for( i=0; rwnames[i]; ++i ){ 365 if( rw & (1<<i) ){ 366 if( flag ) printf( "|" ); 367 ++flag; 368 printf( rwnames[i] ); 369 } 370 } 371 } 372 # endif 373 374 reclaim( p, rw, cookie ) NODE *p; { 375 register NODE **qq; 376 register NODE *q; 377 register i; 378 NODE *recres[5]; 379 struct respref *r; 380 381 /* get back stuff */ 382 383 # ifndef BUG3 384 if( rdebug ){ 385 printf( "reclaim( %o, ", p ); 386 rwprint( rw ); 387 printf( ", " ); 388 prcook( cookie ); 389 printf( " )\n" ); 390 } 391 # endif 392 393 if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */ 394 395 walkf( p, recl2 ); 396 397 if( callop(p->in.op) ){ 398 /* check that all scratch regs are free */ 399 callchk(p); /* ordinarily, this is the same as allchk() */ 400 } 401 402 if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */ 403 tfree(p); 404 return; 405 } 406 407 /* handle condition codes specially */ 408 409 if( (cookie & FORCC) && (rw&RESCC)) { 410 /* result is CC register */ 411 tfree(p); 412 p->in.op = CCODES; 413 p->tn.lval = 0; 414 p->tn.rval = 0; 415 return; 416 } 417 418 /* locate results */ 419 420 qq = recres; 421 422 if( rw&RLEFT) *qq++ = getlr( p, 'L' );; 423 if( rw&RRIGHT ) *qq++ = getlr( p, 'R' ); 424 if( rw&RESC1 ) *qq++ = &resc[0]; 425 if( rw&RESC2 ) *qq++ = &resc[1]; 426 if( rw&RESC3 ) *qq++ = &resc[2]; 427 428 if( qq == recres ){ 429 cerror( "illegal reclaim"); 430 } 431 432 *qq = NIL; 433 434 /* now, select the best result, based on the cookie */ 435 436 for( r=respref; r->cform; ++r ){ 437 if( cookie & r->cform ){ 438 for( qq=recres; (q= *qq) != NIL; ++qq ){ 439 if( tshape( q, r->mform ) ) goto gotit; 440 } 441 } 442 } 443 444 /* we can't do it; die */ 445 cerror( "cannot reclaim"); 446 447 gotit: 448 449 if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */ 450 451 q->in.type = p->in.type; /* to make multi-register allocations work */ 452 /* maybe there is a better way! */ 453 q = tcopy(q); 454 455 tfree(p); 456 457 p->in.op = q->in.op; 458 p->tn.lval = q->tn.lval; 459 p->tn.rval = q->tn.rval; 460 #ifdef FLEXNAMES 461 p->in.name = q->in.name; 462 #ifdef ONEPASS 463 p->in.stalign = q->in.stalign; 464 #endif 465 #else 466 for( i=0; i<NCHNAM; ++i ) 467 p->in.name[i] = q->in.name[i]; 468 #endif 469 470 q->in.op = FREE; 471 472 /* if the thing is in a register, adjust the type */ 473 474 switch( p->in.op ){ 475 476 case REG: 477 if( !rtyflg ){ 478 /* the C language requires intermediate results to change type */ 479 /* this is inefficient or impossible on some machines */ 480 /* the "T" command in match supresses this type changing */ 481 if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT; 482 else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED; 483 #if !defined(FORT) && !defined(SPRECC) 484 else if( p->in.type == FLOAT ) p->in.type = DOUBLE; 485 #endif 486 } 487 if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */ 488 i = p->in.rall & ~MUSTDO; 489 if( i & NOPREF ) return; 490 if( i != p->tn.rval ){ 491 if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){ 492 cerror( "faulty register move" ); 493 } 494 rbusy( i, p->in.type ); 495 rfree( p->tn.rval, p->in.type ); 496 rmove( i, p->tn.rval, p->in.type ); 497 p->tn.rval = i; 498 } 499 500 case OREG: 501 if( p->in.op == REG || !R2TEST(p->tn.rval) ) { 502 if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror( "potential register overwrite"); 503 } 504 else 505 if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) ) 506 || (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) ) 507 cerror( "potential register overwrite"); 508 } 509 510 } 511 512 ncopy( q, p ) NODE *p, *q; { 513 /* copy the contents of p into q, without any feeling for 514 the contents */ 515 /* this code assume that copying rval and lval does the job; 516 in general, it might be necessary to special case the 517 operator types */ 518 register i; 519 520 q->in.op = p->in.op; 521 q->in.rall = p->in.rall; 522 q->in.type = p->in.type; 523 q->tn.lval = p->tn.lval; 524 q->tn.rval = p->tn.rval; 525 #ifdef FLEXNAMES 526 q->in.name = p->in.name; 527 #ifdef ONEPASS 528 q->in.stalign = p->in.stalign; 529 #endif 530 #else 531 for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i]; 532 #endif 533 534 } 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