Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030531103446

Diff

Diff from 1.13 to:

Annotations

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

Annotated File View

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