Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040526181758

Diff

Diff from 1.98 to:

Annotations

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

Annotated File View

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