Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030729091618

Diff

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