Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040426210530

Diff

Diff from 1.76 to:

Annotations

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

Annotated File View

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