xref: /csrg-svn/old/pcc/ccom.tahoe/order.c (revision 32893)
1 #ifndef lint
2 static char sccsid[] = "@(#)order.c	1.3 (Berkeley) 12/10/87";
3 #endif
4 
5 # include "pass2.h"
6 
7 int maxargs = { -1 };
8 
9 /*ARGSUSED*/
10 stoasg( p, o ) NODE *p; {
11 	/* should the assignment op p be stored,
12 	   given that it lies as the right operand of o
13 	   (or the left, if o==UNARY MUL) */
14 	}
15 
16 deltest( p ) register NODE *p; {
17 	/* should we delay the INCR or DECR operation p */
18 	p = p->in.left;
19 	return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG );
20 	}
21 
22 /*ARGSUSED*/
23 autoincr( p ) NODE *p; {
24 
25 	return(0);
26 	}
27 
28 mkadrs(p) register NODE *p; {
29 	register int o;
30 
31 	o = p->in.op;
32 
33 	if( asgop(o) ){
34 		if( p->in.left->in.su >= p->in.right->in.su ){
35 			if( p->in.left->in.op == UNARY MUL ){
36 				SETSTO( p->in.left->in.left, INTEMP );
37 				}
38 			else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
39 				SETSTO( p->in.left->in.left->in.left, INTEMP );
40 				}
41 			else { /* should be only structure assignment */
42 				SETSTO( p->in.left, INTEMP );
43 				}
44 			}
45 		else SETSTO( p->in.right, INTEMP );
46 		}
47 	else {
48 		if( p->in.left->in.su > p->in.right->in.su ){
49 			SETSTO( p->in.left, INTEMP );
50 			}
51 		else {
52 			SETSTO( p->in.right, INTEMP );
53 			}
54 		}
55 	}
56 
57 /*ARGSUSED*/
58 notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; {
59 	/* is it legal to make an OREG or NAME entry which has an
60 	/* offset of off, (from a register of r), if the
61 	/* resulting thing had type t */
62 
63 	return(0);  /* YES */
64 	}
65 
66 # define max(x,y) ((x)<(y)?(y):(x))
67 
68 sucomp( p ) register NODE *p; {
69 
70 	/* set the su field in the node to the sethi-ullman
71 	   number, or local equivalent */
72 
73 	register int o, ty, sul, sur, r;
74 
75 	o = p->in.op;
76 	ty = optype( o );
77 	p->in.su = szty( p->in.type );   /* 2 for double, else 1 */;
78 
79 	if( ty == LTYPE ){
80 		if( o == OREG ){
81 			r = p->tn.rval;
82 			/* oreg cost is (worst case) 1 + number of temp registers used */
83 			if( R2TEST(r) ){
84 				if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su;
85 				if( istreg(R2UPK2(r)) ) ++p->in.su;
86 				}
87 			else {
88 				if( istreg( r ) ) ++p->in.su;
89 				}
90 			}
91 		if( p->in.su == szty(p->in.type) &&
92 		   (p->in.op!=REG || !istreg(p->tn.rval)) &&
93 		   (p->in.type==INT || p->in.type==UNSIGNED || p->in.type==DOUBLE) )
94 			p->in.su = 0;
95 		return;
96 		}
97 
98 	else if( ty == UTYPE ){
99 		switch( o ) {
100 		case UNARY CALL:
101 		case UNARY STCALL:
102 			p->in.su = fregs;  /* all regs needed */
103 			return;
104 
105 		default:
106 			p->in.su = p->in.left->in.su +
107 			(szty(p->in.type) >1 ? 2 : 0);
108 			return;
109 			}
110 		}
111 
112 
113 	/* If rhs needs n, lhs needs m, regular su computation */
114 
115 	sul = p->in.left->in.su;
116 	sur = p->in.right->in.su;
117 
118 	if( o == ASSIGN ){
119 		/* computed by doing right, then left (if not in mem), then doing it */
120 		p->in.su = max(sur,sul+1);
121 		return;
122 		}
123 
124 	if( o == CALL || o == STCALL ){
125 		/* in effect, takes all free registers */
126 		p->in.su = fregs;
127 		return;
128 		}
129 
130 	if( o == STASG ){
131 		/* right, then left */
132 		p->in.su = max( max( 1+sul, sur), fregs );
133 		return;
134 		}
135 
136 	if( asgop(o) ){
137 		/* computed by doing right, doing left address, doing left, op, and store */
138 		if(optype(p->in.left->in.op) != LTYPE)
139 			sul++;
140 		/* ediv uses more regs */
141 		if(o==ASG DIV && p->in.left->in.type==UNSIGNED || o==ASG MOD){
142 			p->in.su = max(max(sur,sul+(sur!=0)),4+(sul!=0)+(sur!=0));
143 			return;
144 			}
145 		p->in.su = max(sur,sul+1);
146 		return;
147 		}
148 
149 	switch( o ){
150 	case ANDAND:
151 	case OROR:
152 	case QUEST:
153 	case COLON:
154 	case COMOP:
155 		p->in.su = max( max(sul,sur), 1);
156 		return;
157 
158 	case PLUS:
159 	case MUL:
160 	case OR:
161 	case ER:
162 		/* commutative ops; put harder on left */
163 		if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){
164 			register NODE *temp;
165 			temp = p->in.left;
166 			p->in.left = p->in.right;
167 			p->in.right = temp;
168 			}
169 		break;
170 	case DIV:
171 		/* ediv uses more regs */
172 		if(p->in.left->in.type!=UNSIGNED)
173 			break;
174 	case MOD:
175 		p->in.su = max(max(sul,sur+(sul!=0)),4+(sul!=0)+(sur!=0));
176 		return;
177 	case SCONV:
178 		p->in.su = max(sul,szty(p->in.right->in.type)+sur)+2;
179 		return;
180 		}
181 	/* binary op, computed by left, then right, then do op */
182 	p->in.su = max(sul,szty(p->in.right->in.type)+sur);
183 
184 	}
185 
186 int radebug = 0;
187 
188 rallo( p, down ) NODE *p; {
189 	/* do register allocation */
190 	register int o, down1, down2, ty;
191 
192 	if( radebug ) printf( "rallo( %o, %d )\n", p, down );
193 
194 	down2 = NOPREF;
195 	p->in.rall = down;
196 	down1 = ( down &= ~MUSTDO );
197 
198 	ty = optype( o = p->in.op );
199 	switch( o ) {
200 	case ASSIGN:
201 		down1 = NOPREF;
202 		down2 = down;
203 		break;
204 
205 	case CALL:
206 	case STASG:
207 	case EQ:
208 	case NE:
209 	case GT:
210 	case GE:
211 	case LT:
212 	case LE:
213 	case NOT:
214 	case ANDAND:
215 	case OROR:
216 		down1 = NOPREF;
217 		break;
218 
219 	case FORCE:
220 		down1 = R0|MUSTDO;
221 		break;
222 
223 		}
224 
225 	if( ty != LTYPE ) rallo( p->in.left, down1 );
226 	if( ty == BITYPE ) rallo( p->in.right, down2 );
227 
228 	}
229 
230 /* VARARGS1 */
231 offstar( p ) register NODE *p; {
232 	if( p->in.op == PLUS ) {
233 		if( p->in.left->in.su == fregs ) {
234 			order( p->in.left, INTAREG|INAREG );
235 			return;
236 		} else if( p->in.right->in.su == fregs ) {
237 			order( p->in.right, INTAREG|INAREG );
238 			return;
239 		}
240 		if( p->in.left->in.op==LS &&
241 		  (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) {
242 			order( p->in.left->in.left, INTAREG|INAREG );
243 			return;
244 		}
245 		if( p->in.right->in.op==LS &&
246 		  (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) {
247 			order( p->in.right->in.left, INTAREG|INAREG );
248 			return;
249 		}
250 		if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) {
251 			if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) {
252 				order( p->in.left, INTAREG|INAREG );
253 				return;
254 			}
255 			else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) {
256 				order(p->in.right, INTAREG|INAREG);
257 				return;
258 			}
259 		}
260 	}
261 	if( p->in.op == PLUS || p->in.op == MINUS ){
262 		if( p->in.right->in.op == ICON ){
263 			p = p->in.left;
264 			order( p , INTAREG|INAREG);
265 			return;
266 			}
267 		}
268 
269 	if( p->in.op == UNARY MUL && !canaddr(p) ) {
270 		offstar( p->in.left );
271 		return;
272 	}
273 
274 	order( p, INTAREG|INAREG );
275 	}
276 
277 /* VARARGS1 */
278 setincr( p ) register NODE *p; {
279 	p = p->in.left;
280 	if( p->in.op == UNARY MUL ){
281 		offstar( p );
282 		return( 1 );
283 		}
284 	return( 0 );
285 	}
286 
287 /* VARARGS1 */
288 setbin( p ) register NODE *p; {
289 	register int ro, rt;
290 
291 	rt = p->in.right->in.type;
292 	ro = p->in.right->in.op;
293 
294 	if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */
295 		if( ro == UNARY MUL ) {
296 			offstar( p->in.right->in.left );
297 			return(1);
298 		} else {
299 			order( p->in.right, INAREG|INTAREG|SOREG );
300 			return(1);
301 		}
302 	}
303 	if( !istnode( p->in.left) ) { /* try putting LHS into a reg */
304 		order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG );
305 		return(1);
306 		}
307 	else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){
308 		offstar( p->in.right->in.left );
309 		return(1);
310 		}
311 	else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG &&
312 			ro != NAME && ro != OREG && ro != ICON ) ){
313 		order( p->in.right, INAREG|INBREG );
314 		return(1);
315 		}
316 	return(0);
317 	}
318 
319 /* VARARGS1 */
320 setstr( p ) register NODE *p; { /* structure assignment */
321 	if( p->in.right->in.op != REG ){
322 		order( p->in.right, INTAREG );
323 		return(1);
324 		}
325 	p = p->in.left;
326 	if( p->in.op != NAME && p->in.op != OREG ){
327 		if( p->in.op != UNARY MUL ) cerror( "bad setstr" );
328 		order( p->in.left, INTAREG );
329 		return( 1 );
330 		}
331 	return( 0 );
332 	}
333 
334 /* VARARGS1 */
335 setasg( p ) register NODE *p; {
336 	/* setup for assignment operator */
337 
338 	if( !canaddr(p->in.right) ) {
339 		if( p->in.right->in.op == UNARY MUL )
340 			offstar(p->in.right->in.left);
341 		else
342 			order( p->in.right, INAREG|INBREG|SOREG );
343 		return(1);
344 		}
345 	if( p->in.left->in.op == UNARY MUL ) {
346 		offstar( p->in.left->in.left );
347 		return(1);
348 		}
349 	if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
350 		offstar( p->in.left->in.left->in.left );
351 		return(1);
352 		}
353 /* FLD patch */
354 	if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) {
355 		order( p->in.right, INAREG);
356 		return(1);
357 		}
358 /* end of FLD patch */
359 	return(0);
360 	}
361 
362 /* VARARGS1 */
363 setasop( p ) register NODE *p; {
364 	/* setup for =ops */
365 	register int rt, ro;
366 
367 	rt = p->in.right->in.type;
368 	ro = p->in.right->in.op;
369 
370 	if( ro == UNARY MUL && rt != CHAR ){
371 		offstar( p->in.right->in.left );
372 		return(1);
373 		}
374 	if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT ||
375 			( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){
376 		order( p->in.right, INAREG|INBREG );
377 		return(1);
378 		}
379 
380 
381 	p = p->in.left;
382 	if( p->in.op == FLD ) p = p->in.left;
383 
384 	switch( p->in.op ){
385 
386 	case REG:
387 	case ICON:
388 	case NAME:
389 	case OREG:
390 		return(0);
391 
392 	case UNARY MUL:
393 		if( p->in.left->in.op==OREG )
394 			return(0);
395 		else
396 			offstar( p->in.left );
397 		return(1);
398 
399 		}
400 	cerror( "illegal setasop" );
401 	}
402 
403 int crslab = 99999;  /* Tahoe */
404 
405 getlab(){
406 	return( crslab-- );
407 	}
408 
409 #ifndef deflab
410 deflab( l ){
411 	printf( "L%d:\n", l );
412 	}
413 #endif
414 
415 genargs( p, ptemp ) register NODE *p, *ptemp; {
416 	register NODE *pasg;
417 	register int align;
418 	register int size;
419 
420 	/* generate code for the arguments */
421 
422 	/*  first, do the arguments on the right */
423 	while( p->in.op == CM ){
424 		genargs( p->in.right, ptemp );
425 		p->in.op = FREE;
426 		p = p->in.left;
427 		}
428 
429 	if( p->in.op == STARG ){ /* structure valued argument */
430 
431 		size = p->stn.stsize;
432 		align = p->stn.stalign;
433 		if( p->in.left->in.op == ICON ){
434 			p->in.op = FREE;
435 			p= p->in.left;
436 			}
437 		else {
438 			/* make it look beautiful... */
439 			p->in.op = UNARY MUL;
440 			canon( p );  /* turn it into an oreg */
441 			if( p->in.op != OREG ){
442 				offstar( p->in.left );
443 				canon( p );
444 				if( p->in.op != OREG ){
445 					offstar( p->in.left );
446 					canon( p );
447 					if( p->in.op != OREG ) cerror( "stuck starg" );
448 					}
449 				}
450 			}
451 
452 
453  		ptemp->tn.lval = 0;	/* all moves to (sp) */
454 
455 		pasg = talloc();
456 		pasg->in.op = STASG;
457 		pasg->stn.stsize = size;
458 		pasg->stn.stalign = align;
459 		pasg->in.right = p;
460 		pasg->in.left = tcopy( ptemp );
461 
462 		/* the following line is done only with the knowledge
463 		that it will be undone by the STASG node, with the
464 		offset (lval) field retained */
465 
466 		if( p->in.op == OREG ) p->in.op = REG;  /* only for temporaries */
467 
468  		order( pasg, FORARG );
469 		ptemp->tn.lval += size;
470 		return;
471 		}
472 
473 	/* ordinary case */
474 
475 	order( p, FORARG );
476 	}
477 
478 argsize( p ) register NODE *p; {
479 	register int t;
480 	t = 0;
481 	if( p->in.op == CM ){
482 		t = argsize( p->in.left );
483 		p = p->in.right;
484 		}
485 	if( p->in.type == DOUBLE || p->in.type == FLOAT ){
486 		SETOFF( t, 4 );
487 		return( t+8 );
488 		}
489 	else if( p->in.op == STARG ){
490  		SETOFF( t, 4 );  /* alignment */
491  		return( t + ((p->stn.stsize+3)/4)*4 );  /* size */
492 		}
493 	else {
494 		SETOFF( t, 4 );
495 		return( t+4 );
496 		}
497 	}
498