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