Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040429163048

Diff

Diff from 1.78 to:

Annotations

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

Annotated File View

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