Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030713123729

Diff

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