Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20020926204151

Diff

Diff from 1.8 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/mip/reader.c

Annotated File View

ragge
1.2
1 #if 0
ragge
1.1
2 static char *sccsid ="@(#)reader.c      4.8 (Berkeley) 12/10/87";
ragge
1.2
3 #endif
ragge
1.1
4
5 # include "pass2.h"
6
7 /*      some storage declarations */
8
9 int nrecur;
10 int lflag;
11 #ifdef FORT
12 int Oflag = 0;
13 #endif
14 extern int Wflag;
15 int xdebug = 0;
16 int udebug = 0;
17 int vdebug = 0;
18
19 OFFSZ tmpoff;  /* offset for first temporary, in bits for current block */
20 OFFSZ maxoff;  /* maximum temporary offset over all blocks in current ftn, in bits */
21 int maxtreg;
22
23 NODE *stotree;
24 int stocook;
25
26 OFFSZ baseoff = 0;
27 OFFSZ maxtemp = 0;
28
ragge
1.8
29 static int e2print(NODE *pint downint *aint *b);
30
ragge
1.2
31 void
32 p2compile(NODE *p)
33 {
ragge
1.1
34
35         iflflag ) lineidlinenofilename );
36         tmpoff = baseoff;  /* expression at top level reuses temps */
37         /* generate code for the tree p */
38 # ifndef BUG4
ragge
1.8
39         if (e2debugfwalkpe2print0 );
ragge
1.1
40 # endif
41
42 # ifdef MYREADER
43         MYREADER(p);  /* do your own laundering of the input */
44 # endif
45         nrecur = 0;
46         delayp );  /* do the code generation */
47         reclaimpRNULL0 );
48         allchk();
49         /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
50         /* first pass will do it... */
ragge
1.2
51 }
ragge
1.1
52
ragge
1.2
53 void
54 p2bbeg(int aoffint myreg)
55 {
ragge
1.1
56         static int myftn = -1;
57
58         tmpoff = baseoff = (unsigned intaoff;
59         maxtreg = myreg;
60         ifmyftn != ftnno ){ /* beginning of function */
61                 maxoff = baseoff;
62                 myftn = ftnno;
63                 maxtemp = 0;
64                 }
65         else {
66                 ifbaseoff > maxoff ) maxoff = baseoff;
67                 /* maxoff at end of ftn is max of autos and temps over all blocks */
68                 }
69         setregs();
ragge
1.2
70 }
ragge
1.1
71
ragge
1.2
72 void
73 p2bend()
74 {
ragge
1.1
75         SETOFFmaxoffALSTACK );
76         eobl2();
ragge
1.2
77 }
ragge
1.1
78
79 NODE *deltrees[DELAYS];
80 int deli;
81
ragge
1.2
82 /*
83  * look in all legal places for COMOP's and ++ and -- ops to delay
84  * note; don't delay ++ and -- within calls or things like
85  * getchar (in their macro forms) will start behaving strangely
86  */
87 void
88 delay(NODE *p)
89 {
90         int i;
ragge
1.1
91
92         /* look for visible COMOPS, and rewrite repeatedly */
93
ragge
1.2
94         while (delay1(p))
95                 ;
ragge
1.1
96
97         /* look for visible, delayable ++ and -- */
98
99         deli = 0;
100         delay2p );
101         codgenpFOREFF );  /* do what is left */
ragge
1.2
102         fori = 0i<deli; ++i )
103                 codgendeltrees[i], FOREFF );  /* do the rest */
104 }
105
106 /*
107  * look for COMOPS
108  */
109 int
110 delay1(NODE *p)
111 {
112         int oty;
ragge
1.1
113
114         o = p->in.op;
115         ty = optypeo );
116         ifty == LTYPE ) return0 );
117         else ifty == UTYPE ) returndelay1p->in.left ) );
118
119         switcho ){
120
121         case QUEST:
122         case ANDAND:
123         case OROR:
124                 /* don't look on RHS */
125                 returndelay1(p->in.left ) );
126
127         case COMOP:  /* the meat of the routine */
128                 delayp->in.left );  /* completely evaluate the LHS */
129                 /* rewrite the COMOP */
130                 { register NODE *q;
131                         q = p->in.right;
132                         ncopypp->in.right );
133                         q->in.op = FREE;
134                         }
135                 return1 );
ragge
1.2
136         }
ragge
1.1
137
138         returndelay1(p->in.left) || delay1(p->in.right ) );
ragge
1.2
139 }
ragge
1.1
140
ragge
1.2
141 void
142 delay2(NODE *p)
143 {
ragge
1.1
144
145         /* look for delayable ++ and -- operators */
146
ragge
1.2
147         int oty;
ragge
1.1
148         o = p->in.op;
149         ty = optypeo );
150
151         switcho ){
152
153         case NOT:
154         case QUEST:
155         case ANDAND:
156         case OROR:
157         case CALL:
158         case UNARY CALL:
159         case STCALL:
160         case UNARY STCALL:
161         case FORTCALL:
162         case UNARY FORTCALL:
163         case COMOP:
164         case CBRANCH:
165                 /* for the moment, don't delay past a conditional context, or
ragge
1.2
166                  * inside of a call */
ragge
1.1
167                 return;
168
169         case UNARY MUL:
170                 /* if *p++, do not rewrite */
171                 ifautoincrp ) ) return;
172                 break;
173
174         case INCR:
175         case DECR:
176                 ifdeltestp ) ){
177                         ifdeli < DELAYS ){
178                                 register NODE *q;
179                                 deltrees[deli++] = tcopy(p);
180                                 q = p->in.left;
181                                 p->in.right->in.op = FREE;  /* zap constant */
182                                 ncopypq );
183                                 q->in.op = FREE;
184                                 return;
185                                 }
186                         }
187
188                 }
189
190         ifty == BITYPE ) delay2p->in.right );
191         ifty != LTYPE ) delay2p->in.left );
ragge
1.2
192 }
ragge
1.1
193
ragge
1.2
194 /*
195  * generate the code for p;
196  * order may call codgen recursively
197  * cookie is used to describe the context
198  */
199 void
200 codgen(NODE *pint cookie)
201 {
ragge
1.1
202
ragge
1.8
203         for (;;) {
ragge
1.1
204                 canon(p);  /* creats OREG from * if possible and does sucomp */
205                 stotree = NIL;
206 # ifndef BUG4
ragge
1.8
207                 if (e2debug) {
208                         printf("store called on:\n");
209                         fwalk(pe2print0);
210                 }
ragge
1.1
211 # endif
212                 store(p);
213                 ifstotree==NIL ) break;
214
215                 /* because it's minimal, can do w.o. stores */
216
217                 orderstotreestocook );
ragge
1.2
218         }
ragge
1.1
219         orderpcookie );
ragge
1.2
220 }
ragge
1.1
221
222 # ifndef BUG4
223 char *cnames[] = {
224         "SANY",
225         "SAREG",
226         "STAREG",
227         "SBREG",
228         "STBREG",
229         "SCC",
230         "SNAME",
231         "SCON",
232         "SFLD",
233         "SOREG",
234 # ifdef WCARD1
235         "WCARD1",
236 # else
237         "STARNM",
238 # endif
239 # ifdef WCARD2
240         "WCARD2",
241 # else
242         "STARREG",
243 # endif
244         "INTEMP",
245         "FORARG",
246         "SWADD",
247         0,
248         };
249
ragge
1.2
250 /*
251  * print a nice-looking description of cookie
252  */
253 void
254 prcook(int cookie)
255 {
ragge
1.1
256         int iflag;
257
258         ifcookie & SPECIAL ){
259                 ifcookie == SZERO ) printf"SZERO" );
260                 else ifcookie == SONE ) printf"SONE" );
261                 else ifcookie == SMONE ) printf"SMONE" );
262                 else ifcookie == SCCON ) printf"SCCON" );
263                 else ifcookie == SSCON ) printf"SSCON" );
264                 else ifcookie == SSOREG ) printf"SSOREG" );
265                 else printf"SPECIAL+%d"cookie & ~SPECIAL );
266                 return;
267                 }
268
269         flag = 0;
270         fori=0cnames[i]; ++i ){
271                 ifcookie & (1<<i) ){
272                         ifflag ) printf"|" );
273                         ++flag;
274                         printfcnames[i] );
275                         }
276                 }
277
ragge
1.2
278 }
ragge
1.1
279 # endif
280
281 int odebug = 0;
282
ragge
1.2
283 void
284 order(NODE *pint cook)
285 {
286         int otym;
ragge
1.1
287         int m1;
288         int cookie;
ragge
1.2
289         NODE *p1, *p2;
ragge
1.1
290
291         cookie = cook;
292         rcount();
293         canon(p);
ragge
1.8
294         rallo(pp->in.rall);
ragge
1.1
295         goto first;
296
ragge
1.8
297
298         /*
299          * by this time, p should be able to be generated without stores;
300          * the only question is how
301          */
ragge
1.1
302         again:
303
ragge
1.8
304         if (p->in.op == FREE)
ragge
1.1
305                 return;         /* whole tree was done */
306         cookie = cook;
307         rcount();
308         canon(p);
ragge
1.8
309         rallo(pp->in.rall);
310         /*
311          * if any rewriting and canonicalization has put
ragge
1.1
312          * the tree (p) into a shape that cook is happy
313          * with (exclusive of FOREFF, FORREW, and INTEMP)
314          * then we are done.
315          * this allows us to call order with shapes in
316          * addition to cookies and stop short if possible.
317          */
ragge
1.8
318         if (tshape(pcook &(~(FOREFF|FORREW|INTEMP))))
319                 return;
ragge
1.1
320
321         first:
322 # ifndef BUG4
ragge
1.8
323         if (odebug) {
324                 printf("order(%p, "p);
325                 prcook(cookie);
326                 printf(")\n");
327                 fwalk(pe2print0);
328         }
ragge
1.1
329 # endif
330
331         o = p->in.op;
332         ty = optype(o);
333
334         /* first of all, for most ops, see if it is in the table */
335
336         /* look for ops */
337
ragge
1.8
338         switch (m = p->in.op) {
ragge
1.1
339
340         default:
341                 /* look for op in table */
ragge
1.8
342                 for (;;) {
343                         if ((m = match(pcookie)) == MDONE)
344                                 goto cleanup;
345                         else if (m == MNOPE) {
346                                 if (!(cookie = nextcook(pcookie)))
347                                         goto nomat;
ragge
1.1
348                                 continue;
ragge
1.8
349                         } else
350                                 break;
351                 }
ragge
1.1
352                 break;
353
354         case COMOP:
355         case FORCE:
356         case CBRANCH:
357         case QUEST:
358         case ANDAND:
359         case OROR:
360         case NOT:
361         case UNARY CALL:
362         case CALL:
363         case UNARY STCALL:
364         case STCALL:
365         case UNARY FORTCALL:
366         case FORTCALL:
367                 /* don't even go near the table... */
368                 ;
369
ragge
1.8
370         }
371         /*
372          * get here to do rewriting if no match or
373          * fall through from above for hard ops
374          */
ragge
1.1
375
376         p1 = p->in.left;
ragge
1.8
377         if (ty == BITYPE)
378                 p2 = p->in.right;
379         else
380                 p2 = NIL;
ragge
1.1
381         
382 # ifndef BUG4
ragge
1.8
383         if (odebug) {
384                 printf("order(%p, "p);
385                 prcook(cook);
386                 printf("), cookie ");
387                 prcook(cookie);
388                 printf(", rewrite %s\n"opst[m]);
389         }
ragge
1.1
390 # endif
ragge
1.8
391         switch (m) {
ragge
1.1
392         default:
393                 nomat:
394                 cerror"no table entry for op %s"opst[p->in.op] );
395
396         case COMOP:
397                 codgenp1FOREFF );
398                 p2->in.rall = p->in.rall;
399                 codgenp2cookie );
400                 ncopypp2 );
401                 p2->in.op = FREE;
402                 goto cleanup;
403
404         case FORCE:
405                 /* recurse, letting the work be done by rallo */
406                 p = p->in.left;
407                 cook = INTAREG|INTBREG;
408                 goto again;
409
410         case CBRANCH:
411                 o = p2->tn.lval;
412                 cbranchp1, -1o );
413                 p2->in.op = FREE;
414                 p->in.op = FREE;
415                 return;
416
417         case QUEST:
418                 cbranchp1, -1m=getlab() );
419                 p2->in.left->in.rall = p->in.rall;
420                 codgenp2->in.leftINTAREG|INTBREG );
421                 /* force right to compute result into same reg used by left */
422                 p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO;
423                 reclaimp2->in.leftRNULL0 );
424                 cbgen0m1 = getlab(), 'I' );
425                 deflabm );
426                 codgenp2->in.rightINTAREG|INTBREG );
427                 deflabm1 );
428                 p->in.op = REG;  /* set up node describing result */
429                 p->tn.lval = 0;
430                 p->tn.rval = p2->in.right->tn.rval;
431                 p->in.type = p2->in.right->in.type;
432                 tfreep2->in.right );
433                 p2->in.op = FREE;
434                 goto cleanup;
435
436         case ANDAND:
437         case OROR:
438         case NOT:  /* logical operators */
439                 /* if here, must be a logical operator for 0-1 value */
440                 cbranchp, -1m=getlab() );
441                 p->in.op = CCODES;
442                 p->bn.label = m;
443                 orderpINTAREG );
444                 goto cleanup;
445
446         case FLD:       /* fields of funny type */
447                 if ( p1->in.op == UNARY MUL ){
448                         offstarp1->in.left );
449                         goto again;
450                         }
451
452         case UNARY MINUS:
453                 orderp1INBREG|INAREG|SOREG );
454                 goto again;
455
456         case NAME:
457                 /* all leaves end up here ... */
458                 ifo == REG ) goto nomat;
459                 orderpINTAREG|INTBREG );
460                 goto again;
461
462         case INIT:
463                 uerror"illegal initialization" );
464                 return;
465
466         case UNARY FORTCALL:
467                 p->in.right = NIL;
468         case FORTCALL:
469                 o = p->in.op = UNARY FORTCALL;
470                 ifgenfcallpcookie ) ) goto nomat;
471                 goto cleanup;
472
473         case UNARY CALL:
474                 p->in.right = NIL;
475         case CALL:
476                 o = p->in.op = UNARY CALL;
477                 ifgencallpcookie ) ) goto nomat;
478                 goto cleanup;
479
480         case UNARY STCALL:
481                 p->in.right = NIL;
482         case STCALL:
483                 o = p->in.op = UNARY STCALL;
484                 ifgenscallpcookie ) ) goto nomat;
485                 goto cleanup;
486
487                 /* if arguments are passed in register, care must be taken that reclaim
ragge
1.2
488                  * not throw away the register which now has the result... */
ragge
1.1
489
490         case UNARY MUL:
491                 ifcook == FOREFF ){
492                         /* do nothing */
493                         orderp->in.leftFOREFF );
494                         p->in.op = FREE;
495                         return;
496                         }
497 #ifdef R2REGS
498                 /* try to coax a tree into a doubly indexed OREG */
499                 p1 = p->in.left;
500                 ifp1->in.op == PLUS ) {
501                         ifISPTR(p1->in.left->in.type) &&
502                             offset(p1->in.righttlen(p)) >= 0 ) {
503                                 orderp1->in.leftINAREG|INTAREG );
504                                 goto again;
505                                 }
506                         ifISPTR(p1->in.right->in.type) &&
507                             offset(p1->in.lefttlen(p)) >= 0 ) {
508                                 orderp1->in.rightINAREG|INTAREG );
509                                 goto again;
510                                 }
511                         }
512 #endif
513                 offstarp->in.left );
514                 goto again;
515
516         case INCR:  /* INCR and DECR */
517                 ifsetincr(p) ) goto again;
518
519                 /* x++ becomes (x += 1) -1; */
520
521                 ifcook & FOREFF ){  /* result not needed so inc or dec and be done with it */
522                         /* x++ => x += 1 */
523                         p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
524                         goto again;
525                         }
526
527                 p1 = tcopy(p);
528                 reclaimp->in.leftRNULL0 );
529                 p->in.left = p1;
530                 p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
531                 p->in.op = (p->in.op==INCR)?MINUS:PLUS;
532                 goto again;
533
534         case STASG:
535                 ifsetstrp ) ) goto again;
536                 goto nomat;
537
538         case ASG PLUS:  /* and other assignment ops */
539                 ifsetasop(p) ) goto again;
540
541                 /* there are assumed to be no side effects in LHS */
542
543                 p2 = tcopy(p);
544                 p->in.op = ASSIGN;
545                 reclaimp->in.rightRNULL0 );
546                 p->in.right = p2;
547                 canon(p);
548                 rallopp->in.rall );
549
550 # ifndef BUG4
ragge
1.8
551                 ifodebug ) fwalkpe2print0 );
ragge
1.1
552 # endif
553
554                 orderp2->in.leftINTBREG|INTAREG );
555                 orderp2INTBREG|INTAREG );
556                 goto again;
557
558         case ASSIGN:
ragge
1.8
559                 if (setasg(p))
560                         goto again;
ragge
1.1
561                 goto nomat;
562
563
564         case BITYPE:
565                 ifsetbinp ) ) goto again;
566                 /* try to replace binary ops by =ops */
567                 switch(o){
568
569                 case PLUS:
570                 case MINUS:
571                 case MUL:
572                 case DIV:
573                 case MOD:
574                 case AND:
575                 case OR:
576                 case ER:
577                 case LS:
578                 case RS:
579                         p->in.op = ASG o;
580                         goto again;
581                         }
582                 goto nomat;
583
584                 }
585
586         cleanup:
587
588         /* if it is not yet in the right state, put it there */
589
590         ifcook & FOREFF ){
591                 reclaimpRNULL0 );
592                 return;
593                 }
594
595         ifp->in.op==FREE ) return;
596
597         iftshapepcook ) ) return;
598
599         if( (m=match(p,cook) ) == MDONE ) return;
600
601         /* we are in bad shape, try one last chance */
ragge
1.8
602         if (lastchance(pcook))
603                 goto again;
ragge
1.1
604
605         goto nomat;
ragge
1.8
606 }
ragge
1.1
607
608 int callflag;
609 int fregs;
610
ragge
1.2
611 void
612 storep ) NODE *p; {
ragge
1.1
613
614         /* find a subtree of p which should be stored */
615
ragge
1.2
616         int oty;
ragge
1.1
617
618         o = p->in.op;
619         ty = optype(o);
620
621         ifty == LTYPE ) return;
622
623         switcho ){
624
625         case UNARY CALL:
626         case UNARY FORTCALL:
627         case UNARY STCALL:
628                 ++callflag;
629                 break;
630
631         case UNARY MUL:
632                 ifasgop(p->in.left->in.op) ) stoasgp->in.leftUNARY MUL );
633                 break;
634
635         case CALL:
636         case FORTCALL:
637         case STCALL:
638                 storep->in.left );
639                 stoargp->in.righto );
640                 ++callflag;
641                 return;
642
643         case COMOP:
644                 markcallp->in.right );
645                 ifp->in.right->in.su > fregs ) SETSTOpINTEMP );
646                 storep->in.left );
647                 return;
648
649         case ANDAND:
650         case OROR:
651         case QUEST:
652                 markcallp->in.right );
653                 ifp->in.right->in.su > fregs ) SETSTOpINTEMP );
654         case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
655         case NOT:
656                 constorep->in.left );
657                 return;
658
659                 }
660
661         ifty == UTYPE ){
662                 storep->in.left );
663                 return;
664                 }
665
666         ifasgopp->in.right->in.op ) ) stoasgp->in.righto );
667
668         ifp->in.su>fregs ){ /* must store */
669                 mkadrsp );  /* set up stotree and stocook to subtree
670                                  that must be stored */
671                 }
672
673         storep->in.right );
674         storep->in.left );
675         }
676
ragge
1.2
677 /*
678  * store conditional expressions
679  * the point is, avoid storing expressions in conditional
680  * conditional context, since the evaluation order is predetermined
681  */
682 void
683 constore(NODE *p)
684 {
ragge
1.1
685         switchp->in.op ) {
686
687         case ANDAND:
688         case OROR:
689         case QUEST:
690                 markcallp->in.right );
691         case NOT:
692                 constorep->in.left );
693                 return;
694
695                 }
696
697         storep );
ragge
1.2
698 }
ragge
1.1
699
ragge
1.2
700 /* mark off calls below the current node */
701 void
702 markcall(NODE *p)
703 {
ragge
1.1
704
705         again:
706         switchp->in.op ){
707
708         case UNARY CALL:
709         case UNARY STCALL:
710         case UNARY FORTCALL:
711         case CALL:
712         case STCALL:
713         case FORTCALL:
714                 ++callflag;
715                 return;
716
717                 }
718
719         switchoptypep->in.op ) ){
720
721         case BITYPE:
722                 markcallp->in.right );
723         case UTYPE:
724                 p = p->in.left;
725                 /* eliminate recursion (aren't I clever...) */
726                 goto again;
727         case LTYPE:
728                 return;
729                 }
730
ragge
1.2
731 }
ragge
1.1
732
ragge
1.2
733 void
734 stoarg(NODE *pint calltype)
735 {
ragge
1.1
736         /* arrange to store the args */
737         ifp->in.op == CM ){
738                 stoargp->in.leftcalltype );
739                 p = p->in.right ;
740                 }
741         ifcalltype == CALL ){
742                 STOARG(p);
743                 }
744         else ifcalltype == STCALL ){
745                 STOSTARG(p);
746                 }
747         else {
748                 STOFARG(p);
749                 }
750         callflag = 0;
751         store(p);
752 # ifndef NESTCALLS
753         ifcallflag ){ /* prevent two calls from being active at once  */
754                 SETSTO(p,INTEMP);
755                 store(p); /* do again to preserve bottom up nature....  */
ragge
1.2
756         }
ragge
1.1
757 #endif
ragge
1.2
758 }
ragge
1.1
759
760 int negrel[] = { NEEQGTGELTLEUGTUGEULTULE } ;  /* negatives of relationals */
761
ragge
1.2
762 /*
763  * evaluate p for truth value, and branch to true or false
764  * accordingly: label <0 means fall through
765  */
766
767 void
768 cbranch(NODE *pint trueint false)
769 {
770         int olabflabtlab;
ragge
1.1
771
772         lab = -1;
773
774         switcho=p->in.op ){
775
776         case ULE:
777         case ULT:
778         case UGE:
779         case UGT:
780         case EQ:
781         case NE:
782         case LE:
783         case LT:
784         case GE:
785         case GT:
786                 iftrue < 0 ){
787                         o = p->in.op = negrelo-EQ ];
788                         true = false;
789                         false = -1;
790                         }
791 #ifndef NOOPT
792                 ifp->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){
793                         switcho ){
794
795                         case UGT:
796                         case ULE:
797                                 o = p->in.op = (o==UGT)?NE:EQ;
798                         case EQ:
799                         case NE:
800                         case LE:
801                         case LT:
802                         case GE:
803                         case GT:
804                                 iflogop(p->in.left->in.op) ){
805                                         /* strange situation: e.g., (a!=0) == 0 */
806                                         /* must prevent reference to p->in.left->lable, so get 0/1 */
807                                         /* we could optimize, but why bother */
808                                         codgenp->in.leftINAREG|INBREG );
809                                         }
810                                 codgenp->in.leftFORCC );
811                                 cbgenotrue'I' );
812                                 break;
813
814                         case UGE:
815                                 codgen(p->in.leftFORCC);
816                                 cbgen0true'I' );  /* unconditional branch */
817                                 break;
818                         case ULT:
819                                 codgen(p->in.leftFORCC);
820                                 }
821                         }
822                 else
823 #endif
824                         {
825                         p->bn.label = true;
826                         codgenpFORCC );
827                         }
828                 iffalse>=0 ) cbgen0false'I' );
829                 reclaimpRNULL0 );
830                 return;
831
832         case ANDAND:
833                 lab = false<0 ? getlab() : false ;
834                 cbranchp->in.left, -1lab );
835                 cbranchp->in.righttruefalse );
836                 iffalse < 0 ) deflablab );
837                 p->in.op = FREE;
838                 return;
839
840         case OROR:
841                 lab = true<0 ? getlab() : true;
842                 cbranchp->in.leftlab, -1 );
843                 cbranchp->in.righttruefalse );
844                 iftrue < 0 ) deflablab );
845                 p->in.op = FREE;
846                 return;
847
848         case NOT:
849                 cbranchp->in.leftfalsetrue );
850                 p->in.op = FREE;
851                 break;
852
853         case COMOP:
854                 codgenp->in.leftFOREFF );
855                 p->in.op = FREE;
856                 cbranchp->in.righttruefalse );
857                 return;
858
859         case QUEST:
860                 flab = false<0 ? getlab() : false;
861                 tlab = true<0 ? getlab() : true;
862                 cbranchp->in.left, -1lab = getlab() );
863                 cbranchp->in.right->in.lefttlabflab );
864                 deflablab );
865                 cbranchp->in.right->in.righttruefalse );
866                 iftrue < 0 ) deflabtlab);
867                 iffalse < 0 ) deflabflab );
868                 p->in.right->in.op = FREE;
869                 p->in.op = FREE;
870                 return;
871
872         case ICON:
873                 ifp->in.type != FLOAT && p->in.type != DOUBLE ){
874
875                         ifp->tn.lval || p->in.name[0] ){
876                                 /* addresses of C objects are never 0 */
877                                 iftrue>=0 ) cbgen0true'I' );
878                                 }
879                         else iffalse>=0 ) cbgen0false'I' );
880                         p->in.op = FREE;
881                         return;
882                         }
883                 /* fall through to default with other strange constants */
884
885         default:
886                 /* get condition codes */
887                 codgenpFORCC );
888                 iftrue >= 0 ) cbgenNEtrue'I' );
889                 iffalse >= 0 ) cbgentrue >= 0 ? 0 : EQfalse'I' );
890                 reclaimpRNULL0 );
891                 return;
892
893                 }
894
895         }
896
ragge
1.2
897 void
898 rcount()
899 /* count recursions */
ragge
1.1
900         if( ++nrecur > NRECUR ){
901                 cerror"expression causes compiler loop: try simplifying" );
902         }
ragge
1.2
903 }
ragge
1.1
904
905 # ifndef BUG4
ragge
1.2
906 int
ragge
1.8
907 e2print(NODE *pint downint *aint *b)
ragge
1.2
908 {
ragge
1.1
909
910         *a = *b = down+1;
911         whiledown >= 2 ){
912                 printf"\t" );
913                 down -= 2;
914                 }
915         ifdown-- ) printf"    " );
916
917
ragge
1.2
918         printf"%p) %s"popst[p->in.op] );
ragge
1.1
919         switchp->in.op ) { /* special cases */
920
921         case REG:
922                 printf" %s"rnames[p->tn.rval] );
923                 break;
924
925         case ICON:
926         case NAME:
927         case OREG:
928                 printf" " );
929                 adrputp );
930                 break;
931
932         case STCALL:
933         case UNARY STCALL:
934         case STARG:
935         case STASG:
936                 printf" size=%d"p->stn.stsize );
937                 printf" align=%d"p->stn.stalign );
938                 break;
939                 }
940
941         printf", " );
942         tprintp->in.type );
943         printf", " );
944         ifp->in.rall == NOPREF ) printf"NOPREF" );
945         else {
946                 ifp->in.rall & MUSTDO ) printf"MUSTDO " );
947                 else printf"PREF " );
948                 printf"%s"rnames[p->in.rall&~MUSTDO]);
949                 }
950         printf", SU= %d\n"p->in.su );
ragge
1.2
951         return 0;
952 }
ragge
1.1
953 # endif
954
955 #ifndef FIELDOPS
ragge
1.7
956 /*
957  * do this if there is no special hardware support for fields
958  */
959 static int
960 ffld(NODE *pint downint *down1int *down2 )
961 {
962         /*
963          * look for fields that are not in an lvalue context,
964          * and rewrite them...
965          */
966         NODE *shp;
967         int sovty;
ragge
1.1
968
969         *down1 =  asgopp->in.op );
970         *down2 = 0;
971
972         if( !down && p->in.op == FLD ){ /* rewrite the node */
973
ragge
1.7
974                 if( !rewfld(p) ) return 0;
ragge
1.1
975
976                 ty = (szty(p->in.type) == 2)? LONGINT;
977                 v = p->tn.rval;
978                 s = UPKFSZ(v);
979 # ifdef RTOLBYTES
980                 o = UPKFOFF(v);  /* amount to shift */
981 # else
982                 o = szty(p->in.type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
983 #endif
984
985                 /* make & mask part */
986
987                 p->in.left->in.type = ty;
988
989                 p->in.op = AND;
990                 p->in.right = talloc();
991                 p->in.right->in.op = ICON;
992                 p->in.right->in.rall = NOPREF;
993                 p->in.right->in.type = ty;
994                 p->in.right->tn.lval = 1;
995                 p->in.right->tn.rval = 0;
996                 p->in.right->in.name = "";
997                 p->in.right->tn.lval <<= s;
998                 p->in.right->tn.lval--;
999
1000                 /* now, if a shift is needed, do it */
1001
1002                 ifo != 0 ){
1003                         shp = talloc();
1004                         shp->in.op = RS;
1005                         shp->in.rall = NOPREF;
1006                         shp->in.type = ty;
1007                         shp->in.left = p->in.left;
1008                         shp->in.right = talloc();
1009                         shp->in.right->in.op = ICON;
1010                         shp->in.right->in.rall = NOPREF;
1011                         shp->in.right->in.type = ty;
1012                         shp->in.right->tn.rval = 0;
1013                         shp->in.right->tn.lval = o;  /* amount to shift */
1014                         shp->in.right->in.name = "";
1015                         p->in.left = shp;
1016                         /* whew! */
1017                 }
1018         }
ragge
1.7
1019         return 0;
1020 }
ragge
1.1
1021 #endif
1022
ragge
1.2
1023 void
1024 oreg2(NODE *p)
1025 {
ragge
1.1
1026         /* look for situations where we can turn * into OREG */
1027
1028         NODE *q;
ragge
1.2
1029         int r;
1030         char *cp;
1031         NODE *ql, *qr;
ragge
1.1
1032         CONSZ temp;
1033
1034         ifp->in.op == UNARY MUL ){
1035                 q = p->in.left;
1036                 ifq->in.op == REG ){
1037                         temp = q->tn.lval;
1038                         r = q->tn.rval;
1039                         cp = q->in.name;
1040                         goto ormake;
1041                         }
1042
1043                 ifq->in.op != PLUS && q->in.op != MINUS ) return;
1044                 ql = q->in.left;
1045                 qr = q->in.right;
1046
1047 #ifdef R2REGS
1048
1049                 /* look for doubly indexed expressions */
1050
1051                 ifq->in.op == PLUS) {
ragge
1.7
1052                         int i;
ragge
1.1
1053                         if( (r=base(ql))>=0 && (i=offset(qrtlen(p)))>=0) {
1054                                 makeor2(pqlri);
1055                                 return;
1056                         } else if( (r=base(qr))>=0 && (i=offset(qltlen(p)))>=0) {
1057                                 makeor2(pqrri);
1058                                 return;
1059                                 }
1060                         }
1061
1062
1063 #endif
1064
1065                 if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
1066                                 ql->in.op==REG && szty(qr->in.type)==1) {
1067                         temp = qr->tn.lval;
1068                         ifq->in.op == MINUS ) temp = -temp;
1069                         r = ql->tn.rval;
1070                         temp += ql->tn.lval;
1071                         cp = qr->in.name;
1072                         if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return;
1073                         if( !*cp ) cp = ql->in.name;
1074
1075                         ormake:
1076                         ifnotoffp->in.typertempcp ) ) return;
1077                         p->in.op = OREG;
1078                         p->tn.rval = r;
1079                      &nb