Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040509182657

Diff

Diff from 1.90 to:

Annotations

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

Annotated File View

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