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