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