Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20021023154656

Diff

Diff from 1.11 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;
ragge
1.9
15 int x2debug;
ragge
1.1
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.10
29 int e2print(NODE *pint downint *aint *b);
ragge
1.8
30
ragge
1.2
31 void
32 p2compile(NODE *p)
33 {
ragge
1.1
34
ragge
1.9
35         iflflag ) lineidlinenoftitle );
ragge
1.1
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:
ragge
1.11
632                 if (asgop(p->in.left->in.op))
633                         stoasg(p->in.leftUNARY MUL);
ragge
1.1
634                 break;
635
636         case CALL:
637         case FORTCALL:
638         case STCALL:
639                 storep->in.left );
640                 stoargp->in.righto );
641                 ++callflag;
642                 return;
643
644         case COMOP:
645                 markcallp->in.right );
646                 ifp->in.right->in.su > fregs ) SETSTOpINTEMP );
647                 storep->in.left );
648                 return;
649
650         case ANDAND:
651         case OROR:
652         case QUEST:
653                 markcallp->in.right );
654                 ifp->in.right->in.su > fregs ) SETSTOpINTEMP );
655         case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
656         case NOT:
657                 constorep->in.left );
658                 return;
659
660                 }
661
ragge
1.11
662         if (ty == UTYPE) {
663                 store(p->in.left);
ragge
1.1
664                 return;
ragge
1.11
665         }
ragge
1.1
666
ragge
1.11
667         if (asgop(p->in.right->in.op))
668                 stoasg(p->in.righto);
ragge
1.1
669
670         ifp->in.su>fregs ){ /* must store */
671                 mkadrsp );  /* set up stotree and stocook to subtree
672                                  that must be stored */
673                 }
674
675         storep->in.right );
676         storep->in.left );
677         }
678
ragge
1.2
679 /*
680  * store conditional expressions
681  * the point is, avoid storing expressions in conditional
682  * conditional context, since the evaluation order is predetermined
683  */
684 void
685 constore(NODE *p)
686 {
ragge
1.1
687         switchp->in.op ) {
688
689         case ANDAND:
690         case OROR:
691         case QUEST:
692                 markcallp->in.right );
693         case NOT:
694                 constorep->in.left );
695                 return;
696
697                 }
698
699         storep );
ragge
1.2
700 }
ragge
1.1
701
ragge
1.2
702 /* mark off calls below the current node */
703 void
704 markcall(NODE *p)
705 {
ragge
1.1
706
707         again:
708         switchp->in.op ){
709
710         case UNARY CALL:
711         case UNARY STCALL:
712         case UNARY FORTCALL:
713         case CALL:
714         case STCALL:
715         case FORTCALL:
716                 ++callflag;
717                 return;
718
719                 }
720
721         switchoptypep->in.op ) ){
722
723         case BITYPE:
724                 markcallp->in.right );
725         case UTYPE:
726                 p = p->in.left;
727                 /* eliminate recursion (aren't I clever...) */
728                 goto again;
729         case LTYPE:
730                 return;
731                 }
732
ragge
1.2
733 }
ragge
1.1
734
ragge
1.2
735 void
736 stoarg(NODE *pint calltype)
737 {
ragge
1.1
738         /* arrange to store the args */
739         ifp->in.op == CM ){
740                 stoargp->in.leftcalltype );
741                 p = p->in.right ;
742                 }
743         ifcalltype == CALL ){
744                 STOARG(p);
745                 }
746         else ifcalltype == STCALL ){
747                 STOSTARG(p);
748                 }
749         else {
750                 STOFARG(p);
751                 }
752         callflag = 0;
753         store(p);
754 # ifndef NESTCALLS
755         ifcallflag ){ /* prevent two calls from being active at once  */
756                 SETSTO(p,INTEMP);
757                 store(p); /* do again to preserve bottom up nature....  */
ragge
1.2
758         }
ragge
1.1
759 #endif
ragge
1.2
760 }
ragge
1.1
761
762 int negrel[] = { NEEQGTGELTLEUGTUGEULTULE } ;  /* negatives of relationals */
763
ragge
1.2
764 /*
765  * evaluate p for truth value, and branch to true or false
766  * accordingly: label <0 means fall through
767  */
768
769 void
770 cbranch(NODE *pint trueint false)
771 {
772         int olabflabtlab;
ragge
1.1
773
774         lab = -1;
775
776         switcho=p->in.op ){
777
778         case ULE:
779         case ULT:
780         case UGE:
781         case UGT:
782         case EQ:
783         case NE:
784         case LE:
785         case LT:
786         case GE:
787         case GT:
788                 iftrue < 0 ){
789                         o = p->in.op = negrelo-EQ ];
790                         true = false;
791                         false = -1;
792                         }
793 #ifndef NOOPT
794                 ifp->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){
795                         switcho ){
796
797                         case UGT:
798                         case ULE:
799                                 o = p->in.op = (o==UGT)?NE:EQ;
800                         case EQ:
801                         case NE:
802                         case LE:
803                         case LT:
804                         case GE:
805                         case GT:
806                                 iflogop(p->in.left->in.op) ){
807                                         /* strange situation: e.g., (a!=0) == 0 */
808                                         /* must prevent reference to p->in.left->lable, so get 0/1 */
809                                         /* we could optimize, but why bother */
810                                         codgenp->in.leftINAREG|INBREG );
811                                         }
812                                 codgenp->in.leftFORCC );
813                                 cbgenotrue'I' );
814                                 break;
815
816                         case UGE:
817                                 codgen(p->in.leftFORCC);
818                                 cbgen0true'I' );  /* unconditional branch */
819                                 break;
820                         case ULT:
821                                 codgen(p->in.leftFORCC);
822                                 }
823                         }
824                 else
825 #endif
826                         {
827                         p->bn.label = true;
828                         codgenpFORCC );
829                         }
830                 iffalse>=0 ) cbgen0false'I' );
831                 reclaimpRNULL0 );
832                 return;
833
834         case ANDAND:
835                 lab = false<0 ? getlab() : false ;
836                 cbranchp->in.left, -1lab );
837                 cbranchp->in.righttruefalse );
838                 iffalse < 0 ) deflablab );
839                 p->in.op = FREE;
840                 return;
841
842         case OROR:
843                 lab = true<0 ? getlab() : true;
844                 cbranchp->in.leftlab, -1 );
845                 cbranchp->in.righttruefalse );
846                 iftrue < 0 ) deflablab );
847                 p->in.op = FREE;
848                 return;
849
850         case NOT:
851                 cbranchp->in.leftfalsetrue );
852                 p->in.op = FREE;
853                 break;
854
855         case COMOP:
856                 codgenp->in.leftFOREFF );
857                 p->in.op = FREE;
858                 cbranchp->in.righttruefalse );
859                 return;
860
861         case QUEST:
862                 flab = false<0 ? getlab() : false;
863                 tlab = true<0 ? getlab() : true;
864                 cbranchp->in.left, -1lab = getlab() );
865                 cbranchp->in.right->in.lefttlabflab );
866                 deflablab );
867                 cbranchp->in.right->in.righttruefalse );
868                 iftrue < 0 ) deflabtlab);
869                 iffalse < 0 ) deflabflab );
870                 p->in.right->in.op = FREE;
871                 p->in.op = FREE;
872                 return;
873
874         case ICON:
875                 ifp->in.type != FLOAT && p->in.type != DOUBLE ){
876
877                         ifp->tn.lval || p->in.name[0] ){
878                                 /* addresses of C objects are never 0 */
879                                 iftrue>=0 ) cbgen0true'I' );
880                                 }
881                         else iffalse>=0 ) cbgen0false'I' );
882                         p->in.op = FREE;
883                         return;
884                         }
885                 /* fall through to default with other strange constants */
886
887         default:
888                 /* get condition codes */
889                 codgenpFORCC );
890                 iftrue >= 0 ) cbgenNEtrue'I' );
891                 iffalse >= 0 ) cbgentrue >= 0 ? 0 : EQfalse'I' );
892                 reclaimpRNULL0 );
893                 return;
894
895                 }
896
897         }
898
ragge
1.2
899 void
900 rcount()
901 /* count recursions */
ragge
1.1
902         if( ++nrecur > NRECUR ){
903                 cerror"expression causes compiler loop: try simplifying" );
904         }
ragge
1.2
905 }
ragge
1.1
906
907 # ifndef BUG4
ragge
1.2
908 int
ragge
1.8
909 e2print(NODE *pint downint *aint *b)
ragge
1.2
910 {
ragge
1.1
911
912         *a = *b = down+1;
913         whiledown >= 2 ){
914                 printf"\t" );
915                 down -= 2;
916                 }
917         ifdown-- ) printf"    " );
918
919
ragge
1.2
920         printf"%p) %s"popst[p->in.op] );
ragge
1.1
921         switchp->in.op ) { /* special cases */
922
923         case REG:
924                 printf" %s"rnames[p->tn.rval] );
925                 break;
926
927         case ICON:
928         case NAME:
929         case OREG:
930                 printf" " );
931                 adrputp );
932                 break;
933
934         case STCALL:
935         case UNARY STCALL:
936         case STARG:
937         case STASG:
938                 printf" size=%d"p->stn.stsize );
939                 printf" align=%d"p->stn.stalign );
940                 break;
941                 }
942
943         printf", " );
944         tprintp->in.type );
945         printf", " );
946         ifp->in.rall == NOPREF ) printf"NOPREF" );
947         else {
948                 ifp->in.rall & MUSTDO ) printf"MUSTDO " );
949                 else printf"PREF " );
950                 printf"%s"rnames[p->in.rall&~MUSTDO]);
951                 }
952         printf", SU= %d\n"p->in.su );
ragge
1.2
953         return 0;
954 }
ragge
1.1
955 # endif
956
957 #ifndef FIELDOPS
ragge
1.7
958 /*
959  * do this if there is no special hardware support for fields
960  */
961 static int
962 ffld(NODE *pint downint *down1int *down2 )
963 {
964         /*
965          * look for fields that are not in an lvalue context,
966          * and rewrite them...
967          */
968         NODE *shp;
969         int sovty;
ragge
1.1
970
971         *down1 =  asgopp->in.op );
972         *down2 = 0;
973
974         if( !down && p->in.op == FLD ){ /* rewrite the node */
975
ragge
1.7
976                 if( !rewfld(p) ) return 0;
ragge
1.1
977
978                 ty = (szty(p->in.type) == 2)? LONGINT;
979                 v = p->tn.rval;
980                 s = UPKFSZ(v);
981 # ifdef RTOLBYTES
982                 o = UPKFOFF(v);  /* amount to shift */
983 # else
984                 o = szty(p->in.type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
985 #endif
986
987                 /* make & mask part */
988
989                 p->in.left->in.type = ty;
990
991                 p->in.op = AND;
992                 p->in.right = talloc();
993                 p->in.right->in.op = ICON;
994                 p->in.right->in.rall = NOPREF;
995                 p->in.right->in.type = ty;
996                 p->in.right->tn.lval = 1;
997                 p->in.right->tn.rval = 0;
998                 p->in.right->in.name = "";
999                 p->in.right->tn.lval <<= s;
1000                 p->in.right->tn.lval--;
1001
1002                 /* now, if a shift is needed, do it */
1003
1004                 ifo != 0 ){
1005                         shp = talloc();
1006                         shp->in.op = RS;
1007                         shp->in.rall = NOPREF;
1008                         shp->in.type = ty;
1009                         shp->in.left = p->in.left;
1010                         shp->in.right = talloc();
1011                         shp->in.right->in.op = ICON;
1012                         shp->in.right->in.rall = NOPREF;
1013                         shp->in.right->in.type = ty;
1014                         shp->in.right->tn.rval = 0;
1015                         shp->in.right->tn.lval = o;  /* amount to shift */
1016                         shp->in.right->in.name = "";
1017                         p->in.left = shp;
1018                         /* whew! */
1019                 }
1020         }
ragge
1.7
1021         return 0;
1022 }
ragge
1.1
1023 #endif
1024
ragge
1.2
1025 void
1026 oreg2(NODE *p)
1027 {
ragge
1.1
1028         /* look for situations where we can turn * into OREG */
1029
1030         NODE *q;
ragge
1.2
1031         int r;
1032         char *cp;
1033         NODE *ql, *qr;
ragge
1.1
1034         CONSZ temp;
1035
1036         ifp->in.op == UNARY MUL ){
1037                 q = p->in.left;
1038                 ifq->in.op == REG ){
1039                         temp = q->tn.lval;
1040                         r = q->tn.rval;
1041                         cp = q->in.name;
1042                         goto ormake;
1043                         }
1044
1045                 ifq->in.op != PLUS && q->in.op != MINUS ) return;
1046                 ql = q->in.left;
1047                 qr = q->in.right;
1048
1049 #ifdef R2REGS
1050
1051                 /* look for doubly indexed expressions */
1052
1053                 ifq->in.op == PLUS) {
ragge
1.7
1054                         int i;
ragge
1.1
1055                         if( (r=base(ql))>=0 && (i=offset(qrtlen(p)))>=0) {
1056                                 makeor2(pqlri);
1057                                 return;
1058                         } else if( (r=base(qr))>=0 && (i=offset(qltlen(p)))>=0) {
1059                                 makeor2(pqrri);
1060                                 return;
1061                                 }
1062                         }
1063
1064
1065 #endif
1066
1067                 if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
1068                                 ql->in.op==REG && szty(qr->in.type)==1) {
1069                         temp = qr->tn.lval;
1070                         ifq->in.op == MINUS ) temp = -temp;
1071                         r = ql->tn.rval;