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