Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030623185010

Diff

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