Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040520132618

Diff

Diff from 1.96 to:

Annotations

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

Annotated File View

ragge
1.96
1 /*      $Id: reader.c,v 1.96 2004/05/20 13:26:19 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;
ragge
1.96
505                 } else {
506                         /* Do tree rewriting to ensure correct incr */
507                         if ((rv & LMASK) != LREG)
508                                 goto sw;
509                 }
ragge
1.77
510                 /*
511                  * Rewrite x++ to (x = x + 1) -1;
512                  */
513                 p1 = p->n_left;
514                 p->n_op = o == INCR ? MINUS : PLUS;
515                 /* Assign node */
516                 p2 = talloc();
517                 p2->n_type = p->n_type;
518                 p2->n_name = "";
519                 p2->n_op = ASSIGN;
520                 p->n_left = p2;
521                 p->n_left->n_left = p1;
522                 /* incr/decr node */
523                 p2 = talloc();
524                 p2->n_type = p->n_type;
525                 p2->n_name = "";
526                 p2->n_op = o == INCR ? PLUS : MINUS;
527                 p->n_left->n_right = p2;
528                 /* const one node */
529                 p->n_left->n_right->n_right = tcopy(p->n_right);
530                 /* input tree */
531                 p1 = tcopy(p1);
532                 /* idstrip(p1); */
533                 p->n_left->n_right->n_left = p1;
534                 goto again;
ragge
1.71
535
ragge
1.69
536         case ASSIGN:
ragge
1.71
537                 if ((rv = findasg(pcookie)) < 0) {
ragge
1.69
538                         if (setasg(pcookie))
539                                 goto again;
540                         goto failed;
541                 }
542                 /*
543                  * Do subnodes conversions (if needed).
544                  */
ragge
1.71
545 sw:             switch (rv & LMASK) {
ragge
1.69
546                 case LREG:
547                         geninsn(p->n_leftINTAREG|INTBREG);
548                         break;
549                 case LOREG:
550                         offstar(p->n_left->n_left);
551                         p->n_left->n_su = -1;
552                         break;
553                 case LTEMP:
554                         geninsn(p->n_leftINTEMP);
555                         break;
556                 }
557
558                 switch (rv & RMASK) {
559                 case RREG:
560                         geninsn(p->n_rightINTAREG|INTBREG);
561                         break;
562                 case ROREG:
563                         offstar(p->n_right->n_left);
564                         p->n_right->n_su = -1;
565                         break;
566                 case RTEMP:
567                         geninsn(p->n_rightINTEMP);
568                         break;
569                 }
570                 p->n_su = rv;
571                 break;
572
573         case REG:
574                 if (istnode(p))
ragge
1.71
575                         comperr("geninsn REG");
ragge
1.69
576                 /* FALLTHROUGH */
ragge
1.72
577         case NAME:
ragge
1.71
578         case ICON:
ragge
1.69
579         case OREG:
ragge
1.83
580 #if 0
ragge
1.69
581                 if ((cookie & (INTAREG|INTBREG)) == 0)
ragge
1.71
582                         comperr("geninsn OREG, node %p"p);
ragge
1.83
583 #endif
ragge
1.69
584                 if ((rv = findleaf(pcookie)) < 0) {
585                         if (setasg(pcookie))
586                                 goto again;
587                         goto failed;
588                 }
589                 p->n_su = rv;
590                 break;
591
ragge
1.82
592         case UMUL:
593                 /*
594                  * If we end up here with an UMUL, try to fold it into
595                  * an OREG anyway.
596                  */
ragge
1.86
597                 if (p->n_type == STRTY) {
598                         /* XXX - what to do here? */
599                         geninsn(p->n_leftcookie);
600                         p->n_su = -1;
601                         break;
602                 }
603 #if 0
ragge
1.82
604                 if ((cookie & INTAREG) == 0)
605                         comperr("bad umul!");
ragge
1.86
606 #endif
ragge
1.84
607                 if (offstar(p->n_left)) {
608                         p->n_op = OREG;
609                         if ((rv = findleaf(pcookie)) < 0)
610                                 comperr("bad findleaf"); /* XXX */
611                         p->n_op = UMUL;
612                         p->n_su = rv | LOREG;
613                         break;
614                 }
ragge
1.82
615
ragge
1.86
616         case COMPL:
ragge
1.85
617         case UMINUS:
ragge
1.71
618         case PCONV:
619         case SCONV:
620         case INIT:
ragge
1.70
621         case GOTO:
622         case FUNARG:
ragge
1.72
623         case UCALL:
ragge
1.69
624                 if ((rv = finduni(pcookie)) < 0) {
625                         if (setuni(pcookie))
626                                 goto again;
627                         goto failed;
628                 }
629                 switch (rv & LMASK) {
630                 case LREG:
631                         geninsn(p->n_leftINTAREG|INTBREG);
632                         break;
ragge
1.70
633                 case LOREG:
634                         offstar(p->n_left->n_left);
635                         p->n_left->n_su = -1;
636                         break;
637                 case LTEMP:
638                         geninsn(p->n_leftINTEMP);
639                         break;
ragge
1.69
640                 }
641                 p->n_su = rv;
642                 break;
643
ragge
1.71
644         case CBRANCH:
645                 p1 = p->n_left;
646                 p2 = p->n_right;
647                 p1->n_label = p2->n_lval;
648                 o = p1->n_op;
649                 geninsn(p1FORCC);
650                 p->n_su = -1/* su calculations traverse left */
651                 break;
652
653         case FORCE:
654                 geninsn(p->n_leftINTAREG|INTBREG);
655                 p->n_su = -1/* su calculations traverse left */
656                 break;
657
ragge
1.69
658         default:
ragge
1.72
659                 comperr("geninsn: bad op %d, node %p"op);
ragge
1.69
660         }
661         return;
662
663 failed:
ragge
1.84
664         comperr("Cannot generate code, node %p op %s"popst[p->n_op]);
665
ragge
1.69
666 }
667
ragge
1.72
668 /*
669  * Store a given subtree in a temporary location.
670  * Return an OREG node where it is located.
671  */
672 NODE *
673 store(NODE *p)
ragge
1.2
674 {
ragge
1.72
675         NODE *q, *r, *s;
ragge
1.49
676
ragge
1.72
677         q = talloc();
678         r = talloc();
679         s = talloc();
680         q->n_op = OREG;
681         q->n_type = p->n_type;
682         q->n_name = "";
683         q->n_rval = FPREG;
684         q->n_lval = BITOOR(freetemp(szty(p->n_type)));
685         *r = *q;
686         s->n_op = ASSIGN;
687         s->n_type = p->n_type;
688         s->n_name = "";
689         s->n_left = q;
690         s->n_right = p;
691         codgen(sFOREFF);
ragge
1.80
692         tfree(s);
ragge
1.72
693         return r;
ragge
1.8
694 }
ragge
1.1
695
ragge
1.69
696 /*
697  * Count the number of registers needed to evaluate a tree.
698  * This is the trivial implementation, for machines with symmetric
699  * registers. Machines with difficult register assignment strategies
700  * will need to define this function themselves.
701  * Return value is the number of registers used so far.
702  */
703 int
704 sucomp(NODE *p
705 {
706         struct optab *q = &table[TBLIDX(p->n_su)];
707         int leftright;
708         int nreg;
709
710         if (p->n_su == -1)
711                 return sucomp(p->n_left);
712
ragge
1.72
713         if (p->n_op == UCALL) {
ragge
1.78
714                 if ((p->n_su & LMASK) && sucomp(p->n_left) < 0)
ragge
1.72
715                         return -1;
716                 return fregs;
717         }
718
ragge
1.69
719         nreg = (q->needs & NACOUNT) * szty(p->n_type);
720
721         switch (p->n_su & RMASK) {
722         case RREG:
723         case ROREG:
ragge
1.72
724                 if ((right = sucomp(p->n_right)) < 0)
725                         return right;
ragge
1.69
726                 break;
727         case RTEMP:
728                 cerror("sucomp RTEMP");
729         default:
730                 right = 0;
731         }
732         switch (p->n_su & LMASK) {
733         case LREG:
734         case LOREG:
ragge
1.72
735                 if ((left = sucomp(p->n_left)) < 0)
736                         return left;
ragge
1.69
737                 break;
738         case LTEMP:
739                 cerror("sucomp LTEMP");
740         default:
741                 left = 0;
742         }
ragge
1.72
743 //printf("sucomp: node %p right %d left %d\n", p, right, left);
744         if ((p->n_su & RMASK) && (p->n_su & LMASK) &&
745             right + szty(p->n_left->n_type) > fregs &&
746             left + szty(p->n_right->n_type) > fregs) {
747                 /*
748                  * Must store one subtree. Store the tree
749                  * with highest SU, or left.
750                  */
751                 if (right > left)
752                         p->n_right = store(p->n_right);
753                 else
754                         p->n_left = store(p->n_left);
755                 return -1;
756         }
ragge
1.81
757         if ((right+left) > fregs) {
758                 /* Almost out of regs, traverse the highest SU first */
759                 if (right > left)
760                         p->n_su |= DORIGHT;
761         } else if (right && (q->needs & NASL) && (q->rewrite & RLEFT)) {
762                 /* Make it easier to share regs */
ragge
1.69
763                 p->n_su |= DORIGHT;
ragge
1.81
764         } else if (right > left) {
ragge
1.72
765                 p->n_su |= DORIGHT;
ragge
1.81
766         }
ragge
1.88
767         /* If both in regs and equal size, return l+r */
768         if (left && left == right)
769                 left += right/* returned below */
770
ragge
1.69
771         if (right > nreg)
772                 nreg = right;
773         if (left > nreg)
ragge
1.72
774                 nreg = left;
ragge
1.69
775         return nreg;
ragge
1.72
776 }
777
ragge
1.75
778 /*
779  * Rewrite node after instruction emit.
780  */
781 static void
782 rewrite(NODE *pint rewrite)
783 {
ragge
1.79
784         NODE *l, *r;
785         int o;
786
ragge
1.75
787         if (p->n_su == -1)
788                 comperr("rewrite");
789
ragge
1.80
790         l = getlr(p'L');
791         r = getlr(p'R');
ragge
1.79
792         o = p->n_op;
ragge
1.75
793         p->n_op = REG;
ragge
1.76
794         p->n_lval = 0;
ragge
1.95
795         p->n_name = "";
ragge
1.79
796         if (rewrite & RLEFT) {
797 #ifdef PCC_DEBUG
798                 if (l->n_op != REG)
799                         comperr("rewrite left");
800 #endif
801                 p->n_rval = l->n_rval;
802         } else if (rewrite & RRIGHT) {
803 #ifdef PCC_DEBUG
804                 if (r->n_op != REG)
805                         comperr("rewrite right");
806 #endif
807                 p->n_rval = r->n_rval;
808         } else if (rewrite & RESC1)
809                 p->n_rval = p->n_rall;
810         else if (rewrite & RESC2)
811                 p->n_rval = p->n_rall + szty(p->n_type);
ragge
1.75
812         else if (rewrite & RESC3)
ragge
1.79
813                 p->n_rval = p->n_rall + 2*szty(p->n_type);
814         if (optype(o) != LTYPE)
815                 tfree(l);
816         if (optype(o) == BITYPE)
817                 tfree(r);
ragge
1.75
818 }
819
ragge
1.69
820 void
ragge
1.72
821 gencode(NODE *pint cookie)
ragge
1.69
822 {
823         struct optab *q = &table[TBLIDX(p->n_su)];
824
825         if (p->n_su == -1/* For OREGs and similar */
ragge
1.72
826                 return gencode(p->n_leftcookie);
ragge
1.69
827
828         if (p->n_su & DORIGHT) {
ragge
1.72
829                 gencode(p->n_rightINTAREG|INTBREG);
ragge
1.69
830                 if ((p->n_su & RMASK) == ROREG)
831                         canon(p);
832         }
833         if (p->n_su & LMASK) {
ragge
1.72
834                 gencode(p->n_leftINTAREG|INTBREG);
ragge
1.69
835                 if ((p->n_su & LMASK) == LOREG)
836                         canon(p);
837         }
838         if ((p->n_su & RMASK) && !(p->n_su & DORIGHT)) {
ragge
1.72
839                 gencode(p->n_rightINTAREG|INTBREG);
ragge
1.69
840                 if ((p->n_su & RMASK) == ROREG)
841                         canon(p);
842         }
ragge
1.72
843         expand(pcookieq->cstring);
ragge
1.75
844         rewrite(pq->rewrite);
ragge
1.2
845 }
ragge
1.1
846
847 int negrel[] = { NEEQGTGELTLEUGTUGEULTULE } ;  /* negatives of relationals */
848
ragge
1.2
849 void
850 rcount()
851 /* count recursions */
ragge
1.1
852         if( ++nrecur > NRECUR ){
853                 cerror"expression causes compiler loop: try simplifying" );
854         }
ragge
1.2
855 }
ragge
1.1
856
ragge
1.30
857 #ifdef PCC_DEBUG
ragge
1.87
858 #undef  PRTABLE
ragge
1.2
859 int
ragge
1.8
860 e2print(NODE *pint downint *aint *b)
ragge
1.2
861 {
ragge
1.85
862 #ifdef PRTABLE
863         extern int tablesize;
864 #endif
ragge
1.1
865
866         *a = *b = down+1;
867         whiledown >= 2 ){
ragge
1.71
868                 fprintf(stderr"\t");
ragge
1.1
869                 down -= 2;
870                 }
ragge
1.71
871         ifdown-- ) fprintf(stderr"    " );
ragge
1.1
872
873
ragge
1.71
874         fprintf(stderr"%p) %s"popst[p->n_op] );
ragge
1.13
875         switchp->n_op ) { /* special cases */
ragge
1.1
876
877         case REG:
ragge
1.71
878                 fprintf(stderr" %s"rnames[p->n_rval] );
ragge
1.1
879                 break;
880
881         case ICON:
882         case NAME:
883         case OREG:
ragge
1.71
884                 fprintf(stderr" " );
885                 adrput(stderrp );
ragge
1.1
886                 break;
887
888         case STCALL:
ragge
1.68
889         case USTCALL:
ragge
1.1
890         case STARG:
891         case STASG:
ragge
1.71
892                 fprintf(stderr" size=%d"p->n_stsize );
893                 fprintf(stderr" align=%d"p->n_stalign );
ragge
1.1
894                 break;
895                 }
896
ragge
1.71
897         fprintf(stderr", " );
898         tprint(stderrp->n_typep->n_qual);
899         fprintf(stderr", " );
900         ifp->n_rall == NOPREF ) fprintf(stderr"NOPREF" );
ragge
1.1
901         else {
ragge
1.71
902                 ifp->n_rall & MUSTDO ) fprintf(stderr"MUSTDO " );
903                 else fprintf(stderr"PREF " );
904                 fprintf(stderr"%s"rnames[p->n_rall&~MUSTDO]);
ragge
1.1
905                 }
ragge
1.85
906         fprintf(stderr", SU= %d(%s,%s,%s,%s)\n",
907             TBLIDX(p->n_su), 
908 #ifdef PRTABLE
909             TBLIDX(p->n_su) >= 0 && TBLIDX(p->n_su) <= tablesize ?
910             table[TBLIDX(p->n_su)].cstring : "",
911 #else
912             "",
913 #endif
914             ltyp[LMASK&p->n_su],
ragge
1.70
915             rtyp[(p->n_su&RMASK) >> 2], p->n_su & DORIGHT ? "DORIGHT" : "");
ragge
1.2
916         return 0;
917 }
ragge
1.30
918 #endif
ragge
1.1
919
920 #ifndef FIELDOPS
ragge
1.7
921 /*
922  * do this if there is no special hardware support for fields
923  */
924 static int
925 ffld(NODE *pint downint *down1int *down2 )
926 {
927         /*
928          * look for fields that are not in an lvalue context,
929          * and rewrite them...
930          */
931         NODE *shp;
932         int sovty;
ragge
1.1
933
ragge
1.13
934         *down1 =  asgopp->n_op );
ragge
1.1
935         *down2 = 0;
936
ragge
1.13
937         if( !down && p->n_op == FLD ){ /* rewrite the node */
ragge
1.1
938
ragge
1.7
939                 if( !rewfld(p) ) return 0;
ragge
1.1
940
ragge
1.48
941                 ty = (szty(p->n_type) == 2)? LONGINT/* XXXX */
ragge
1.13
942                 v = p->n_rval;
ragge
1.1
943                 s = UPKFSZ(v);
944 # ifdef RTOLBYTES
945                 o = UPKFOFF(v);  /* amount to shift */
946 # else
ragge
1.13
947                 o = szty(p->n_type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
ragge
1.1
948 #endif
949
950                 /* make & mask part */
951