BSD 4_4 release
[unix-history] / usr / src / old / pcc / ccom.tahoe / order.c
CommitLineData
fbf70ca6 1#ifndef lint
1c15e888 2static char sccsid[] = "@(#)order.c 1.8 (Berkeley) 8/26/88";
fbf70ca6
SL
3#endif
4
f8a5269a 5# include "pass2.h"
fbf70ca6
SL
6
7int maxargs = { -1 };
8
e7c77527 9/*ARGSUSED*/
fbf70ca6
SL
10stoasg( 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
16deltest( 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
e7c77527 22/*ARGSUSED*/
fbf70ca6
SL
23autoincr( p ) NODE *p; {
24
25 return(0);
26 }
27
28mkadrs(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
e7c77527 57/*ARGSUSED*/
fbf70ca6
SL
58notoff( 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
68sucomp( 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)) &&
8a2e495c
DS
93 (p->in.type==INT ||
94 p->in.type==UNSIGNED ||
95 p->in.type==FLOAT ||
96 p->in.type==DOUBLE ||
97 ISPTR(p->in.type) ||
8548594d 98 ISARY(p->in.type)) )
fbf70ca6
SL
99 p->in.su = 0;
100 return;
101 }
102
103 else if( ty == UTYPE ){
104 switch( o ) {
105 case UNARY CALL:
106 case UNARY STCALL:
107 p->in.su = fregs; /* all regs needed */
108 return;
109
110 default:
111 p->in.su = p->in.left->in.su +
112 (szty(p->in.type) >1 ? 2 : 0);
113 return;
114 }
115 }
116
117
118 /* If rhs needs n, lhs needs m, regular su computation */
119
120 sul = p->in.left->in.su;
121 sur = p->in.right->in.su;
122
123 if( o == ASSIGN ){
124 /* computed by doing right, then left (if not in mem), then doing it */
125 p->in.su = max(sur,sul+1);
126 return;
127 }
128
129 if( o == CALL || o == STCALL ){
130 /* in effect, takes all free registers */
131 p->in.su = fregs;
132 return;
133 }
134
135 if( o == STASG ){
136 /* right, then left */
137 p->in.su = max( max( 1+sul, sur), fregs );
138 return;
139 }
140
141 if( asgop(o) ){
142 /* computed by doing right, doing left address, doing left, op, and store */
143 if(optype(p->in.left->in.op) != LTYPE)
144 sul++;
145 /* ediv uses more regs */
146 if(o==ASG DIV && p->in.left->in.type==UNSIGNED || o==ASG MOD){
e0720a2a 147 p->in.su = max(max(sul,(sul!=0)+2),sur+1);
fbf70ca6
SL
148 return;
149 }
150 p->in.su = max(sur,sul+1);
151 return;
152 }
153
154 switch( o ){
155 case ANDAND:
156 case OROR:
157 case QUEST:
158 case COLON:
159 case COMOP:
160 p->in.su = max( max(sul,sur), 1);
161 return;
162
163 case PLUS:
164 case MUL:
165 case OR:
166 case ER:
167 /* commutative ops; put harder on left */
168 if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){
169 register NODE *temp;
170 temp = p->in.left;
171 p->in.left = p->in.right;
172 p->in.right = temp;
173 }
174 break;
175 case DIV:
176 /* ediv uses more regs */
177 if(p->in.left->in.type!=UNSIGNED)
178 break;
179 case MOD:
e0720a2a 180 p->in.su = max(max(sul,(sul!=0)+2),sur+1);
fbf70ca6 181 return;
fbf70ca6
SL
182 }
183 /* binary op, computed by left, then right, then do op */
184 p->in.su = max(sul,szty(p->in.right->in.type)+sur);
185
186 }
187
188int radebug = 0;
189
190rallo( p, down ) NODE *p; {
191 /* do register allocation */
192 register int o, down1, down2, ty;
193
194 if( radebug ) printf( "rallo( %o, %d )\n", p, down );
195
196 down2 = NOPREF;
197 p->in.rall = down;
198 down1 = ( down &= ~MUSTDO );
199
200 ty = optype( o = p->in.op );
201 switch( o ) {
202 case ASSIGN:
203 down1 = NOPREF;
204 down2 = down;
205 break;
206
207 case CALL:
208 case STASG:
209 case EQ:
210 case NE:
211 case GT:
212 case GE:
213 case LT:
214 case LE:
215 case NOT:
216 case ANDAND:
217 case OROR:
218 down1 = NOPREF;
219 break;
220
221 case FORCE:
222 down1 = R0|MUSTDO;
223 break;
224
225 }
226
227 if( ty != LTYPE ) rallo( p->in.left, down1 );
228 if( ty == BITYPE ) rallo( p->in.right, down2 );
229
230 }
231
fbf70ca6
SL
232offstar( p ) register NODE *p; {
233 if( p->in.op == PLUS ) {
234 if( p->in.left->in.su == fregs ) {
235 order( p->in.left, INTAREG|INAREG );
236 return;
237 } else if( p->in.right->in.su == fregs ) {
238 order( p->in.right, INTAREG|INAREG );
239 return;
240 }
241 if( p->in.left->in.op==LS &&
8a2e495c 242 (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=SZINT/SZCHAR ) ) {
fbf70ca6
SL
243 order( p->in.left->in.left, INTAREG|INAREG );
244 return;
245 }
246 if( p->in.right->in.op==LS &&
8a2e495c 247 (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=SZINT/SZCHAR ) ) {
fbf70ca6
SL
248 order( p->in.right->in.left, INTAREG|INAREG );
249 return;
250 }
251 if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) {
8a2e495c 252 if( p->in.left->in.op!=REG || tlen(p->in.left)!=SZINT/SZCHAR ) {
fbf70ca6
SL
253 order( p->in.left, INTAREG|INAREG );
254 return;
255 }
8a2e495c 256 else if( p->in.right->in.op!=REG || tlen(p->in.right)!=SZINT/SZCHAR ) {
fbf70ca6
SL
257 order(p->in.right, INTAREG|INAREG);
258 return;
259 }
260 }
261 }
262 if( p->in.op == PLUS || p->in.op == MINUS ){
263 if( p->in.right->in.op == ICON ){
264 p = p->in.left;
265 order( p , INTAREG|INAREG);
266 return;
267 }
268 }
269
270 if( p->in.op == UNARY MUL && !canaddr(p) ) {
271 offstar( p->in.left );
272 return;
273 }
274
275 order( p, INTAREG|INAREG );
276 }
277
fbf70ca6
SL
278setincr( p ) register NODE *p; {
279 p = p->in.left;
280 if( p->in.op == UNARY MUL ){
8a2e495c 281 offstar( p->in.left );
fbf70ca6
SL
282 return( 1 );
283 }
284 return( 0 );
285 }
286
fbf70ca6
SL
287setbin( p ) register NODE *p; {
288 register int ro, rt;
289
290 rt = p->in.right->in.type;
291 ro = p->in.right->in.op;
292
293 if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */
294 if( ro == UNARY MUL ) {
295 offstar( p->in.right->in.left );
296 return(1);
297 } else {
298 order( p->in.right, INAREG|INTAREG|SOREG );
299 return(1);
300 }
301 }
302 if( !istnode( p->in.left) ) { /* try putting LHS into a reg */
303 order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG );
304 return(1);
305 }
306 else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){
307 offstar( p->in.right->in.left );
308 return(1);
309 }
310 else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG &&
311 ro != NAME && ro != OREG && ro != ICON ) ){
312 order( p->in.right, INAREG|INBREG );
313 return(1);
314 }
315 return(0);
316 }
317
318/* VARARGS1 */
319setstr( p ) register NODE *p; { /* structure assignment */
320 if( p->in.right->in.op != REG ){
321 order( p->in.right, INTAREG );
322 return(1);
323 }
324 p = p->in.left;
325 if( p->in.op != NAME && p->in.op != OREG ){
326 if( p->in.op != UNARY MUL ) cerror( "bad setstr" );
327 order( p->in.left, INTAREG );
328 return( 1 );
329 }
330 return( 0 );
331 }
332
fbf70ca6
SL
333setasg( p ) register NODE *p; {
334 /* setup for assignment operator */
335
336 if( !canaddr(p->in.right) ) {
337 if( p->in.right->in.op == UNARY MUL )
338 offstar(p->in.right->in.left);
339 else
340 order( p->in.right, INAREG|INBREG|SOREG );
341 return(1);
342 }
343 if( p->in.left->in.op == UNARY MUL ) {
344 offstar( p->in.left->in.left );
345 return(1);
346 }
347 if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
348 offstar( p->in.left->in.left->in.left );
349 return(1);
350 }
351/* FLD patch */
352 if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) {
353 order( p->in.right, INAREG);
354 return(1);
355 }
356/* end of FLD patch */
357 return(0);
358 }
359
fbf70ca6
SL
360setasop( 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" );
8a2e495c 398 /*NOTREACHED*/
fbf70ca6
SL
399 }
400
e7c77527 401int crslab = 99999; /* Tahoe */
fbf70ca6
SL
402
403getlab(){
404 return( crslab-- );
405 }
406
407deflab( l ){
38cb9d5a 408 if (nerrors) return;
fbf70ca6
SL
409 printf( "L%d:\n", l );
410 }
411
412genargs( p, ptemp ) register NODE *p, *ptemp; {
413 register NODE *pasg;
414 register int align;
415 register int size;
26655c9e 416 int count;
fbf70ca6
SL
417
418 /* generate code for the arguments */
419
420 /* first, do the arguments on the right */
421 while( p->in.op == CM ){
422 genargs( p->in.right, ptemp );
423 p->in.op = FREE;
424 p = p->in.left;
425 }
426
427 if( p->in.op == STARG ){ /* structure valued argument */
428
429 size = p->stn.stsize;
430 align = p->stn.stalign;
431 if( p->in.left->in.op == ICON ){
432 p->in.op = FREE;
433 p= p->in.left;
434 }
435 else {
436 /* make it look beautiful... */
437 p->in.op = UNARY MUL;
438 canon( p ); /* turn it into an oreg */
26655c9e 439 for( count = 0; p->in.op != OREG && count < 10; ++count ){
fbf70ca6
SL
440 offstar( p->in.left );
441 canon( p );
fbf70ca6 442 }
26655c9e 443 if( p->in.op != OREG ) cerror( "stuck starg" );
fbf70ca6
SL
444 }
445
446
447 ptemp->tn.lval = 0; /* all moves to (sp) */
448
449 pasg = talloc();
450 pasg->in.op = STASG;
451 pasg->stn.stsize = size;
452 pasg->stn.stalign = align;
453 pasg->in.right = p;
454 pasg->in.left = tcopy( ptemp );
455
456 /* the following line is done only with the knowledge
457 that it will be undone by the STASG node, with the
458 offset (lval) field retained */
459
460 if( p->in.op == OREG ) p->in.op = REG; /* only for temporaries */
461
462 order( pasg, FORARG );
463 ptemp->tn.lval += size;
464 return;
465 }
466
467 /* ordinary case */
468
469 order( p, FORARG );
470 }
471
472argsize( p ) register NODE *p; {
473 register int t;
474 t = 0;
475 if( p->in.op == CM ){
476 t = argsize( p->in.left );
477 p = p->in.right;
478 }
479 if( p->in.type == DOUBLE || p->in.type == FLOAT ){
480 SETOFF( t, 4 );
481 return( t+8 );
482 }
483 else if( p->in.op == STARG ){
484 SETOFF( t, 4 ); /* alignment */
485 return( t + ((p->stn.stsize+3)/4)*4 ); /* size */
486 }
487 else {
488 SETOFF( t, 4 );
489 return( t+4 );
490 }
491 }