Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040510213558

Diff

Diff from 1.91 to:

Annotations

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

Annotated File View

ragge
1.91
1 /*      $Id: reader.c,v 1.91 2004/05/10 21:35:58 ragge Exp $    */
ragge
1.72
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
ragge
1.31
29 /*
30  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  *
36  * Redistributions of source code and documentation must retain the above
37  * copyright notice, this list of conditions and the following disclaimer.
38  * Redistributions in binary form must reproduce the above copyright
39  * notice, this list of conditionsand the following disclaimer in the
40  * documentation and/or other materials provided with the distribution.
41  * All advertising materials mentioning features or use of this software
42  * must display the following acknowledgement:
43  *      This product includes software developed or owned by Caldera
44  *      International, Inc.
45  * Neither the name of Caldera International, Inc. nor the names of other
46  * contributors may be used to endorse or promote products derived from
47  * this software without specific prior written permission.
48  *
49  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
50  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
51  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
54  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
58  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
60  * POSSIBILITY OF SUCH DAMAGE.
61  */
ragge
1.1
62
63 # include "pass2.h"
ragge
1.49
64 #include "external.h"
ragge
1.1
65
ragge
1.70
66 #include <string.h>
ragge
1.71
67 #include <stdarg.h>
ragge
1.70
68
ragge
1.1
69 /*      some storage declarations */
70 int nrecur;
71 int lflag;
ragge
1.9
72 int x2debug;
ragge
1.1
73 int udebug = 0;
ragge
1.32
74 int ftnno;
ragge
1.71
75 static int thisline;
ragge
1.72
76 int fregs;
ragge
1.1
77
ragge
1.72
78 NODE *nodepole;
ragge
1.91
79 int saving;
ragge
1.23
80
ragge
1.10
81 int e2print(NODE *pint downint *aint *b);
ragge
1.37
82 void saveip(struct interpass *ip);
83 void deljumps(void);
ragge
1.40
84 void deltemp(NODE *p);
ragge
1.37
85 void optdump(struct interpass *ip);
ragge
1.40
86 void cvtemps(struct interpass *epil);
ragge
1.69
87 int findops(NODE *pint);
88 int findasg(NODE *pint);
89 int finduni(NODE *pint);
90 int findleaf(NODE *pint);
ragge
1.65
91 int relops(NODE *p);
92 int asgops(NODE *pint);
ragge
1.72
93 NODE *store(NODE *);
ragge
1.65
94
ragge
1.72
95 static void gencode(NODE *pint cookie);
ragge
1.69
96
97 static char *ltyp[] = { """LREG""LOREG""LTEMP" };
98 static char *rtyp[] = { """RREG""ROREG""RTEMP" };
ragge
1.37
99
ragge
1.46
100 #define DELAYS 20
101 NODE *deltrees[DELAYS];
102 int deli;
ragge
1.26
103
104 #ifdef PCC_DEBUG
105 static void
106 cktree(NODE *p)
107 {
108         if (p->n_op > MAXOP)
109                 cerror("op %d slipped through"p->n_op);
ragge
1.35
110         if (p->n_op == CBRANCH && !logop(p->n_left->n_op))
111                 cerror("not logop branch");
ragge
1.47
112         if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
113                 cerror("asgop %d slipped through"p->n_op);
ragge
1.91
114         if (p->n_op ==CALL || p->n_op == ADDROF)
ragge
1.78
115                 cerror("non-UCALL node");
ragge
1.26
116 }
117 #endif
ragge
1.8
118
ragge
1.17
119 static void
ragge
1.2
120 p2compile(NODE *p)
121 {
ragge
1.46
122         int i;
123
ragge
1.15
124 #if !defined(MULTIPASS)
125         extern char *ftitle;
126 #endif
ragge
1.1
127
ragge
1.14
128         if (lflag)
129                 lineid(linenoftitle);
130
ragge
1.1
131         /* generate code for the tree p */
ragge
1.26
132 #ifdef PCC_DEBUG
133         walkf(pcktree);
ragge
1.79
134         if (e2debug) {
135                 fprintf(stderr"Entering pass2\n");
ragge
1.26
136                 fwalk(pe2print0);
ragge
1.79
137         }
ragge
1.26
138 #endif
ragge
1.25
139
ragge
1.1
140 # ifdef MYREADER
141         MYREADER(p);  /* do your own laundering of the input */
142 # endif
143         nrecur = 0;
ragge
1.46
144         deli = 0;
145         delay(p);
ragge
1.25
146         codgen(pFOREFF);
ragge
1.46
147         for (i = 0i < deli; ++i)
148                 codgen(deltrees[i], FOREFF);  /* do the rest */
ragge
1.75
149         tfree(p);
ragge
1.46
150 }
151
152 /* look for delayable ++ and -- operators */
153 void
154 delay(NODE *p)
155 {
156         int ty = optype(p->n_op);
157
158         switch (p->n_op) {
ragge
1.68
159         case UCALL:
ragge
1.46
160         case STCALL:
ragge
1.68
161         case USTCALL:
ragge
1.46
162         case FORTCALL:
ragge
1.68
163         case UFORTCALL:
ragge
1.46
164         case CBRANCH:
165                 /* for the moment, don7t delay past a conditional context, or
166                  * inside of a call */
167                 return;
168
ragge
1.67
169         case UMUL:
ragge
1.46
170                 /* if *p++, do not rewrite */
171                 ifautoincrp ) ) return;
172                 break;
173
174         case INCR:
175         case DECR:
ragge
1.83
176                 break;
ragge
1.46
177                 ifdeltestp ) ){
178                         ifdeli < DELAYS ){
179                                 register NODE *q;
180                                 deltrees[deli++] = tcopy(p);
181                                 q = p->n_left;
ragge
1.58
182                                 nfree(p->n_right); /* zap constant */
ragge
1.46
183                                 *p = *q;
ragge
1.58
184                                 nfree(q);
ragge
1.46
185                                 return;
186                         }
ragge
1.83
187                 }
ragge
1.46
188
ragge
1.83
189         }
ragge
1.46
190
191         if (ty == BITYPE)
192                 delay(p->n_right);
193         if (ty != LTYPE)
194                 delay(p->n_left);
ragge
1.2
195 }
ragge
1.1
196
ragge
1.89
197 /*
198  * Check if a node has side effects.
199  */
200 static int
201 isuseless(NODE *n)
202 {
203         switch (n->n_op) {
204         case FUNARG:
205         case UCALL:
206         case UFORTCALL:
207         case FORCE:
208         case INIT:
209         case ASSIGN:
210         case INCR:
211         case DECR:
212         case CALL:
213         case FORTCALL:
214         case CBRANCH:
215         case RETURN:
216         case GOTO:
217         case STCALL:
218         case USTCALL:
219         case STASG:
220         case STARG:
221                 return 0;
222         default:
223                 return 1;
224         }
225 }
226
227 static NODE *
228 deluseless(NODE *p)
229 {
230         struct interpass *ip;
231         NODE *l, *r;
232
233         if (optype(p->n_op) == LTYPE) {
234                 nfree(p);
235                 return NULL;
236         }
237         if (isuseless(p) == 0)
238                 return p;
239
240         if (optype(p->n_op) == UTYPE) {
241                 l = p->n_left;
242                 nfree(p);
243                 return deluseless(l);
244         }
245
246         /* Be sure that both leaves may be valid */
247         l = deluseless(p->n_left);
248         r = deluseless(p->n_right);
249         nfree(p);
250         if (l && r) {
251                 /* Put left on queue first */
252                 ip = tmpalloc(sizeof(*ip));
253                 ip->type = IP_NODE;
254                 ip->lineno = 0/* XXX */
255                 ip->ip_node = l;
256                 pass2_compile(ip);
257                 return r;
258         } else if (l)
259                 return l;
260         else if (r)
261                 return r;
262         return NULL;
263 }
264
ragge
1.17
265 static void newblock(int myregint aoff);
266 static void epilogue(int regsint autosint retlab);
267
ragge
1.2
268 void
ragge
1.17
269 pass2_compile(struct interpass *ip)
270 {
ragge
1.89
271         if (ip->type == IP_NODE) {
ragge
1.90
272 #ifdef PCC_DEBUG
273                 if (e2debug) {
274                         printf("pass2 called on:\n");
275                         fwalk(ip->ip_nodee2print0);
276                 }
277 #endif
ragge
1.89
278                 ip->ip_node = deluseless(ip->ip_node);
279                 if (ip->ip_node == NULL)
280                         return;
281         }
ragge
1.37
282         if (Oflag) {
283                 if (ip->type == IP_PROLOG)
284                         saving++;
285                 if (saving)
286                         return saveip(ip);
287         }
ragge
1.17
288         switch (ip->type) {
289         case IP_NODE:
ragge
1.71
290                 thisline = ip->lineno;
ragge
1.17
291                 p2compile(ip->ip_node);
ragge
1.21
292                 tfree(ip->ip_node);
ragge
1.17
293                 break;
294         case IP_PROLOG:
295                 prologue(ip->ip_regsip->ip_auto);
296                 break;
297         case IP_NEWBLK:
298                 newblock(ip->ip_regsip->ip_auto);
299                 break;
300         case IP_EPILOG:
301                 epilogue(ip->ip_regsip->ip_autoip->ip_retl);
ragge
1.18
302                 break;
303         case IP_LOCCTR:
304                 setlocc(ip->ip_locc);
305                 break;
306         case IP_DEFLAB:
307                 deflab(ip->ip_lbl);
308                 break;
309         case IP_DEFNAM:
310                 defname(ip->ip_nameip->ip_vis);
ragge
1.39
311                 break;
312         case IP_ASM:
313                 printf("%s\n"ip->ip_asm);
ragge
1.18
314                 break;
ragge
1.17
315         default:
316                 cerror("pass2_compile %d"ip->type);
317         }
318 }
319
320 static void
ragge
1.16
321 newblock(int myregint aoff)
ragge
1.2
322 {
ragge
1.1
323         setregs();
ragge
1.2
324 }
ragge
1.1
325
ragge
1.17
326 static void
ragge
1.16
327 epilogue(int regsint autosint retlab)
ragge
1.2
328 {
ragge
1.16
329         eoftn(regsautosretlab);
ragge
1.2
330 }
ragge
1.1
331
ragge
1.2
332 /*
333  * generate the code for p;
ragge
1.72
334  * store may call codgen recursively
ragge
1.2
335  * cookie is used to describe the context
336  */
337 void
338 codgen(NODE *pint cookie)
339 {
ragge
1.71
340         int o;
ragge
1.70
341
ragge
1.71
342         nodepole = p;
ragge
1.69
343         canon(p);  /* creats OREG from * if possible and does sucomp */
344 #ifdef PCC_DEBUG
345         if (e2debug) {
346                 printf("geninsn called on:\n");
347                 fwalk(pe2print0);
348         }
349 #endif
ragge
1.70
350         do {
351                 geninsn(pcookie); /* Assign instructions for tree */
ragge
1.78
352 #ifdef PCC_DEBUG
353                 if (udebug) {
354                         printf("sucomp called on:\n");
355                         fwalk(pe2print0);
356                 }
357 #endif
ragge
1.72
358         } while (sucomp(p) < 0);  /* Calculate sub-tree evaluation order */
ragge
1.69
359 #ifdef PCC_DEBUG
360         if (udebug) {
361                 printf("genregs called on:\n");
362                 fwalk(pe2print0);
363         }
364 #endif
ragge
1.72
365         /*
366          * When here it is known that the tree can be evaluated.
367          * Assign registers for all instructions.
368          */
ragge
1.69
369         genregs(p); /* allocate registers for instructions */
ragge
1.72
370 #ifdef PCC_DEBUG
371         if (udebug) {
372                 printf("gencode called on:\n");
373                 fwalk(pe2print0);
374         }
375 #endif
ragge
1.71
376         switch (p->n_op) {
377         case CBRANCH:
378                 o = p->n_left->n_op;
ragge
1.72
379                 gencode(pFORCC);
ragge
1.71
380                 cbgen(op->n_right->n_lval);
381                 break;
382         case FORCE:
ragge
1.72
383                 gencode(p->n_leftINTAREG|INTBREG);
ragge
1.71
384                 break;
385         default:
386                 if (p->n_op != REG || p->n_type != VOID/* XXX */
ragge
1.72
387                         gencode(pFOREFF); /* Emit instructions */
ragge
1.71
388         }
ragge
1.2
389 }
ragge
1.1
390
ragge
1.30
391 #ifdef PCC_DEBUG
ragge
1.1
392 char *cnames[] = {
393         "SANY",
394         "SAREG",
395         "STAREG",
396         "SBREG",
397         "STBREG",
398         "SCC",
399         "SNAME",
400         "SCON",
401         "SFLD",
402         "SOREG",
403         "STARNM",
404         "STARREG",
405         "INTEMP",
406         "FORARG",
407         "SWADD",
408         0,
ragge
1.72
409 };
ragge
1.1
410
ragge
1.2
411 /*
412  * print a nice-looking description of cookie
413  */
ragge
1.70
414 char *
ragge
1.2
415 prcook(int cookie)
416 {
ragge
1.70
417         static char buf[50];
ragge
1.1
418         int iflag;
419
ragge
1.70
420         if (cookie & SPECIAL) {
421                 switch (cookie) {
422                 case SZERO:
423                         return "SZERO";
424                 case SONE:
425                         return "SONE";
426                 case SMONE:
427                         return "SMONE";
428                 default:
429                         sprintf(buf"SPECIAL+%d"cookie & ~SPECIAL);
430                         return buf;
ragge
1.1
431                 }
ragge
1.70
432         }
ragge
1.1
433
434         flag = 0;
ragge
1.70
435         buf[0] = 0;
436         for (i = 0cnames[i]; ++i) {
437                 if (cookie & (1<<i)) {
438                         if (flag)
439                                 strcat(buf"|");
ragge
1.1
440                         ++flag;
ragge
1.70
441                         strcat(bufcnames[i]);
ragge
1.1
442                 }
ragge
1.70
443         }
444         return buf;
445 }
ragge
1.1
446
ragge
1.30
447 #endif
ragge
1.1
448
449 int odebug = 0;
450
ragge
1.2
451 void
ragge
1.69
452 geninsn(NODE *pint cookie)
453 {
ragge
1.71
454         NODE *p1, *p2;
ragge
1.69
455         int orv;
456
457 #ifdef PCC_DEBUG
458         if (odebug) {
ragge
1.70
459                 printf("geninsn(%p, %s)\n"pprcook(cookie));
ragge
1.69
460                 fwalk(pe2print0);
461         }
462 #endif
463
464 again:  switch (o = p->n_op) {
ragge
1.71
465         case EQ:
466         case NE:
467         case LE:
468         case LT:
469         case GE:
470         case GT:
471         case ULE:
472         case ULT:
473         case UGE:
474         case UGT:
475                 if ((rv = relops(p)) < 0) {
476                         if (setbin(p))
477                                 goto again;
478                         goto failed;
479                 }
480                 goto sw;
481
ragge
1.69
482         case PLUS:
483         case MINUS:
484         case MUL:
485         case DIV:
486         case MOD:
487         case AND:
488         case OR:
489         case ER:
490         case LS:
491         case RS:
492                 if ((rv = findops(pcookie)) < 0) {
493                         if (setbin(p))
494                                 goto again;
495                         goto failed;
496                 }
ragge
1.71
497                 goto sw;
ragge
1.77
498
499         case INCR:
500         case DECR:
501                 if ((rv = findops(pcookie)) < 0) {
502                         if (setbin(p))
503                                 goto again;
504                 } else
505                         goto sw;
506
507                 /*
508                  * Rewrite x++ to (x = x + 1) -1;
509                  */
510                 p1 = p->n_left;
511                 p->n_op = o == INCR ? MINUS : PLUS;
512                 /* Assign node */
513                 p2 = talloc();
514                 p2->n_type = p->n_type;
515                 p2->n_name = "";
516                 p2->n_op = ASSIGN;
517                 p->n_left = p2;
518                 p->n_left->n_left = p1;
519                 /* incr/decr node */
520                 p2 = talloc();
521                 p2->n_type = p->n_type;
522                 p2->n_name = "";
523                 p2->n_op = o == INCR ? PLUS : MINUS;
524                 p->n_left->n_right = p2;
525                 /* const one node */
526                 p->n_left->n_right->n_right = tcopy(p->n_right);
527                 /* input tree */
528                 p1 = tcopy(p1);
529                 /* idstrip(p1); */
530                 p->n_left->n_right->n_left = p1;
531                 goto again;
ragge
1.71
532
ragge
1.69
533         case ASSIGN:
ragge
1.71
534                 if ((rv = findasg(pcookie)) < 0) {
ragge
1.69
535                         if (setasg(pcookie))
536                                 goto again;
537                         goto failed;
538                 }
539                 /*
540                  * Do subnodes conversions (if needed).
541                  */
ragge
1.71
542 sw:             switch (rv & LMASK) {
ragge
1.69
543                 case LREG:
544                         geninsn(p->n_leftINTAREG|INTBREG);
545                         break;
546                 case LOREG:
547                         offstar(p->n_left->n_left);
548                         p->n_left->n_su = -1;
549                         break;
550                 case LTEMP:
551                         geninsn(p->n_leftINTEMP);
552                         break;
553                 }
554
555                 switch (rv & RMASK) {
556                 case RREG:
557                         geninsn(p->n_rightINTAREG|INTBREG);
558                         break;
559                 case ROREG:
560                         offstar(p->n_right->n_left);
561                         p->n_right->n_su = -1;
562                         break;
563                 case RTEMP:
564                         geninsn(p->n_rightINTEMP);
565                         break;
566                 }
567                 p->n_su = rv;
568                 break;
569
570         case REG:
571                 if (istnode(p))
ragge
1.71
572                         comperr("geninsn REG");
ragge
1.69
573                 /* FALLTHROUGH */
ragge
1.72
574         case NAME:
ragge
1.71
575         case ICON:
ragge
1.69
576         case OREG:
ragge
1.83
577 #if 0
ragge
1.69
578                 if ((cookie & (INTAREG|INTBREG)) == 0)
ragge
1.71
579                         comperr("geninsn OREG, node %p"p);
ragge
1.83
580 #endif
ragge
1.69
581                 if ((rv = findleaf(pcookie)) < 0) {
582                         if (setasg(pcookie))
583                                 goto again;
584                         goto failed;
585                 }
586                 p->n_su = rv;
587                 break;
588
ragge
1.82
589         case UMUL:
590                 /*
591                  * If we end up here with an UMUL, try to fold it into
592                  * an OREG anyway.
593                  */
ragge
1.86
594                 if (p->n_type == STRTY) {
595                         /* XXX - what to do here? */
596                         geninsn(p->n_leftcookie);
597                         p->n_su = -1;
598                         break;
599                 }
600 #if 0
ragge
1.82
601                 if ((cookie & INTAREG) == 0)
602                         comperr("bad umul!");
ragge
1.86
603 #endif
ragge
1.84
604                 if (offstar(p->n_left)) {
605                         p->n_op = OREG;
606                         if ((rv = findleaf(pcookie)) < 0)
607                                 comperr("bad findleaf"); /* XXX */
608                         p->n_op = UMUL;
609                         p->n_su = rv | LOREG;
610                         break;
611                 }
ragge
1.82
612
ragge
1.86
613         case COMPL:
ragge
1.85
614         case UMINUS:
ragge
1.71
615         case PCONV:
616         case SCONV:
617         case INIT:
ragge
1.70
618         case GOTO:
619         case FUNARG:
ragge
1.72
620         case UCALL:
ragge
1.69
621                 if ((rv = finduni(pcookie)) < 0) {
622                         if (setuni(pcookie))
623                                 goto again;
624                         goto failed;
625                 }
626                 switch (rv & LMASK) {
627                 case LREG:
628                         geninsn(p->n_leftINTAREG|INTBREG);
629                         break;
ragge
1.70
630                 case LOREG:
631                         offstar(p->n_left->n_left);
632                         p->n_left->n_su = -1;
633                         break;
634                 case LTEMP:
635                         geninsn(p->n_leftINTEMP);
636                         break;
ragge
1.69
637                 }
638                 p->n_su = rv;
639                 break;
640
ragge
1.71
641         case CBRANCH:
642                 p1 = p->n_left;
643                 p2 = p->n_right;
644                 p1->n_label = p2->n_lval;
645                 o = p1->n_op;
646                 geninsn(p1FORCC);
647                 p->n_su = -1/* su calculations traverse left */
648                 break;
649
650         case FORCE:
651                 geninsn(p->n_leftINTAREG|INTBREG);
652                 p->n_su = -1/* su calculations traverse left */
653                 break;
654
ragge
1.69
655         default:
ragge
1.72
656                 comperr("geninsn: bad op %d, node %p"op);
ragge
1.69
657         }
658         return;
659
660 failed:
ragge
1.84
661         comperr("Cannot generate code, node %p op %s"popst[p->n_op]);
662
ragge
1.69
663 }
664
ragge
1.72
665 /*
666  * Store a given subtree in a temporary location.
667  * Return an OREG node where it is located.
668  */
669 NODE *
670 store(NODE *p)
ragge
1.2
671 {
ragge
1.72
672         NODE *q, *r, *s;
ragge
1.49
673
ragge
1.72
674         q = talloc();
675         r = talloc();
676         s = talloc();
677         q->n_op = OREG;
678         q->n_type = p->n_type;
679         q->n_name = "";
680         q->n_rval = FPREG;
681         q->n_lval = BITOOR(freetemp(szty(p->n_type)));
682         *r = *q;
683         s->n_op = ASSIGN;
684         s->n_type = p->n_type;
685         s->n_name = "";
686         s->n_left = q;
687         s->n_right = p;
688         codgen(sFOREFF);
ragge
1.80
689         tfree(s);
ragge
1.72
690         return r;
ragge
1.8
691 }
ragge
1.1
692
ragge
1.69
693 /*
694  * Count the number of registers needed to evaluate a tree.
695  * This is the trivial implementation, for machines with symmetric
696  * registers. Machines with difficult register assignment strategies
697  * will need to define this function themselves.
698  * Return value is the number of registers used so far.
699  */
700 int
701 sucomp(NODE *p
702 {
703         struct optab *q = &table[TBLIDX(p->n_su)];
704         int leftright;
705         int nreg;
706
707         if (p->n_su == -1)
708                 return sucomp(p->n_left);
709
ragge
1.72
710         if (p->n_op == UCALL) {
ragge
1.78
711                 if ((p->n_su & LMASK) && sucomp(p->n_left) < 0)
ragge
1.72
712                         return -1;
713                 return fregs;
714         }
715
ragge
1.69
716         nreg = (q->needs & NACOUNT) * szty(p->n_type);
717
718         switch (p->n_su & RMASK) {
719         case RREG:
720         case ROREG:
ragge
1.72
721                 if ((right = sucomp(p->n_right)) < 0)
722                         return right;
ragge
1.69
723                 break;
724         case RTEMP:
725                 cerror("sucomp RTEMP");
726         default:
727                 right = 0;
728         }
729         switch (p->n_su & LMASK) {
730         case LREG:
731         case LOREG:
ragge
1.72
732                 if ((left = sucomp(p->n_left)) < 0)
733                         return left;
ragge
1.69
734                 break;
735         case LTEMP:
736                 cerror("sucomp LTEMP");
737         default:
738                 left = 0;
739         }
ragge
1.72
740 //printf("sucomp: node %p right %d left %d\n", p, right, left);
741         if ((p->n_su & RMASK) && (p->n_su & LMASK) &&
742             right + szty(p->n_left->n_type) > fregs &&
743             left + szty(p->n_right->n_type) > fregs) {
744                 /*
745                  * Must store one subtree. Store the tree
746                  * with highest SU, or left.
747                  */
748                 if (right > left)
749                         p->n_right = store(p->n_right);
750                 else
751                         p->n_left = store(p->n_left);
752                 return -1;
753         }
ragge
1.81
754         if ((right+left) > fregs) {
755                 /* Almost out of regs, traverse the highest SU first */
756                 if (right > left)
757                         p->n_su |= DORIGHT;
758         } else if (right && (q->needs & NASL) && (q->rewrite & RLEFT)) {
759                 /* Make it easier to share regs */
ragge
1.69
760                 p->n_su |= DORIGHT;
ragge
1.81
761         } else if (right > left) {
ragge
1.72
762                 p->n_su |= DORIGHT;
ragge
1.81
763         }
ragge
1.88
764         /* If both in regs and equal size, return l+r */
765         if (left && left == right)
766                 left += right/* returned below */
767
ragge
1.69
768         if (right > nreg)
769                 nreg = right;
770         if (left > nreg)
ragge
1.72
771                 nreg = left;
ragge
1.69
772         return nreg;
ragge
1.72
773 }
774
ragge
1.75
775 /*
776  * Rewrite node after instruction emit.
777  */
778 static void
779 rewrite(NODE *pint rewrite)
780 {
ragge
1.79
781         NODE *l, *r;
782         int o;
783
ragge
1.75
784         if (p->n_su == -1)
785                 comperr("rewrite");
786
ragge
1.80
787         l = getlr(p'L');
788         r = getlr(p'R');
ragge
1.79
789         o = p->n_op;
ragge
1.75
790         p->n_op = REG;
ragge
1.76
791         p->n_lval = 0;
ragge
1.79
792         if (rewrite & RLEFT) {
793 #ifdef PCC_DEBUG
794                 if (l->n_op != REG)
795                         comperr("rewrite left");
796 #endif
797                 p->n_rval = l->n_rval;
798         } else if (rewrite & RRIGHT) {
799 #ifdef PCC_DEBUG
800                 if (r->n_op != REG)
801                         comperr("rewrite right");
802 #endif
803                 p->n_rval = r->n_rval;
804         } else if (rewrite & RESC1)
805                 p->n_rval = p->n_rall;
806         else if (rewrite & RESC2)
807                 p->n_rval = p->n_rall + szty(p->n_type);
ragge
1.75
808         else if (rewrite & RESC3)
ragge
1.79
809                 p->n_rval = p->n_rall + 2*szty(p->n_type);
810         if (optype(o) != LTYPE)
811                 tfree(l);
812         if (optype(o) == BITYPE)
813                 tfree(r);
ragge
1.75
814 }
815
ragge
1.69
816 void
ragge
1.72
817 gencode(NODE *pint cookie)
ragge
1.69
818 {
819         struct optab *q = &table[TBLIDX(p->n_su)];
820
821         if (p->n_su == -1/* For OREGs and similar */
ragge
1.72
822                 return gencode(p->n_leftcookie);
ragge
1.69
823
824         if (p->n_su & DORIGHT) {
ragge
1.72
825                 gencode(p->n_rightINTAREG|INTBREG);
ragge
1.69
826                 if ((p->n_su & RMASK) == ROREG)
827                         canon(p);
828         }
829         if (p->n_su & LMASK) {
ragge
1.72
830                 gencode(p->n_leftINTAREG|INTBREG);
ragge
1.69
831                 if ((p->n_su & LMASK) == LOREG)
832                         canon(p);
833         }
834         if ((p->n_su & RMASK) && !(p->n_su & DORIGHT)) {
ragge
1.72
835                 gencode(p->n_rightINTAREG|INTBREG);
ragge
1.69
836                 if ((p->n_su & RMASK) == ROREG)
837                         canon(p);
838         }
ragge
1.72
839         expand(pcookieq->cstring);
ragge
1.75
840         rewrite(pq->rewrite);
ragge
1.2
841 }
ragge
1.1
842
843 int negrel[] = { NEEQGTGELTLEUGTUGEULTULE } ;  /* negatives of relationals */
844
ragge
1.2
845 void
846 rcount()
847 /* count recursions */
ragge
1.1
848         if( ++nrecur > NRECUR ){
849                 cerror"expression causes compiler loop: try simplifying" );
850         }
ragge
1.2
851 }
ragge
1.1
852
ragge
1.30
853 #ifdef PCC_DEBUG
ragge
1.87
854 #undef  PRTABLE
ragge
1.2
855 int
ragge
1.8
856 e2print(NODE *pint downint *aint *b)
ragge
1.2
857 {
ragge
1.85
858 #ifdef PRTABLE
859         extern int tablesize;
860 #endif
ragge
1.1
861
862         *a = *b = down+1;
863         whiledown >= 2 ){
ragge
1.71
864                 fprintf(stderr"\t");
ragge
1.1
865                 down -= 2;
866                 }
ragge
1.71
867         ifdown-- ) fprintf(stderr"    " );
ragge
1.1
868
869
ragge
1.71
870         fprintf(stderr"%p) %s"popst[p->n_op] );
ragge
1.13
871         switchp->n_op ) { /* special cases */
ragge
1.1
872
873         case REG:
ragge
1.71
874                 fprintf(stderr" %s"rnames[p->n_rval] );
ragge
1.1
875                 break;
876
877         case ICON:
878         case NAME:
879         case OREG:
ragge
1.71
880                 fprintf(stderr" " );
881                 adrput(stderrp );
ragge
1.1
882                 break;
883
884         case STCALL:
ragge
1.68
885         case USTCALL:
ragge
1.1
886         case STARG:
887         case STASG:
ragge
1.71
888                 fprintf(stderr" size=%d"p->n_stsize );
889                 fprintf(stderr" align=%d"p->n_stalign );
ragge
1.1
890                 break;
891                 }
892
ragge
1.71
893         fprintf(stderr", " );
894         tprint(stderrp->n_typep->n_qual);
895         fprintf(stderr", " );
896         ifp->n_rall == NOPREF ) fprintf(stderr"NOPREF" );
ragge
1.1
897         else {
ragge
1.71
898                 ifp->n_rall & MUSTDO ) fprintf(stderr"MUSTDO " );
899                 else fprintf(stderr"PREF " );
900                 fprintf(stderr"%s"rnames[p->n_rall&~MUSTDO]);
ragge
1.1
901                 }
ragge
1.85
902         fprintf(stderr", SU= %d(%s,%s,%s,%s)\n",
903             TBLIDX(p->n_su), 
904 #ifdef PRTABLE
905             TBLIDX(p->n_su) >= 0 && TBLIDX(p->n_su) <= tablesize ?
906             table[TBLIDX(p->n_su)].cstring : "",
907 #else
908             "",
909 #endif
910             ltyp[LMASK&p->n_su],
ragge
1.70
911             rtyp[(p->n_su&RMASK) >> 2], p->n_su & DORIGHT ? "DORIGHT" : "");
ragge
1.2
912         return 0;
913 }
ragge
1.30
914 #endif
ragge
1.1
915
916 #ifndef FIELDOPS
ragge
1.7
917 /*
918  * do this if there is no special hardware support for fields
919  */
920 static int
921 ffld(NODE *pint downint *down1int *down2 )
922 {
923         /*
924          * look for fields that are not in an lvalue context,
925          * and rewrite them...
926          */
927         NODE *shp;
928         int sovty;
ragge
1.1
929
ragge
1.13
930         *down1 =  asgopp->n_op );
ragge
1.1
931         *down2 = 0;
932
ragge
1.13
933         if( !down && p->n_op == FLD ){ /* rewrite the node */
ragge
1.1
934
ragge
1.7
935                 if( !rewfld(p) ) return 0;
ragge
1.1
936
ragge
1.48
937                 ty = (szty(p->n_type) == 2)? LONGINT/* XXXX */
ragge
1.13
938                 v = p->n_rval;
ragge
1.1
939                 s = UPKFSZ(v);
940 # ifdef RTOLBYTES
941                 o = UPKFOFF(v);  /* amount to shift */
942 # else
ragge
1.13
943                 o = szty(p->n_type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
ragge
1.1
944 #endif
945
946                 /* make & mask part */
947
ragge
1.13
948                 p->n_left->n_type = ty;
ragge
1.1
949
ragge
1.13
950                 p->n_op = AND;
951                 p->n_right = talloc();
952                 p->n_right->n_op = ICON;
953                 p->n_right->n_rall = NOPREF;
954                 p->n_right->n_type = ty;
955                 p->n_right->n_lval = 1;
956                 p->n_right->n_rval = 0;
957                 p->n_right->n_name = "";
958                 p->n_right->n_lval <<= s;
959