|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)allo.c 1.1 86/02/03 SMI";
3: #endif
4: # include "cpass2.h"
5:
6: NODE resc[3];
7:
8: int busy[REGSZ];
9:
10: int maxa, mina, maxb, minb, maxc, minc;
11:
12: # ifndef ALLO0
13: allo0()
14: { /* 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: if( rstatus[i] & STCREG ){
32: if( maxc<0 ) minc = i;
33: maxc = i;
34: }
35: }
36: }
37: # endif
38:
39: # define TBUSY 01000
40:
41: # ifndef ALLO
42: allo( p, q )
43: NODE *p; struct optab *q;
44: {
45:
46: register n, i, j;
47: #ifdef VAX
48: int either;
49: #endif
50:
51: n = q->needs;
52: #ifdef VAX
53: either = ( EITHER & n );
54: #endif
55: i = 0;
56:
57: while( n & NACOUNT ){
58: resc[i].in.op = REG;
59: resc[i].tn.rval = freereg( p, n&NAMASK );
60: resc[i].tn.lval = 0;
61: resc[i].in.name = "";
62: n -= NAREG;
63: ++i;
64: }
65:
66: #ifdef VAX
67: if (either) { /* all or nothing at all */
68: for( j = 0; j < i; j++ )
69: if( resc[j].tn.rval < 0 ) { /* nothing */
70: i = 0;
71: break;
72: }
73: if( i != 0 ) goto ok; /* all */
74: }
75: #endif
76:
77: while( n & NBCOUNT ){
78: resc[i].in.op = REG;
79: resc[i].tn.rval = freereg( p, n&NBMASK );
80: resc[i].tn.lval = 0;
81: resc[i].in.name = "";
82: n -= NBREG;
83: ++i;
84: }
85: #ifdef VAX
86: if (either) { /* all or nothing at all */
87: for( j = 0; j < i; j++ )
88: if( resc[j].tn.rval < 0 ) { /* nothing */
89: i = 0;
90: break;
91: }
92: if( i != 0 ) goto ok; /* all */
93: }
94: #endif
95:
96: while( n & NCCOUNT ){
97: resc[i].in.op = REG;
98: resc[i].tn.rval = freereg( p, n&NCMASK );
99: resc[i].tn.lval = 0;
100: resc[i].in.name = "";
101: n -= NCREG;
102: ++i;
103: }
104: #ifdef VAX
105: if (either) { /* all or nothing at all */
106: for( j = 0; j < i; j++ )
107: if( resc[j].tn.rval < 0 ) { /* nothing */
108: i = 0;
109: break;
110: }
111: if( i != 0 ) goto ok; /* all */
112: }
113: #endif
114:
115: if( n & NTMASK ){
116: resc[i].in.op = OREG;
117: resc[i].tn.rval = TMPREG;
118: if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){
119: resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT );
120: } else {
121: resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP );
122: }
123: resc[i].in.name = "";
124:
125: resc[i].tn.lval = BITOOR(resc[i].tn.lval);
126: ++i;
127: }
128:
129: /* turn off "temporarily busy" bit */
130:
131: ok:
132: REGLOOP(j){
133: busy[j] &= ~TBUSY;
134: }
135:
136: for( j=0; j<i; ++j )
137: if( resc[j].tn.rval < 0 ) return(0);
138:
139: return(1);
140: }
141: # endif
142:
143: extern unsigned int offsz;
144:
145: # ifndef FREETEMP
146: freetemp( k )
147: {
148: /* allocate k integers worth of temp space */
149: /* we also make the convention that, if the number of words is more than 1,
150: /* it must be aligned for storing doubles... */
151:
152: # ifndef BACKTEMP
153: int t;
154:
155: if( k>1 ){
156: SETOFF( tmpoff, ALDOUBLE );
157: }
158:
159: t = tmpoff;
160: tmpoff += k*SZINT;
161: if( tmpoff > maxoff ) maxoff = tmpoff;
162: if( tmpoff >= offsz )
163: cerror( "stack overflow" );
164: if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
165: return(t);
166:
167: # else
168: tmpoff += k*SZINT;
169: if( k>1 ) {
170: SETOFF( tmpoff, ALDOUBLE );
171: }
172: if( tmpoff > maxoff ) maxoff = tmpoff;
173: #ifndef VAX
174: if (tmpoff >= TMPMAX)
175: uerror( "stack overflow: too many local variables");
176: #endif
177: if( tmpoff >= offsz )
178: cerror( "stack overflow" );
179: if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
180: return( -tmpoff );
181: # endif
182: }
183: #endif
184:
185: freereg( p, n )
186: NODE *p;
187: {
188: /* allocate a register of type n */
189: /* p gives the type, if floating */
190:
191: register j;
192:
193: /* not general; means that only one register (the result) OK for call */
194: if( callop(p->in.op) ){
195: j = callreg(p);
196: if( usable( p, n, j ) ) return( j );
197: /* have allocated callreg first */
198: }
199: j = p->in.rall & ~MUSTDO;
200: if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */
201: return( j );
202: }
203: if( n&NAMASK ){
204: for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){
205: if( usable(p,n,j) ){
206: return( j );
207: }
208: }
209: }
210: else if( n &NBMASK ){
211: for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){
212: if( usable(p,n,j) ){
213: return(j);
214: }
215: }
216: }
217: else if( n &NCMASK ){
218: for( j=minc; j<=maxc; ++j ) if( rstatus[j]&STCREG ){
219: if( usable(p,n,j) ){
220: return(j);
221: }
222: }
223: }
224:
225: return( -1 );
226: }
227:
228: # ifndef USABLE
229: usable( p, n, r )
230: NODE *p;
231: {
232: /* decide if register r is usable in tree p to satisfy need n */
233:
234: /* checks, for the moment */
235: if ( !istreg(r) ) cerror( "usable asked about nontemp register" );
236:
237: if ( busy[r] > 1 ) return(0);
238: if ( isbreg(r) ){
239: if ( n&(NAMASK|NCMASK) ) return(0);
240: } else if ( iscreg(r) ){
241: if ( n&(NAMASK|NBMASK) ) return(0);
242: } else {
243: if ( n & (NBMASK|NCMASK) ) return(0);
244: }
245: if ((n&NAMASK) && needpair(r, p->in.type) ){ /* only do the pairing for real regs */
246: if ( r&01 ) return(0);
247: if ( !istreg(r+1) ) return( 0 );
248: if ( busy[r+1] > 1 ) return( 0 );
249: if ( ( busy[r] == 0 || shareit( p, r, n ) )
250: && ( busy[r+1] == 0 || shareit( p, r+1, n ) ) ){
251: busy[r] |= TBUSY;
252: busy[r+1] |= TBUSY;
253: return(1);
254: } else
255: return(0);
256: }
257: if ( busy[r] == 0 ) {
258: busy[r] |= TBUSY;
259: return(1);
260: }
261:
262: /* busy[r] is 1: is there chance for sharing */
263: return( shareit( p, r, n ) );
264:
265: }
266: # endif
267:
268: shareit( p, r, n )
269: NODE *p;
270: {
271: /* can we make register r available by sharing from p
272: given that the need is n */
273: if( (n&(NASL|NBSL|NCSL)) && ushare( getlr(p,'L'), r ) ) return(1);
274: if( (n&(NASR|NBSR|NCSR)) && ushare( getlr(p,'R'), r ) ) return(1);
275: return(0);
276: }
277:
278: ushare( p, r )
279: NODE *p;
280: {
281: /* can we find a register r to share in subtree p? */
282: switch(optype(p->in.op)) {
283: case LTYPE:
284: break;
285: case UTYPE:
286: return ushare(p->in.left, r);
287: case BITYPE:
288: return ushare(p->in.left, r) || ushare(p->in.right, r);
289: }
290: if( p->in.op == OREG ){
291: if(R2TEST(p->tn.rval))
292: return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) );
293: return( r == p->tn.rval );
294: }
295: if( p->in.op == REG ){
296: return( r == p->tn.rval ||
297: ( needpair(r, p->in.type) && r==p->tn.rval+1 ) );
298: }
299: return(0);
300: }
301:
302: #ifdef VAX
303: recl2( p )
304: register NODE *p;
305: {
306: register r = p->tn.rval;
307: #ifndef OLD
308: int op = p->in.op;
309: switch(optype(op))
310: case LTYPE:
311: break;
312: case UTYPE:
313: recl2(p->in.left);
314: return;
315: case BITYPE:
316: recl2(p->in.left);
317: recl2(p->in.right);
318: return;
319: }
320: if (op == REG && r >= REGSZ)
321: op = OREG;
322: if( op == REG ) rfree( r, p->in.type );
323: else if( op == OREG ) {
324: if( R2TEST( r ) ) {
325: if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
326: rfree( R2UPK2( r ), INT );
327: } else {
328: rfree( r, PTR+INT );
329: }
330: }
331: #else
332: switch(optype(p->in.op))
333: case LTYPE:
334: break;
335: case UTYPE:
336: recl2(p->in.left);
337: return;
338: case BITYPE:
339: recl2(p->in.left);
340: recl2(p->in.right);
341: return;
342: }
343: if( p->in.op == REG ) rfree( r, p->in.type );
344: else if( p->in.op == OREG ) {
345: if( R2TEST( r ) ) {
346: if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
347: rfree( R2UPK2( r ), INT );
348: } else {
349: rfree( r, PTR+INT );
350: }
351: }
352: #endif
353: }
354: #else
355: recl2( p )
356: register NODE *p;
357: {
358: register r = p->tn.rval;
359: switch(optype(p->in.op)) {
360: case LTYPE:
361: break;
362: case UTYPE:
363: recl2(p->in.left);
364: return;
365: case BITYPE:
366: recl2(p->in.left);
367: recl2(p->in.right);
368: return;
369: }
370: if( p->in.op == REG ) rfree( r, p->in.type );
371: else if( p->in.op == OREG ) {
372: if( R2TEST( r ) ) {
373: rfree( R2UPK1( r ), PTR+INT );
374: rfree( R2UPK2( r ), INT );
375: } else {
376: rfree( r, PTR+INT );
377: }
378: }
379: }
380: #endif
381:
382:
383: int rdebug = 0;
384:
385: # ifndef RFREE
386: rfree( r, t ) TWORD t; {
387: /* mark register r free, if it is legal to do so */
388: /* t is the type */
389:
390: # ifndef BUG3
391: if( rdebug ){
392: printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
393: }
394: # endif
395:
396: if( istreg(r) ){
397: if( --busy[r] < 0 ) cerror( "register overfreed");
398: if( needpair(r,t) ){
399: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
400: if( --busy[r+1] < 0 ) cerror( "register overfreed" );
401: }
402: }
403: }
404: # endif
405:
406: # ifndef RBUSY
407: rbusy(r,t)
408: TWORD t;
409: {
410: /* mark register r busy */
411: /* t is the type */
412:
413: # ifndef BUG3
414: if( rdebug ){
415: printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
416: }
417: # endif
418:
419: if( istreg(r) ) ++busy[r];
420: if( needpair(r,t) ){
421: if( istreg(r+1) ) ++busy[r+1];
422: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
423: }
424: }
425: # endif
426:
427: # ifndef BUG3
428: rwprint( rw ){ /* print rewriting rule */
429: register i, flag;
430: static char * rwnames[] = {
431:
432: "RLEFT",
433: "RRIGHT",
434: "RESC1",
435: "RESC2",
436: "RESC3",
437: 0,
438: };
439:
440: if( rw == RNULL ){
441: print_str( "RNULL" );
442: return;
443: }
444:
445: if( rw == RNOP ){
446: print_str( "RNOP" );
447: return;
448: }
449:
450: flag = 0;
451: for( i=0; rwnames[i]; ++i ){
452: if( rw & (1<<i) ){
453: if( flag ) putchar('|');
454: ++flag;
455: print_str( rwnames[i] );
456: }
457: }
458: }
459: # endif
460:
461: reclaim( p, rw, cookie )
462: NODE *p;
463: {
464: register NODE **qq;
465: register NODE *q;
466: register i;
467: NODE *recres[5];
468: struct respref *r;
469:
470: /* get back stuff */
471:
472: # ifndef BUG3
473: if( rdebug ){
474: printf( "reclaim( %o, ", p );
475: rwprint( rw );
476: print_str( ", " );
477: prcook( cookie );
478: print_str( " )\n" );
479: }
480: # endif
481:
482: if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */
483:
484: recl2(p);
485:
486: if( callop(p->in.op) ){
487: /* check that all scratch regs are free */
488: callchk(p); /* ordinarily, this is the same as allchk() */
489: }
490:
491: if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
492: tfree(p);
493: return;
494: }
495:
496: /* handle condition codes specially */
497:
498: if( (cookie & FORCC) && (rw&(RESFCC|RESCC)) ) {
499: /*
500: * result is CC register. Machines with
501: * coprocessors may have more than one (bletch)
502: */
503: tfree(p);
504: p->in.op = (rw&RESFCC ? FCCODES : CCODES);
505: p->tn.lval = 0;
506: p->tn.rval = 0;
507: return;
508: }
509:
510: /* locate results */
511:
512: qq = recres;
513:
514: if( rw&RLEFT) *qq++ = getlr( p, 'L' );;
515: if( rw&RRIGHT ) *qq++ = getlr( p, 'R' );
516: if( rw&RESC1 ) *qq++ = &resc[0];
517: if( rw&RESC2 ) *qq++ = &resc[1];
518: if( rw&RESC3 ) *qq++ = &resc[2];
519:
520: if( qq == recres ){
521: cerror( "illegal reclaim");
522: }
523:
524: *qq = NIL;
525:
526: /* now, select the best result, based on the cookie */
527:
528: for( r=respref; r->cform; ++r ){
529: if( cookie & r->cform ){
530: for( qq=recres; (q= *qq) != NIL; ++qq ){
531: if( tshape( q, r->mform ) ) goto gotit;
532: }
533: }
534: }
535:
536: /* we can't do it; die */
537: cerror( "cannot reclaim");
538:
539: gotit:
540:
541: if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */
542:
543: q->in.type = p->in.type; /* to make multi-register allocations work */
544: q->in.rall = p->in.rall;
545: /* maybe there is a better way! */
546: q = tcopy(q);
547: tfree(p);
548: ncopy(p,q);
549: q->in.op = FREE;
550:
551: /* if the thing is in a register, adjust the type */
552:
553: switch( p->in.op ){
554:
555: case REG:
556: #ifdef VAX
557: if( !rtyflg ){
558: /* the C language requires intermediate results to change type */
559: /* this is inefficient or impossible on some machines */
560: /* the "T" command in match supresses this type changing */
561: if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT;
562: else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED;
563: else if( p->in.type == FLOAT ) p->in.type = DOUBLE;
564: }
565: #endif
566: if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */
567: i = p->in.rall & ~MUSTDO;
568: if( i & NOPREF ) return;
569: if( i != p->tn.rval ){
570: if( busy[i] || (needpair(i,p->in.type) && busy[i+1]) ){
571: cerror( "faulty register move" );
572: }
573: rbusy( i, p->in.type );
574: rfree( p->tn.rval, p->in.type );
575: rmove( i, p->tn.rval, p->in.type );
576: p->tn.rval = i;
577: }
578:
579: case OREG:
580: #ifdef VAX
581: if( p->in.op == REG || !R2TEST(p->tn.rval) ) {
582: if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror( "potential register overwrite");
583: } else
584: if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) )
585: || (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) )
586: cerror( "potential register overwrite");
587: #else
588: if( R2TEST(p->tn.rval) ){
589: int r1, r2;
590: r1 = R2UPK1(p->tn.rval);
591: r2 = R2UPK2(p->tn.rval);
592: if( (busy[r1]>1 && istreg(r1)) || (busy[r2]>1 && istreg(r2)) ){
593: cerror( "potential register overwrite" );
594: }
595: }
596: else if( (busy[p->tn.rval]>1) && istreg(p->tn.rval) ) cerror( "potential register overwrite");
597: #endif
598: }
599:
600: }
601:
602: NODE *
603: tcopy( p )
604: register NODE *p;
605: {
606: /* make a fresh copy of p */
607:
608: register NODE *q;
609: register r;
610:
611: ncopy(q=talloc(), p);
612: r = p->tn.rval;
613: if( p->in.op == REG ) rbusy( r, p->in.type );
614: else if( p->in.op == OREG ) {
615: if( R2TEST(r) ){
616: if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT );
617: rbusy( R2UPK2(r), INT );
618: } else {
619: rbusy( r, PTR+INT );
620: }
621: }
622:
623: switch( optype(q->in.op) ){
624:
625: case BITYPE:
626: q->in.right = tcopy(p->in.right);
627: case UTYPE:
628: q->in.left = tcopy(p->in.left);
629: }
630:
631: return(q);
632: }
633:
634: allchk(){
635: /* check to ensure that all register are free */
636:
637: register i;
638:
639: REGLOOP(i){
640: if( istreg(i) && busy[i] ){
641: cerror( "register allocation error");
642: }
643: }
644:
645: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.