Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040518142937

Diff

Diff from 1.95 to:

Annotations

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

Annotated File View

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