Research V7 development
[unix-history] / usr / src / cmd / pcc / order.c
CommitLineData
3c5d933b
SJ
1# include "mfile2"
2
3int fltused = 0;
4
5stoasg( p, o ) register NODE *p; {
6 /* should the assignment op p be stored,
7 given that it lies as the right operand of o
8 (or the left, if o==UNARY MUL) */
9 return( shltype(p->left->op, p->left ) );
10
11 }
12
13deltest( p ) register NODE *p; {
14 /* should we delay the INCR or DECR operation p */
15 if( p->op == INCR && p->left->op == REG && spsz( p->left->type, p->right->lval ) ){
16 /* STARREG */
17 return( 0 );
18 }
19
20 p = p->left;
21 if( p->op == UNARY MUL ) p = p->left;
22 return( p->op == NAME || p->op == OREG || p->op == REG );
23 }
24
25mkadrs(p) register NODE *p; {
26 register o;
27
28 o = p->op;
29
30 if( asgop(o) ){
31 if( p->left->su >= p->right->su ){
32 if( p->left->op == UNARY MUL ){
33 if( p->left->su > 0 )
34 SETSTO( p->left->left, INTEMP );
35 else {
36 if( p->right->su > 0 ) SETSTO( p->right, INTEMP );
37 else cerror( "store finds both sides trivial" );
38 }
39 }
40 else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
41 SETSTO( p->left->left->left, INTEMP );
42 }
43 else { /* should be only structure assignment */
44 SETSTO( p->left, INTEMP );
45 }
46 }
47 else SETSTO( p->right, INTEMP );
48 }
49 else {
50 if( p->left->su > p->right->su ){
51 SETSTO( p->left, INTEMP );
52 }
53 else {
54 SETSTO( p->right, INTEMP );
55 }
56 }
57 }
58
59notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; {
60 /* is it legal to make an OREG or NAME entry which has an
61 /* offset of off, (from a register of r), if the
62 /* resulting thing had type t */
63
64 /* return( 1 ); /* NO */
65 return(0); /* YES */
66 }
67
68# define max(x,y) ((x)<(y)?(y):(x))
69# define min(x,y) ((x)<(y)?(x):(y))
70
71
72# define ZCHAR 01
73# define ZLONG 02
74# define ZFLOAT 04
75
76zum( p, zap ) register NODE *p; {
77 /* zap Sethi-Ullman number for chars, longs, floats */
78 /* in the case of longs, only STARNM's are zapped */
79 /* ZCHAR, ZLONG, ZFLOAT are used to select the zapping */
80
81 register su;
82
83 su = p->su;
84
85 switch( p->type ){
86
87 case CHAR:
88 case UCHAR:
89 if( !(zap&ZCHAR) ) break;
90 if( su == 0 ) p->su = su = 1;
91 break;
92
93 case LONG:
94 case ULONG:
95 if( !(zap&ZLONG) ) break;
96 if( p->op == UNARY MUL && su == 0 ) p->su = su = 2;
97 break;
98
99 case FLOAT:
100 if( !(zap&ZFLOAT) ) break;
101 if( su == 0 ) p->su = su = 1;
102
103 }
104
105 return( su );
106 }
107
108sucomp( p ) register NODE *p; {
109
110 /* set the su field in the node to the sethi-ullman
111 number, or local equivalent */
112
113 register o, ty, sul, sur;
114 register nr;
115
116 ty = optype( o=p->op);
117 nr = szty( p->type );
118 p->su = 0;
119
120 if( ty == LTYPE ) {
121 if( p->type==FLOAT ) p->su = 1;
122 return;
123 }
124 else if( ty == UTYPE ){
125 switch( o ) {
126 case UNARY CALL:
127 case UNARY STCALL:
128 p->su = fregs; /* all regs needed */
129 return;
130
131 case UNARY MUL:
132 if( shumul( p->left ) ) return;
133
134 default:
135 p->su = max( p->left->su, nr);
136 return;
137 }
138 }
139
140
141 /* If rhs needs n, lhs needs m, regular su computation */
142
143 sul = p->left->su;
144 sur = p->right->su;
145
146 if( o == ASSIGN ){
147 asop: /* also used for +=, etc., to memory */
148 if( sul==0 ){
149 /* don't need to worry about the left side */
150 p->su = max( sur, nr );
151 }
152 else {
153 /* right, left address, op */
154 if( sur == 0 ){
155 /* just get the lhs address into a register, and mov */
156 /* the `nr' covers the case where value is in reg afterwards */
157 p->su = max( sul, nr );
158 }
159 else {
160 /* right, left address, op */
161 p->su = max( sur, nr+sul );
162 }
163 }
164 return;
165 }
166
167 if( o == CALL || o == STCALL ){
168 /* in effect, takes all free registers */
169 p->su = fregs;
170 return;
171 }
172
173 if( o == STASG ){
174 /* right, then left */
175 p->su = max( max( sul+nr, sur), fregs );
176 return;
177 }
178
179 if( logop(o) ){
180 /* do the harder side, then the easier side, into registers */
181 /* left then right, max(sul,sur+nr) */
182 /* right then left, max(sur,sul+nr) */
183 /* to hold both sides in regs: nr+nr */
184 nr = szty( p->left->type );
185 sul = zum( p->left, ZLONG|ZCHAR|ZFLOAT );
186 sur = zum( p->right, ZLONG|ZCHAR|ZFLOAT );
187 p->su = min( max(sul,sur+nr), max(sur,sul+nr) );
188 return;
189 }
190
191 if( asgop(o) ){
192 /* computed by doing right, doing left address, doing left, op, and store */
193 switch( o ) {
194 case INCR:
195 case DECR:
196 /* do as binary op */
197 break;
198
199 case ASG DIV:
200 case ASG MOD:
201 case ASG MUL:
202 if( p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs;
203 goto gencase;
204
205 case ASG PLUS:
206 case ASG MINUS:
207 case ASG AND: /* really bic */
208 case ASG OR:
209 if( p->type == INT || p->type == UNSIGNED || ISPTR(p->type) ) goto asop;
210
211 gencase:
212 default:
213 sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT );
214 if( sur == 0 ){ /* easy case: if addressable,
215 do left value, op, store */
216 if( sul == 0 ) p->su = nr;
217 /* harder: left adr, val, op, store */
218 else p->su = max( sul, nr+1 );
219 }
220 else { /* do right, left adr, left value, op, store */
221 if( sul == 0 ){ /* right, left value, op, store */
222 p->su = max( sur, nr+nr );
223 }
224 else {
225 p->su = max( sur, max( sul+nr, 1+nr+nr ) );
226 }
227 }
228 return;
229 }
230 }
231
232 switch( o ){
233 case ANDAND:
234 case OROR:
235 case QUEST:
236 case COLON:
237 case COMOP:
238 p->su = max( max(sul,sur), nr);
239 return;
240 }
241
242 if( ( o==DIV || o==MOD || o==MUL )
243 && p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs;
244 if( o==PLUS || o==MUL || o==OR || o==ER ){
245 /* AND is ruined by the hardware */
246 /* permute: get the harder on the left */
247
248 register rt, lt;
249
250 if( istnode( p->left ) || sul > sur ) goto noswap; /* don't do it! */
251
252 /* look for a funny type on the left, one on the right */
253
254
255 lt = p->left->type;
256 rt = p->right->type;
257
258 if( rt == FLOAT && lt == DOUBLE ) goto swap;
259
260 if( (rt==CHAR||rt==UCHAR) && (lt==INT||lt==UNSIGNED||ISPTR(lt)) ) goto swap;
261
262 if( lt==LONG || lt==ULONG ){
263 if( rt==LONG || rt==ULONG ){
264 /* if one is a STARNM, swap */
265 if( p->left->op == UNARY MUL && sul==0 ) goto noswap;
266 if( p->right->op == UNARY MUL && p->left->op != UNARY MUL ) goto swap;
267 goto noswap;
268 }
269 else if( p->left->op == UNARY MUL && sul == 0 ) goto noswap;
270 else goto swap; /* put long on right, unless STARNM */
271 }
272
273 /* we are finished with the type stuff now; if one is addressable,
274 put it on the right */
275 if( sul == 0 && sur != 0 ){
276
277 NODE *s;
278 int ssu;
279
280 swap:
281 ssu = sul; sul = sur; sur = ssu;
282 s = p->left; p->left = p->right; p->right = s;
283 }
284 }
285 noswap:
286
287 sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT );
288 if( sur == 0 ){
289 /* get left value into a register, do op */
290 p->su = max( nr, sul );
291 }
292 else {
293 /* do harder into a register, then easier */
294 p->su = max( nr+nr, min( max( sul, nr+sur ), max( sur, nr+sul ) ) );
295 }
296 }
297
298int radebug = 0;
299
300mkrall( p, r ) register NODE *p; {
301 /* insure that the use of p gets done with register r; in effect, */
302 /* simulate offstar */
303
304 if( p->op == FLD ){
305 p->left->rall = p->rall;
306 p = p->left;
307 }
308
309 if( p->op != UNARY MUL ) return; /* no more to do */
310 p = p->left;
311 if( p->op == UNARY MUL ){
312 p->rall = r;
313 p = p->left;
314 }
315 if( p->op == PLUS && p->right->op == ICON ){
316 p->rall = r;
317 p = p->left;
318 }
319 rallo( p, r );
320 }
321
322rallo( p, down ) register NODE *p; {
323 /* do register allocation */
324 register o, type, down1, down2, ty;
325
326 if( radebug ) printf( "rallo( %o, %o )\n", p, down );
327
328 down2 = NOPREF;
329 p->rall = down;
330 down1 = ( down &= ~MUSTDO );
331
332 ty = optype( o = p->op );
333 type = p->type;
334
335
336 if( type == DOUBLE || type == FLOAT ){
337 if( o == FORCE ) down1 = FR0|MUSTDO;
338 ++fltused;
339 }
340 else switch( o ) {
341 case ASSIGN:
342 down1 = NOPREF;
343 down2 = down;
344 break;
345
346 case ASG MUL:
347 case ASG DIV:
348 case ASG MOD:
349 /* keep the addresses out of the hair of (r0,r1) */
350 if(fregs == 2 ){
351 /* lhs in (r0,r1), nothing else matters */
352 down1 = R1|MUSTDO;
353 down2 = NOPREF;
354 break;
355 }
356 /* at least 3 regs free */
357 /* compute lhs in (r0,r1), address of left in r2 */
358 p->left->rall = R1|MUSTDO;
359 mkrall( p->left, R2|MUSTDO );
360 /* now, deal with right */
361 if( fregs == 3 ) rallo( p->right, NOPREF );
362 else {
363 /* put address of long or value here */
364 p->right->rall = R3|MUSTDO;
365 mkrall( p->right, R3|MUSTDO );
366 }
367 return;
368
369 case MUL:
370 case DIV:
371 case MOD:
372 rallo( p->left, R1|MUSTDO );
373
374 if( fregs == 2 ){
375 rallo( p->right, NOPREF );
376 return;
377 }
378 /* compute addresses, stay away from (r0,r1) */
379
380 p->right->rall = (fregs==3) ? R2|MUSTDO : R3|MUSTDO ;
381 mkrall( p->right, R2|MUSTDO );
382 return;
383
384 case CALL:
385 case STASG:
386 case EQ:
387 case NE:
388 case GT:
389 case GE:
390 case LT:
391 case LE:
392 case NOT:
393 case ANDAND:
394 case OROR:
395 down1 = NOPREF;
396 break;
397
398 case FORCE:
399 down1 = R0|MUSTDO;
400 break;
401
402 }
403
404 if( ty != LTYPE ) rallo( p->left, down1 );
405 if( ty == BITYPE ) rallo( p->right, down2 );
406
407 }
408
409offstar( p ) register NODE *p; {
410 /* handle indirections */
411
412 if( p->op == UNARY MUL ) p = p->left;
413
414 if( p->op == PLUS || p->op == MINUS ){
415 if( p->right->op == ICON ){
416 order( p->left , INTAREG|INAREG );
417 return;
418 }
419 }
420 order( p, INTAREG|INAREG );
421 }
422
423setincr( p ) NODE *p; {
424 return( 0 ); /* for the moment, don't bother */
425 }
426
427niceuty( p ) register NODE *p; {
428 register TWORD t;
429
430 return( p->op == UNARY MUL && (t=p->type)!=CHAR &&
431 t!= UCHAR && t!= FLOAT &&
432 shumul( p->left) != STARREG );
433 }
434setbin( p ) register NODE *p; {
435 register NODE *r, *l;
436
437 r = p->right;
438 l = p->left;
439
440 if( p->right->su == 0 ){ /* rhs is addressable */
441 if( logop( p->op ) ){
442 if( l->op == UNARY MUL && l->type != FLOAT && shumul( l->left ) != STARREG ) offstar( l->left );
443 else order( l, INAREG|INTAREG|INBREG|INTBREG|INTEMP );
444 return( 1 );
445 }
446 if( !istnode( l ) ){
447 order( l, INTAREG|INTBREG );
448 return( 1 );
449 }
450 /* rewrite */
451 return( 0 );
452 }
453 /* now, rhs is complicated: must do both sides into registers */
454 /* do the harder side first */
455
456 if( logop( p->op ) ){
457 /* relational: do both sides into regs if need be */
458
459 if( r->su > l->su ){
460 if( niceuty(r) ){
461 offstar( r->left );
462 return( 1 );
463 }
464 else if( !istnode( r ) ){
465 order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP );
466 return( 1 );
467 }
468 }
469 if( niceuty(l) ){
470 offstar( l->left );
471 return( 1 );
472 }
473 else if( niceuty(r) ){
474 offstar( r->left );
475 return( 1 );
476 }
477 else if( !istnode( l ) ){
478 order( l, INTAREG|INAREG|INTBREG|INBREG|INTEMP );
479 return( 1 );
480 }
481 if( !istnode( r ) ){
482 order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP );
483 return( 1 );
484 }
485 cerror( "setbin can't deal with %s", opst[p->op] );
486 }
487
488 /* ordinary operator */
489
490 if( !istnode(r) && r->su > l->su ){
491 /* if there is a chance of making it addressable, try it... */
492 if( niceuty(r) ){
493 offstar( r->left );
494 return( 1 ); /* hopefully, it is addressable by now */
495 }
496 order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); /* anything goes on rhs */
497 return( 1 );
498 }
499 else {
500 if( !istnode( l ) ){
501 order( l, INTAREG|INTBREG );
502 return( 1 );
503 }
504 /* rewrite */
505 return( 0 );
506 }
507 }
508
509setstr( p ) register NODE *p; { /* structure assignment */
510 if( p->right->op != REG ){
511 order( p->right, INTAREG );
512 return(1);
513 }
514 p = p->left;
515 if( p->op != NAME && p->op != OREG ){
516 if( p->op != UNARY MUL ) cerror( "bad setstr" );
517 order( p->left, INTAREG );
518 return( 1 );
519 }
520 return( 0 );
521 }
522
523setasg( p ) register NODE *p; {
524 /* setup for assignment operator */
525
526 if( p->right->su != 0 && p->right->op != REG ) {
527 if( p->right->op == UNARY MUL )
528 offstar( p->right->left );
529 else
530 order( p->right, INAREG|INBREG|SOREG|SNAME|SCON );
531 return(1);
532 }
533 if( p->right->op != REG && ( p->type == FLOAT || p->type == DOUBLE ) ) {
534 order( p->right, INBREG );
535 return(1);
536 }
537 if( p->left->op == UNARY MUL && !tshape( p->left, STARREG|STARNM ) ){
538 offstar( p->left->left );
539 return(1);
540 }
541 if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
542 offstar( p->left->left->left );
543 return(1);
544 }
545 /* if things are really strange, get rhs into a register */
546 if( p->right->op != REG ){
547 order( p->right, INAREG|INBREG );
548 return( 1 );
549 }
550 return(0);
551 }
552
553setasop( p ) register NODE *p; {
554 /* setup for =ops */
555 register sul, sur;
556 register NODE *q, *p2;
557
558 sul = p->left->su;
559 sur = p->right->su;
560
561 switch( p->op ){
562
563 case ASG PLUS:
564 case ASG OR:
565 case ASG MINUS:
566 if( p->type != INT && p->type != UNSIGNED && !ISPTR(p->type) ) break;
567 if( p->right->type == CHAR || p->right->type == UCHAR ){
568 order( p->right, INAREG );
569 return( 1 );
570 }
571 break;
572
573 case ASG ER:
574 if( sul == 0 || p->left->op == REG ){
575 if( p->left->type == CHAR || p->left->type == UCHAR ) goto rew; /* rewrite */
576 order( p->right, INAREG|INBREG );
577 return( 1 );
578 }
579 goto leftadr;
580 }
581
582 if( sur == 0 ){
583
584 leftadr:
585 /* easy case: if addressable, do left value, op, store */
586 if( sul == 0 ) goto rew; /* rewrite */
587
588 /* harder; make aleft address, val, op, and store */
589
590 if( p->left->op == UNARY MUL ){
591 offstar( p->left->left );
592 return( 1 );
593 }
594 if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
595 offstar( p->left->left->left );
596 return( 1 );
597 }
598 rew: /* rewrite, accounting for autoincrement and autodecrement */
599
600 q = p->left;
601 if( q->op == FLD ) q = q->left;
602 if( q->op != UNARY MUL || shumul(q->left) != STARREG ) return(0); /* let reader.c do it */
603
604 /* mimic code from reader.c */
605
606 p2 = tcopy( p );
607 p->op = ASSIGN;
608 reclaim( p->right, RNULL, 0 );
609 p->right = p2;
610
611 /* now, zap INCR on right, ASG MINUS on left */
612
613 if( q->left->op == INCR ){
614 q = p2->left;
615 if( q->op == FLD ) q = q->left;
616 if( q->left->op != INCR ) cerror( "bad incr rewrite" );
617 }
618 else if( q->left->op != ASG MINUS ) cerror( " bad -= rewrite" );
619
620 q->left->right->op = FREE;
621 q->left->op = FREE;
622 q->left = q->left->left;
623
624 /* now, resume reader.c rewriting code */
625
626 canon(p);
627 rallo( p, p->rall );
628 order( p2->left, INTBREG|INTAREG );
629 order( p2, INTBREG|INTAREG );
630 return( 1 );
631 }
632
633 /* harder case: do right, left address, left value, op, store */
634
635 if( p->right->op == UNARY MUL ){
636 offstar( p->right->left );
637 return( 1 );
638 }
639 /* sur> 0, since otherwise, done above */
640 if( p->right->op == REG ) goto leftadr; /* make lhs addressable */
641 order( p->right, INAREG|INBREG );
642 return( 1 );
643 }
644
645int crslab = 10000;
646
647getlab(){
648 return( crslab++ );
649 }
650
651deflab( l ){
652 printf( "L%d:\n", l );
653 }
654
655genargs( p) register NODE *p; {
656 register size;
657
658 /* generate code for the arguments */
659
660 /* first, do the arguments on the right (last->first) */
661 while( p->op == CM ){
662 genargs( p->right );
663 p->op = FREE;
664 p = p->left;
665 }
666
667 if( p->op == STARG ){ /* structure valued argument */
668
669 size = p->stsize;
670 if( p->left->op == ICON ){
671 /* make into a name node */
672 p->op = FREE;
673 p= p->left;
674 p->op = NAME;
675 }
676 else {
677 /* make it look beautiful... */
678 p->op = UNARY MUL;
679 canon( p ); /* turn it into an oreg */
680 if( p->op != OREG ){
681 offstar( p->left );
682 canon( p );
683 if( p->op != OREG ) cerror( "stuck starg" );
684 }
685 }
686
687 p->lval += size; /* end of structure */
688 /* put on stack backwards */
689 for( ; size>0; size -= 2 ){
690 p->lval -= 2;
691 expand( p, RNOP, " mov AR,Z-\n" );
692 }
693 reclaim( p, RNULL, 0 );
694 return;
695 }
696
697 /* ordinary case */
698
699 order( p, FORARG );
700 }
701
702argsize( p ) register NODE *p; {
703 register t;
704 t = 0;
705 if( p->op == CM ){
706 t = argsize( p->left );
707 p = p->right;
708 }
709 if( p->type == DOUBLE || p->type == FLOAT ){
710 SETOFF( t, 2 );
711 return( t+8 );
712 }
713 else if( p->type == LONG || p->type == ULONG ) {
714 SETOFF( t, 2);
715 return( t+4 );
716 }
717 else if( p->op == STARG ){
718 SETOFF( t, p->stalign ); /* alignment */
719 return( t + p->stsize ); /* size */
720 }
721 else {
722 SETOFF( t, 2 );
723 return( t+2 );
724 }
725 }