Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030825110855

Diff

Diff from 1.48 to:

Annotations

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

Annotated File View

ragge
1.48
1 /*      $Id: reader.c,v 1.48 2003/08/25 11:08:56 ragge Exp $    */
ragge
1.31
2 /*
3  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * Redistributions of source code and documentation must retain the above
10  * copyright notice, this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditionsand the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * All advertising materials mentioning features or use of this software
15  * must display the following acknowledgement:
16  *      This product includes software developed or owned by Caldera
17  *      International, Inc.
18  * Neither the name of Caldera International, Inc. nor the names of other
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
23  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
27  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
ragge
1.1
35
36 # include "pass2.h"
37
38 /*      some storage declarations */
ragge
1.26
39 /*
40  * TODO: re-invent autoincr()/deltest()
41  */
ragge
1.1
42
43 int nrecur;
44 int lflag;
ragge
1.9
45 int x2debug;
ragge
1.1
46 int udebug = 0;
ragge
1.32
47 int ftnno;
ragge
1.1
48
49 NODE *stotree;
50 int stocook;
ragge
1.37
51 static int saving;
ragge
1.1
52
ragge
1.23
53 static struct templst {
54         struct templst *next;
55         int tempnr;
56         int tempoff;
57 } *templst;
58
ragge
1.10
59 int e2print(NODE *pint downint *aint *b);
ragge
1.37
60 void saveip(struct interpass *ip);
61 void deljumps(void);
ragge
1.40
62 void deltemp(NODE *p);
ragge
1.37
63 void optdump(struct interpass *ip);
ragge
1.40
64 void cvtemps(struct interpass *epil);
ragge
1.37
65
ragge
1.46
66 #define DELAYS 20
67 NODE *deltrees[DELAYS];
68 int deli;
ragge
1.26
69
70 #ifdef PCC_DEBUG
71 static void
72 cktree(NODE *p)
73 {
74         if (p->n_op > MAXOP)
75                 cerror("op %d slipped through"p->n_op);
ragge
1.35
76         if (p->n_op == CBRANCH && !logop(p->n_left->n_op))
77                 cerror("not logop branch");
ragge
1.47
78         if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
79                 cerror("asgop %d slipped through"p->n_op);
ragge
1.26
80 }
81 #endif
ragge
1.8
82
ragge
1.17
83 static void
ragge
1.2
84 p2compile(NODE *p)
85 {
ragge
1.46
86         int i;
87
ragge
1.15
88 #if !defined(MULTIPASS)
89         extern char *ftitle;
90 #endif
ragge
1.1
91
ragge
1.14
92         if (lflag)
93                 lineid(linenoftitle);
94
ragge
1.1
95         /* generate code for the tree p */
ragge
1.26
96 #ifdef PCC_DEBUG
97         walkf(pcktree);
98         if (e2debug)
99                 fwalk(pe2print0);
100 #endif
ragge
1.25
101
ragge
1.1
102 # ifdef MYREADER
103         MYREADER(p);  /* do your own laundering of the input */
104 # endif
105         nrecur = 0;
ragge
1.46
106         deli = 0;
107         delay(p);
ragge
1.25
108         codgen(pFOREFF);
ragge
1.46
109         for (i = 0i < deli; ++i)
110                 codgen(deltrees[i], FOREFF);  /* do the rest */
ragge
1.1
111         reclaimpRNULL0 );
112         allchk();
ragge
1.46
113 }
114
115 /* look for delayable ++ and -- operators */
116 void
117 delay(NODE *p)
118 {
119         int ty = optype(p->n_op);
120
121         switch (p->n_op) {
122         case CALL:
123         case UNARY CALL:
124         case STCALL:
125         case UNARY STCALL:
126         case FORTCALL:
127         case UNARY FORTCALL:
128         case CBRANCH:
129                 /* for the moment, don7t delay past a conditional context, or
130                  * inside of a call */
131                 return;
132
133         case UNARY MUL:
134                 /* if *p++, do not rewrite */
135                 ifautoincrp ) ) return;
136                 break;
137
138         case INCR:
139         case DECR:
140                 ifdeltestp ) ){
141                         ifdeli < DELAYS ){
142                                 register NODE *q;
143                                 deltrees[deli++] = tcopy(p);
144                                 q = p->n_left;
145                                 p->n_right->n_op = FREE;  /* zap constant */
146                                 *p = *q;
147                                 q->n_op = FREE;
148                                 return;
149                                 }
150                         }
151
152                 }
153
154         if (ty == BITYPE)
155                 delay(p->n_right);
156         if (ty != LTYPE)
157                 delay(p->n_left);
ragge
1.2
158 }
ragge
1.1
159
ragge
1.17
160 static void newblock(int myregint aoff);
161 static void epilogue(int regsint autosint retlab);
162
ragge
1.2
163 void
ragge
1.17
164 pass2_compile(struct interpass *ip)
165 {
ragge
1.37
166         if (Oflag) {
167                 if (ip->type == IP_PROLOG)
168                         saving++;
169                 if (saving)
170                         return saveip(ip);
171         }
ragge
1.17
172         switch (ip->type) {
173         case IP_NODE:
174                 p2compile(ip->ip_node);
ragge
1.21
175                 tfree(ip->ip_node);
ragge
1.17
176                 break;
177         case IP_PROLOG:
178                 prologue(ip->ip_regsip->ip_auto);
179                 break;
180         case IP_NEWBLK:
181                 newblock(ip->ip_regsip->ip_auto);
182                 break;
183         case IP_EPILOG:
184                 epilogue(ip->ip_regsip->ip_autoip->ip_retl);
ragge
1.18
185                 break;
186         case IP_LOCCTR:
187                 setlocc(ip->ip_locc);
188                 break;
189         case IP_DEFLAB:
190                 deflab(ip->ip_lbl);
191                 break;
192         case IP_DEFNAM:
193                 defname(ip->ip_nameip->ip_vis);
ragge
1.39
194                 break;
195         case IP_ASM:
196                 printf("%s\n"ip->ip_asm);
ragge
1.18
197                 break;
ragge
1.17
198         default:
199                 cerror("pass2_compile %d"ip->type);
200         }
201 }
202
203 static void
ragge
1.16
204 newblock(int myregint aoff)
ragge
1.2
205 {
ragge
1.1
206         setregs();
ragge
1.2
207 }
ragge
1.1
208
ragge
1.17
209 static void
ragge
1.16
210 epilogue(int regsint autosint retlab)
ragge
1.2
211 {
ragge
1.23
212         templst = NULL;
ragge
1.16
213         eoftn(regsautosretlab);
ragge
1.2
214 }
ragge
1.1
215
ragge
1.2
216 /*
217  * generate the code for p;
218  * order may call codgen recursively
219  * cookie is used to describe the context
220  */
221 void
222 codgen(NODE *pint cookie)
223 {
ragge
1.1
224
ragge
1.8
225         for (;;) {
ragge
1.1
226                 canon(p);  /* creats OREG from * if possible and does sucomp */
227                 stotree = NIL;
ragge
1.30
228 #ifdef PCC_DEBUG
ragge
1.8
229                 if (e2debug) {
230                         printf("store called on:\n");
231                         fwalk(pe2print0);
232                 }
ragge
1.30
233 #endif
ragge
1.1
234                 store(p);
235                 ifstotree==NIL ) break;
236
237                 /* because it's minimal, can do w.o. stores */
238
239                 orderstotreestocook );
ragge
1.2
240         }
ragge
1.1
241         orderpcookie );
ragge
1.2
242 }
ragge
1.1
243
ragge
1.30
244 #ifdef PCC_DEBUG
ragge
1.1
245 char *cnames[] = {
246         "SANY",
247         "SAREG",
248         "STAREG",
249         "SBREG",
250         "STBREG",
251         "SCC",
252         "SNAME",
253         "SCON",
254         "SFLD",
255         "SOREG",
256         "STARNM",
257         "STARREG",
258         "INTEMP",
259         "FORARG",
260         "SWADD",
261         0,
262         };
263
ragge
1.2
264 /*
265  * print a nice-looking description of cookie
266  */
267 void
268 prcook(int cookie)
269 {
ragge
1.1
270         int iflag;
271
272         ifcookie & SPECIAL ){
273                 ifcookie == SZERO ) printf"SZERO" );
274                 else ifcookie == SONE ) printf"SONE" );
275                 else ifcookie == SMONE ) printf"SMONE" );
276                 else printf"SPECIAL+%d"cookie & ~SPECIAL );
277                 return;
278                 }
279
280         flag = 0;
281         fori=0cnames[i]; ++i ){
282                 ifcookie & (1<<i) ){
283                         ifflag ) printf"|" );
284                         ++flag;
285                         printfcnames[i] );
286                         }
287                 }
288
ragge
1.2
289 }
ragge
1.30
290 #endif
ragge
1.1
291
292 int odebug = 0;
293
ragge
1.2
294 void
295 order(NODE *pint cook)
296 {
297         int otym;
ragge
1.1
298         int cookie;
ragge
1.2
299         NODE *p1, *p2;
ragge
1.1
300
ragge
1.8
301         /*
302          * by this time, p should be able to be generated without stores;
303          * the only question is how
304          */
ragge
1.1
305         again:
306
307         cookie = cook;
308         rcount();
309         canon(p);
ragge
1.13
310         rallo(pp->n_rall);
ragge
1.1
311
ragge
1.30
312 #ifdef PCC_DEBUG
ragge
1.8
313         if (odebug) {
314                 printf("order(%p, "p);
315                 prcook(cookie);
316                 printf(")\n");
317                 fwalk(pe2print0);
318         }
ragge
1.30
319 #endif
ragge
1.1
320
ragge
1.13
321         o = p->n_op;
ragge
1.1
322         ty = optype(o);
323
324         /* first of all, for most ops, see if it is in the table */
325
326         /* look for ops */
327
ragge
1.13
328         switch (m = p->n_op) {
ragge
1.1
329
ragge
1.48
330         case PLUS:
331                 /*
332                  * Be sure that both sides are addressable.
333                  */
334                 if (!canaddr(p->n_left))
335                         order(p->n_leftINTAREG|INTBREG);
336                 if (!canaddr(p->n_right))
337                         order(p->n_rightINTAREG|INTBREG);
338
339                 /*
340                  * If any of the leaves are already in a temp reg,
341                  * try to add to it.
342                  */
343                 if (istnode(p->n_left))
344                         if ((m = nmatch(pNDLEFT)) == MDONE)
345                                 goto cleanup;
346                 if (istnode(p->n_right))
347                         if ((m = nmatch(pNDRIGHT)) == MDONE)
348                                 goto cleanup;
349
350                 /*
351                  * None of the leaves are in a temp register, try to find
352                  * a matching instruction that ends in a register.
353                  */
354                 if ((m = nmatch(p0)) == MDONE)
355                         goto cleanup;
356                 /*
357                  * Search for a match if any of the leaves are put
358                  * in a register.  Use the dynamic programming 
359                  * algorithm?
360                  * This can be made much more efficient.
361                  */
362                 if (chkmatch(pSTAREG|STBREGSANYNDLEFT) == MDONE) {
363                         /* offstar? */
364                         order(p->n_leftINTAREG|INTBREG); 
365                         goto again;
366                 }
367                 if (chkmatch(pSANYSTAREG|STBREGNDRIGHT) == MDONE) {
368                         /* offstar? */
369                         order(p->n_rightINTAREG|INTBREG); 
370                         goto again;
371                 }
372                 cerror("add failed");
373                 goto nomat;
ragge
1.1
374         default:
ragge
1.47
375 #ifdef notyet
376                 if ((cookie & (INTAREG|INTBREG)) && optype(m) == LTYPE) {
377                         /*
378                          * Search for an ASSIGN op instead of OPLTYPE.
379                          */
380                 }
381 #endif
ragge
1.1
382                 /* look for op in table */
ragge
1.8
383                 for (;;) {
384                         if ((m = match(pcookie)) == MDONE)
385                                 goto cleanup;
386                         else if (m == MNOPE) {
387                                 if (!(cookie = nextcook(pcookie)))
388                                         goto nomat;
ragge
1.1
389                                 continue;
ragge
1.8
390                         } else
391                                 break;
392                 }
ragge
1.1
393                 break;
394
395         case FORCE:
396         case CBRANCH:
397         case UNARY CALL:
398         case CALL:
399         case UNARY STCALL:
400         case STCALL:
401         case UNARY FORTCALL:
402         case FORTCALL:
403                 /* don't even go near the table... */
404                 ;
405
ragge
1.8
406         }
ragge
1.25
407         /*
ragge
1.8
408          * get here to do rewriting if no match or
409          * fall through from above for hard ops
410          */
ragge
1.1
411
ragge
1.13
412         p1 = p->n_left;
ragge
1.8
413         if (ty == BITYPE)
ragge
1.13
414                 p2 = p->n_right;
ragge
1.8
415         else
416                 p2 = NIL;
ragge
1.1
417         
ragge
1.30
418 #ifdef PCC_DEBUG
ragge
1.8
419         if (odebug) {
420                 printf("order(%p, "p);
421                 prcook(cook);
422                 printf("), cookie ");
423                 prcook(cookie);
424                 printf(", rewrite %s\n"opst[m]);
425         }
ragge
1.30
426 #endif
ragge
1.8
427         switch (m) {
ragge
1.1
428         default:
429                 nomat:
ragge
1.13
430                 cerror"no table entry for op %s"opst[p->n_op] );
ragge
1.1
431
432         case FORCE:
433                 cook = INTAREG|INTBREG;
ragge
1.19
434                 order(p->n_leftcook);
435                 reclaim(pRLEFTcook);
ragge
1.38
436                 return;
ragge
1.1
437
438         case CBRANCH:
ragge
1.36
439                 p1->n_label = p2->n_lval;
ragge
1.42
440                 o = p1->n_op;
ragge
1.36
441                 codgen(p1FORCC);
ragge
1.42
442                 cbgen(op2->n_lval);
ragge
1.36
443                 reclaim(p1RNULL0);
ragge
1.19
444                 nfree(p2);
445                 nfree(p);
ragge
1.1
446                 return;
447
448         case FLD:       /* fields of funny type */
ragge
1.13
449                 if ( p1->n_op == UNARY MUL ){
450                         offstarp1->n_left );
ragge
1.1
451                         goto again;
452                         }
453
454         case UNARY MINUS:
ragge
1.30
455                 orderp1INBREG|INAREG);
ragge
1.1
456                 goto again;
457
458         case NAME:
459                 /* all leaves end up here ... */
460                 ifo == REG ) goto nomat;
461                 orderpINTAREG|INTBREG );
462                 goto again;
463
464         case INIT:
ragge
1.12
465                 uerror("init: illegal initialization");
ragge
1.1
466                 return;
467
468         case UNARY FORTCALL:
ragge
1.13
469                 p->n_right = NIL;
ragge
1.1
470         case FORTCALL:
ragge
1.13
471                 o = p->n_op = UNARY FORTCALL;
ragge
1.1
472                 ifgenfcallpcookie ) ) goto nomat;
473                 goto cleanup;
474
475         case UNARY CALL:
ragge
1.13
476                 p->n_right = NIL;
ragge
1.1
477         case CALL:
ragge
1.13
478                 o = p->n_op = UNARY CALL;
ragge
1.1
479                 ifgencallpcookie ) ) goto nomat;
480                 goto cleanup;
481
482         case UNARY STCALL:
ragge
1.13
483                 p->n_right = NIL;
ragge
1.1
484         case STCALL:
ragge
1.13
485                 o = p->n_op = UNARY STCALL;
ragge
1.1
486                 ifgenscallpcookie ) ) goto nomat;
487                 goto cleanup;
488
489                 /* if arguments are passed in register, care must be taken that reclaim
ragge
1.2
490                  * not throw away the register which now has the result... */
ragge
1.1
491
492         case UNARY MUL:
493                 ifcook == FOREFF ){
494                         /* do nothing */
ragge
1.13
495                         orderp->n_leftFOREFF );
ragge
1.19
496                         nfree(p);
ragge
1.1
497                         return;
ragge
1.19
498                 }
ragge
1.30
499                 offstarp->n_left );
500 #if 0
501                 canon(p);
502                 ifcanaddr(p) && cook != INTEMP )
503                         goto cleanup;
ragge
1.1
504 #endif
505                 goto again;
506
507         case INCR:  /* INCR and DECR */
508                 ifsetincr(p) ) goto again;
509
510                 /* x++ becomes (x += 1) -1; */
511
512                 ifcook & FOREFF ){  /* result not needed so inc or dec and be done with it */
513                         /* x++ => x += 1 */
ragge
1.13
514                         p->n_op = (p->n_op==INCR)?ASG PLUS:ASG MINUS;
ragge
1.1
515                         goto again;
516                         }
517
518                 p1 = tcopy(p);
ragge
1.13
519                 reclaimp->n_leftRNULL0 );
520                 p->n_left = p1;
521                 p1->n_op = (p->n_op==INCR)?ASG PLUS:ASG MINUS;
522                 p->n_op = (p->n_op==INCR)?MINUS:PLUS;
ragge
1.1
523                 goto again;
524
525         case STASG:
526                 ifsetstrp ) ) goto again;
527                 goto nomat;
528
529         case ASG PLUS:  /* and other assignment ops */
530                 ifsetasop(p) ) goto again;
531
532                 /* there are assumed to be no side effects in LHS */
533
534                 p2 = tcopy(p);
ragge
1.13
535                 p->n_op = ASSIGN;
536                 reclaimp->n_rightRNULL0 );
537                 p->n_right = p2;
ragge
1.1
538                 canon(p);
ragge
1.13
539                 rallopp->n_rall );
ragge
1.1
540
ragge
1.30
541 #ifdef PCC_DEBUG
ragge
1.8
542                 ifodebug ) fwalkpe2print0 );
ragge
1.30
543 #endif
ragge
1.1
544
ragge
1.13
545                 orderp2->n_leftINTBREG|INTAREG );
ragge
1.1
546                 orderp2INTBREG|INTAREG );
547                 goto again;
548
549         case ASSIGN:
ragge
1.8
550                 if (setasg(p))
551                         goto again;
ragge
1.1
552                 goto nomat;
553
554
555         case BITYPE:
556                 ifsetbinp ) ) goto again;
557                 /* try to replace binary ops by =ops */
558                 switch(o){
559
560                 case PLUS:
561                 case MINUS:
562                 case MUL:
563                 case DIV:
564                 case MOD:
565                 case AND:
566                 case OR:
567                 case ER:
568                 case LS:
569                 case RS:
ragge
1.43
570                         if (!istnode(p->n_left))
571                                 order(p->n_leftINTAREG|INTBREG);
ragge
1.13
572                         p->n_op = ASG o;
ragge
1.1
573                         goto again;
574                         }
575                 goto nomat;
576
577                 }
578
579         cleanup:
580
581         /* if it is not yet in the right state, put it there */
582
583         ifcook & FOREFF ){
584                 reclaimpRNULL0 );
585                 return;
586                 }
587
ragge
1.13
588         ifp->n_op==FREE ) return;
ragge
1.1
589
590         iftshapepcook ) ) return;
591
592         if( (m=match(p,cook) ) == MDONE ) return;
593
594         /* we are in bad shape, try one last chance */
ragge
1.8
595         if (lastchance(pcook))
596                 goto again;
ragge
1.1
597
598         goto nomat;
ragge
1.8
599 }
ragge
1.1
600
601 int callflag;
602 int fregs;
603
ragge
1.2
604 void
605 storep ) NODE *p; {
ragge
1.1
606
607         /* find a subtree of p which should be stored */
608
ragge
1.2
609         int oty;
ragge
1.1
610
ragge
1.13
611         o = p->n_op;
ragge
1.1
612         ty = optype(o);
613
614         ifty == LTYPE ) return;
615
616         switcho ){
617
618         case UNARY CALL:
619         case UNARY FORTCALL:
620         case UNARY STCALL:
621                 ++callflag;
622                 break;
623
624         case UNARY MUL:
ragge
1.13
625                 if (asgop(p->n_left->n_op))
626                         stoasg(p->n_leftUNARY MUL);
ragge
1.1
627                 break;
628
629         case CALL:
630         case FORTCALL:
631         case STCALL:
ragge
1.13
632                 storep->n_left );
633                 stoargp->n_righto );
ragge
1.1
634                 ++callflag;
635                 return;
636
637         case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
ragge
1.13
638                 constorep->n_left );
ragge
1.1
639                 return;
640
641                 }
642
ragge
1.11
643         if (ty == UTYPE) {
ragge
1.13
644                 store(p->n_left);
ragge
1.1
645                 return;
ragge
1.11
646         }
ragge
1.1
647
ragge
1.13
648         if (asgop(p->n_right->n_op))
649                 stoasg(p->n_righto);
ragge
1.1
650
ragge
1.13
651         ifp->n_su>fregs ){ /* must store */
ragge
1.1
652                 mkadrsp );  /* set up stotree and stocook to subtree
653                                  that must be stored */
654                 }
655
ragge
1.13
656         storep->n_right );
657         storep->n_left );
ragge
1.1
658         }
659
ragge
1.2
660 /*
661  * store conditional expressions
662  * the point is, avoid storing expressions in conditional
663  * conditional context, since the evaluation order is predetermined
664  */
665 void
666 constore(NODE *p)
667 {
ragge
1.1
668         storep );
ragge
1.2
669 }
ragge
1.1
670
ragge
1.2
671 /* mark off calls below the current node */
672 void
673 markcall(NODE *p)
674 {
ragge
1.1
675
676         again:
ragge
1.13
677         switchp->n_op ){
ragge
1.1
678
679         case UNARY CALL:
680         case UNARY STCALL:
681         case UNARY FORTCALL:
682         case CALL:
683         case STCALL:
684         case FORTCALL:
685                 ++callflag;
686                 return;
687
688                 }
689
ragge
1.13
690         switchoptypep->n_op ) ){
ragge
1.1
691
692         case BITYPE:
ragge
1.13
693                 markcallp->n_right );
ragge
1.1
694         case UTYPE:
ragge
1.13
695                 p = p->n_left;
ragge
1.1
696                 /* eliminate recursion (aren't I clever...) */
697                 goto again;
698         case LTYPE:
699                 return;
700                 }
701
ragge
1.2
702 }
ragge
1.1
703
ragge
1.2
704 void
705 stoarg(NODE *pint calltype)
706 {
ragge
1.1
707         /* arrange to store the args */
ragge
1.13
708         ifp->n_op == CM ){
709                 stoargp->n_leftcalltype );
710                 p = p->n_right ;
ragge
1.1
711                 }
712         ifcalltype == CALL ){
713                 STOARG(p);
714                 }
715         else ifcalltype == STCALL ){
716                 STOSTARG(p);
717                 }
718         else {
719                 STOFARG(p);
720                 }
721         callflag = 0;
722         store(p);
ragge
1.30
723 #ifdef NO_NESTCALLS
ragge
1.1
724         ifcallflag ){ /* prevent two calls from being active at once  */
725                 SETSTO(p,INTEMP);
726                 store(p); /* do again to preserve bottom up nature....  */
ragge
1.2
727         }
ragge
1.1
728 #endif
ragge
1.2
729 }
ragge
1.1
730
731 int negrel[] = { NEEQGTGELTLEUGTUGEULTULE } ;  /* negatives of relationals */
732
ragge
1.2
733 void
734 rcount()
735 /* count recursions */
ragge
1.1
736         if( ++nrecur > NRECUR ){
737                 cerror"expression causes compiler loop: try simplifying" );
738         }
ragge
1.2
739 }
ragge
1.1
740
ragge
1.30
741 #ifdef PCC_DEBUG
ragge
1.2
742 int
ragge
1.8
743 e2print(NODE *pint downint *aint *b)
ragge
1.2
744 {
ragge
1.1
745
746         *a = *b = down+1;
747         whiledown >= 2 ){
748                 printf"\t" );
749                 down -= 2;
750                 }
751         ifdown-- ) printf"    " );
752
753
ragge
1.13
754         printf"%p) %s"popst[p->n_op] );
755         switchp->n_op ) { /* special cases */
ragge
1.1
756
757         case REG:
ragge
1.13
758                 printf" %s"rnames[p->n_rval] );
ragge
1.1
759                 break;
760
ragge
1.23
761         case TEMP:
762                 printf(" %d", (int)p->n_lval);
763                 break;
764
ragge
1.1
765         case ICON:
766         case NAME:
767         case OREG:
768                 printf" " );
769                 adrputp );
770                 break;
771
772         case STCALL:
773         case UNARY STCALL:
774         case STARG:
775         case STASG:
ragge
1.13
776                 printf" size=%d"p->n_stsize );
777                 printf" align=%d"p->n_stalign );
ragge
1.1
778                 break;
779                 }
780
781         printf", " );
ragge
1.33
782         tprintp->n_typep->n_qual);
ragge
1.1
783         printf", " );
ragge
1.13
784         ifp->n_rall == NOPREF ) printf"NOPREF" );
ragge
1.1
785         else {
ragge
1.13
786                 ifp->n_rall & MUSTDO ) printf"MUSTDO " );
ragge
1.1
787                 else printf"PREF " );
ragge
1.13
788                 printf"%s"rnames[p->n_rall&~MUSTDO]);
ragge
1.1
789                 }
ragge
1.13
790         printf", SU= %d\n"p->n_su );
ragge
1.2
791         return 0;
792 }
ragge
1.30
793 #endif
ragge
1.1
794
795 #ifndef FIELDOPS
ragge
1.7
796 /*
797  * do this if there is no special hardware support for fields
798  */
799 static int
800 ffld(NODE *pint downint *down1int *down2 )
801 {
802         /*
803          * look for fields that are not in an lvalue context,
804          * and rewrite them...
805          */
806         NODE *shp;
807         int sovty;
ragge
1.1
808
ragge
1.13
809         *down1 =  asgopp->n_op );
ragge
1.1
810         *down2 = 0;
811
ragge
1.13
812         if( !down && p->n_op == FLD ){ /* rewrite the node */
ragge
1.1
813
ragge
1.7
814                 if( !rewfld(p) ) return 0;
ragge
1.1
815
ragge
1.48
816                 ty = (szty(p->n_type) == 2)? LONGINT/* XXXX */
ragge
1.13
817                 v = p->n_rval;
ragge
1.1
818                 s = UPKFSZ(v);
819 # ifdef RTOLBYTES
820                 o = UPKFOFF(v);  /* amount to shift */
821 # else
ragge
1.13
822                 o = szty(p->n_type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
ragge
1.1
823 #endif
824
825                 /* make & mask part */
826
ragge
1.13
827                 p->n_left->n_type = ty;
ragge
1.1
828
ragge
1.13
829                 p->n_op = AND;
830                 p->n_right = talloc();
831                 p->n_right->n_op = ICON;
832                 p->n_right->n_rall = NOPREF;
833                 p->n_right->n_type = ty;
834                 p->n_right->n_lval = 1;
835                 p->n_right->n_rval = 0;
836                 p->n_right->n_name = "";
837                 p->n_right->n_lval <<= s;
838                 p->n_right->n_lval--;
ragge
1.1
839
840                 /* now, if a shift is needed, do it */
841
842                 ifo != 0 ){
843                         shp = talloc();
ragge
1.13
844                         shp->n_op = RS;
845                         shp->n_rall = NOPREF;
846                         shp->n_type = ty;
847                         shp->n_left = p->n_left;
848                         shp->n_right = talloc();
849                         shp->n_right->n_op = ICON;
850                         shp->n_right->n_rall = NOPREF;
851                         shp->n_right->n_type = ty;
852                         shp->n_right->n_rval = 0;
853                         shp->n_right->n_lval = o;  /* amount to shift */
854                         shp->n_right->n_name = "";
855                         p->n_left = shp;
ragge
1.1
856                         /* whew! */
857                 }
858         }
ragge
1.7
859         return 0;
860 }
ragge
1.1
861 #endif
862
ragge
1.23
863 /*
864  * change left TEMPs into OREGs
ragge
1.40
865  */
866 void
867 deltemp(NODE *p)
868 {
869         struct templst *w = templst;
870
871         if (p->n_op != TEMP)
872                 return;
873         /*
874          * the size of a TEMP is in multiples of the reg size.
875          */
876         p->n_op = OREG;
877         p->n_rval = FPREG;
878         while (w != NULL) {
879                 if (w->tempnr == p->n_lval)
880                         break;
881                 w = w->next;
882         }
883         if (w == NULL) {
884                 w = tmpalloc(sizeof(struct templst));
885                 w->tempnr = p->n_lval;
886                 w->tempoff = BITOOR(freetemp(szty(p->n_type)));
887                 w->next = templst;
888                 templst = w;
889         }
890         p->n_lval = w->tempoff;
891         p->n_name = "";
892 }
893
894 /*
ragge
1.48
895  * for pointer/integer arithmetic, set pointer at left node
896  */
897 static void
898 setleft(NODE *p)          
899 {        
900         NODE *q;
901
902         /* only additions for now */
903         if (p->n_op != PLUS)
904                 return;
905         if (ISPTR(p->n_right->n_type) && !ISPTR(p->n_left->n_type)) {
906                 q = p->n_right;
907                 p->n_right = p->n_left;
908                 p->n_left = q;
909         }
910 }
911
912 /*
ragge
1.23
913  * look for situations where we can turn * into OREG
914  */
ragge
1.2
915 void
916 oreg2(NODE *p)
917 {
ragge
1.1
918
919         NODE *q;
ragge
1.2
920         int r;
921         char *cp;
922         NODE *ql, *qr;
ragge
1.1
923         CONSZ temp;
ragge
1.23
924
ragge
1.44
925         if (Oflag == 0)
926                 deltemp(p);
ragge
1.1
927
ragge
1.13
928         if (p->n_op == UNARY MUL) {
929                 q = p->n_left;
930                 if (q->n_op == REG) {
931                         temp = q->n_lval;
932                         r = q->n_rval;
933                         cp = q->n_name;
ragge
1.1
934                         goto ormake;
ragge
1.12
935                 }
ragge
1.1
936
ragge
1.13
937                 if (q->n_op != PLUS && q->n_op != MINUS)
ragge
1.12
938                         return;
ragge
1.13
939                 ql = q->n_left;
940                 qr = q->n_right;
ragge
1.1
941
942 #ifdef R2REGS
943
944                 /* look for doubly indexed expressions */
945
ragge
1.13
946                 ifq->n_op == PLUS) {
ragge
1.7
947                         int i;
ragge
1.1
948                         if( (r=base(ql))>=0 && (i=offset(qrtlen(p)))>=0) {
949                                 makeor2(pqlri);
950                                 return;
ragge
1.12
951                         } else if((r=base(qr))>=0 && (i=offset(qltlen(p)))>=0) {
ragge
1.1
952                                 makeor2(pqrri);
953                                 return;
954                         }
ragge
1.12
955                 }
ragge
1.1
956
957
958 #endif
959
ragge
1.13
960                 if( (q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
961                                 ql->n_op==REG && szty(qr->n_type)==1) {
962                         temp = qr->n_lval;
963                         ifq->n_op == MINUS ) temp = -temp;
964                         r = ql->n_rval;
965                         temp += ql->n_lval;
966