Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20030909194158

Diff

Diff from 1.63 to:

Annotations

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

Annotated File View

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