Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030705090010

Diff

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