Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20020325225236

Diff

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