|
|
1.1 root 1: #ifndef lint
2: static char *sccsid ="@(#)allo.c 4.10 (Berkeley) 12/9/87";
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( ISBUSY(r) ) 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 || (busy[r] & PBUSY)) &&
223: shareit( p, r, n ) ||
224: busy[r] == 0 && shareit( p, r+1, n ) ){
225: busy[r] |= TBUSY;
226: busy[r+1] |= TBUSY;
227: return(1);
228: }
229: else return(0);
230: }
231: if( busy[r] == 0 ) {
232: busy[r] |= TBUSY;
233: return(1);
234: }
235:
236: /* busy[r] is 1: is there chance for sharing */
237: return( shareit( p, r, n ) );
238:
239: }
240: # endif
241:
242: shareit( p, r, n ) NODE *p; {
243: /* can we make register r available by sharing from p
244: given that the need is n */
245: if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1);
246: if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1);
247: return(0);
248: }
249:
250: ushare( p, f, r ) NODE *p; {
251: /* can we find a register r to share on the left or right
252: (as f=='L' or 'R', respectively) of p */
253: p = getlr( p, f );
254: if( p->in.op == UNARY MUL ) p = p->in.left;
255: if( p->in.op == OREG ){
256: if( R2TEST(p->tn.rval) ){
257: return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) );
258: }
259: else return( r == p->tn.rval );
260: }
261: if( p->in.op == REG ){
262: return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) );
263: }
264: return(0);
265: }
266:
267: recl2( p ) register NODE *p; {
268: register r = p->tn.rval;
269: #ifndef OLD
270: int op = p->in.op;
271: if (op == REG && r >= REGSZ)
272: op = OREG;
273: if( op == REG ) rfree( r, p->in.type );
274: else if( op == OREG ) {
275: if( R2TEST( r ) ) {
276: if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
277: rfree( R2UPK2( r ), INT );
278: }
279: else {
280: rfree( r, PTR+INT );
281: }
282: }
283: #else
284: if( p->in.op == REG ) rfree( r, p->in.type );
285: else if( p->in.op == OREG ) {
286: if( R2TEST( r ) ) {
287: if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
288: rfree( R2UPK2( r ), INT );
289: }
290: else {
291: rfree( r, PTR+INT );
292: }
293: }
294: #endif
295: }
296:
297: int rdebug = 0;
298:
299: # ifndef RFREE
300: rfree( r, t ) TWORD t; {
301: /* mark register r free, if it is legal to do so */
302: /* t is the type */
303:
304: # ifndef BUG3
305: if( rdebug ){
306: printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
307: }
308: # endif
309:
310: if( istreg(r) ){
311: if( --busy[r] < 0 ) cerror( "register overfreed");
312: if( busy[r] == PBUSY )
313: busy[r] = 0;
314: if( szty(t) == 2 ){
315: #ifdef NOEVENODD
316: if( istreg(r) ^ istreg(r+1) ) cerror( "illegal free" );
317: #else
318: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
319: #endif
320: if( --busy[r+1] < 0 ) cerror( "register overfreed" );
321: }
322: }
323: }
324: # endif
325:
326: # ifndef RBUSY
327: rbusy(r,t) TWORD t; {
328: /* mark register r busy */
329: /* t is the type */
330:
331: # ifndef BUG3
332: if( rdebug ){
333: printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
334: }
335: # endif
336:
337: if( istreg(r) ) ++busy[r];
338: if( szty(t) == 2 ){
339: if( istreg(r+1) ) {
340: ++busy[r+1];
341: busy[r] |= PBUSY;
342: }
343: #ifdef NOEVENODD
344: if( istreg(r) ^ istreg(r+1) ) cerror( "illegal register pair freed" );
345: #else
346: if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
347: #endif
348: }
349: }
350: # endif
351:
352: # ifndef BUG3
353: rwprint( rw ){ /* print rewriting rule */
354: register i, flag;
355: static char * rwnames[] = {
356:
357: "RLEFT",
358: "RRIGHT",
359: "RESC1",
360: "RESC2",
361: "RESC3",
362: 0,
363: };
364:
365: if( rw == RNULL ){
366: printf( "RNULL" );
367: return;
368: }
369:
370: if( rw == RNOP ){
371: printf( "RNOP" );
372: return;
373: }
374:
375: flag = 0;
376: for( i=0; rwnames[i]; ++i ){
377: if( rw & (1<<i) ){
378: if( flag ) printf( "|" );
379: ++flag;
380: printf( rwnames[i] );
381: }
382: }
383: }
384: # endif
385:
386: reclaim( p, rw, cookie ) NODE *p; {
387: register NODE **qq;
388: register NODE *q;
389: register i;
390: NODE *recres[5];
391: struct respref *r;
392:
393: /* get back stuff */
394:
395: # ifndef BUG3
396: if( rdebug ){
397: printf( "reclaim( %o, ", p );
398: rwprint( rw );
399: printf( ", " );
400: prcook( cookie );
401: printf( " )\n" );
402: }
403: # endif
404:
405: if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */
406:
407: walkf( p, recl2 );
408:
409: if( callop(p->in.op) ){
410: /* check that all scratch regs are free */
411: callchk(p); /* ordinarily, this is the same as allchk() */
412: }
413:
414: if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
415: tfree(p);
416: return;
417: }
418:
419: /* handle condition codes specially */
420:
421: if( (cookie & FORCC) && (rw&RESCC)) {
422: /* result is CC register */
423: tfree(p);
424: p->in.op = CCODES;
425: p->tn.lval = 0;
426: p->tn.rval = 0;
427: return;
428: }
429:
430: /* locate results */
431:
432: qq = recres;
433:
434: if( rw&RLEFT) *qq++ = getlr( p, 'L' );;
435: if( rw&RRIGHT ) *qq++ = getlr( p, 'R' );
436: if( rw&RESC1 ) *qq++ = &resc[0];
437: if( rw&RESC2 ) *qq++ = &resc[1];
438: if( rw&RESC3 ) *qq++ = &resc[2];
439:
440: if( qq == recres ){
441: cerror( "illegal reclaim");
442: }
443:
444: *qq = NIL;
445:
446: /* now, select the best result, based on the cookie */
447:
448: for( r=respref; r->cform; ++r ){
449: if( cookie & r->cform ){
450: for( qq=recres; (q= *qq) != NIL; ++qq ){
451: if( tshape( q, r->mform ) ) goto gotit;
452: }
453: }
454: }
455:
456: /* we can't do it; die */
457: cerror( "cannot reclaim");
458:
459: gotit:
460:
461: if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */
462:
463: q->in.type = p->in.type; /* to make multi-register allocations work */
464: /* maybe there is a better way! */
465: q = tcopy(q);
466:
467: tfree(p);
468:
469: p->in.op = q->in.op;
470: p->tn.lval = q->tn.lval;
471: p->tn.rval = q->tn.rval;
472: #ifdef FLEXNAMES
473: p->in.name = q->in.name;
474: #ifdef ONEPASS
475: p->in.stalign = q->in.stalign;
476: #endif
477: #else
478: for( i=0; i<NCHNAM; ++i )
479: p->in.name[i] = q->in.name[i];
480: #endif
481:
482: q->in.op = FREE;
483:
484: /* if the thing is in a register, adjust the type */
485:
486: switch( p->in.op ){
487:
488: case REG:
489: if( !rtyflg ){
490: /* the C language requires intermediate results to change type */
491: /* this is inefficient or impossible on some machines */
492: /* the "T" command in match supresses this type changing */
493: if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT;
494: else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED;
495: #if !defined(FORT) && !defined(SPRECC)
496: else if( p->in.type == FLOAT ) p->in.type = DOUBLE;
497: #endif
498: }
499: if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */
500: i = p->in.rall & ~MUSTDO;
501: if( i & NOPREF ) return;
502: if( i != p->tn.rval ){
503: if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){
504: cerror( "faulty register move" );
505: }
506: rbusy( i, p->in.type );
507: rfree( p->tn.rval, p->in.type );
508: rmove( i, p->tn.rval, p->in.type );
509: p->tn.rval = i;
510: }
511:
512: case OREG:
513: if( p->in.op == REG || !R2TEST(p->tn.rval) ) {
514: if( ISBUSY(p->tn.rval) && istreg(p->tn.rval) ) cerror( "potential register overwrite");
515: }
516: else
517: if( (R2UPK1(p->tn.rval) != 100 && ISBUSY(R2UPK1(p->tn.rval)) && istreg(R2UPK1(p->tn.rval)) )
518: || (ISBUSY(R2UPK2(p->tn.rval)) && istreg(R2UPK2(p->tn.rval)) ) )
519: cerror( "potential register overwrite");
520: }
521:
522: }
523:
524: #ifndef ncopy
525: ncopy( q, p ) NODE *p, *q; {
526: /* copy the contents of p into q, without any feeling for
527: the contents */
528: /* this code assume that copying rval and lval does the job;
529: in general, it might be necessary to special case the
530: operator types */
531: register i;
532:
533: q->in.op = p->in.op;
534: q->in.rall = p->in.rall;
535: q->in.type = p->in.type;
536: q->tn.lval = p->tn.lval;
537: q->tn.rval = p->tn.rval;
538: #ifdef FLEXNAMES
539: q->in.name = p->in.name;
540: #ifdef ONEPASS
541: q->in.stalign = p->in.stalign;
542: #endif
543: #else
544: for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i];
545: #endif
546:
547: }
548: #endif
549:
550: NODE *
551: tcopy( p ) register NODE *p; {
552: /* make a fresh copy of p */
553:
554: register NODE *q;
555: register r;
556:
557: ncopy( q=talloc(), p );
558:
559: r = p->tn.rval;
560: if( p->in.op == REG ) rbusy( r, p->in.type );
561: else if( p->in.op == OREG ) {
562: if( R2TEST(r) ){
563: if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT );
564: rbusy( R2UPK2(r), INT );
565: }
566: else {
567: rbusy( r, PTR+INT );
568: }
569: }
570:
571: switch( optype(q->in.op) ){
572:
573: case BITYPE:
574: q->in.right = tcopy(p->in.right);
575: case UTYPE:
576: q->in.left = tcopy(p->in.left);
577: }
578:
579: return(q);
580: }
581:
582: allchk(){
583: /* check to ensure that all register are free */
584:
585: register i;
586:
587: REGLOOP(i){
588: if( istreg(i) && busy[i] ){
589: cerror( "register allocation error");
590: }
591: }
592:
593: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.