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