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