Quick Search:

View

Revision:
Expand:  
Changeset: BSD_44:ragge:20020324105723

Diff

Diff from 1.1.1.1 to:

Annotations

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

Annotated File View

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