Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20020326195648

Diff

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