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