Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030621182813

Diff

Diff from 1.14 to:

Annotations

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

Annotated File View

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