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