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