Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040425212417

Diff

Diff from 1.75 to:

Annotations

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

Annotated File View

ragge
1.75
1 /*      $Id: reader.c,v 1.75 2004/04/25 21:24:18 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;
649         if (rewrite & RESC2)
650                 p->n_rval += szty(p->n_type);
651         else if (rewrite & RESC3)
652                 p->n_rval += 2*szty(p->n_type);
653 }
654
ragge
1.69
655 void
ragge
1.72
656 gencode(NODE *pint cookie)
ragge
1.69
657 {
658         struct optab *q = &table[TBLIDX(p->n_su)];
659
660         if (p->n_su == -1/* For OREGs and similar */
ragge
1.72
661                 return gencode(p->n_leftcookie);
ragge
1.69
662
663         if (p->n_su & DORIGHT) {
ragge
1.72
664                 gencode(p->n_rightINTAREG|INTBREG);
ragge
1.69
665                 if ((p->n_su & RMASK) == ROREG)
666                         canon(p);
667         }
668         if (p->n_su & LMASK) {
ragge
1.72
669                 gencode(p->n_leftINTAREG|INTBREG);
ragge
1.69
670                 if ((p->n_su & LMASK) == LOREG)
671                         canon(p);
672         }
673         if ((p->n_su & RMASK) && !(p->n_su & DORIGHT)) {
ragge
1.72
674                 gencode(p->n_rightINTAREG|INTBREG);
ragge
1.69
675                 if ((p->n_su & RMASK) == ROREG)
676                         canon(p);
677         }
ragge
1.72
678         expand(pcookieq->cstring);
ragge
1.75
679         rewrite(pq->rewrite);
ragge
1.2
680 }
ragge
1.1
681
682 int negrel[] = { NEEQGTGELTLEUGTUGEULTULE } ;  /* negatives of relationals */
683
ragge
1.2
684 void
685 rcount()
686 /* count recursions */
ragge
1.1
687         if( ++nrecur > NRECUR ){
688                 cerror"expression causes compiler loop: try simplifying" );
689         }
ragge
1.2
690 }
ragge
1.1
691
ragge
1.30
692 #ifdef PCC_DEBUG
ragge
1.2
693 int
ragge
1.8
694 e2print(NODE *pint downint *aint *b)
ragge
1.2
695 {
ragge
1.1
696
697         *a = *b = down+1;
698         whiledown >= 2 ){
ragge
1.71
699                 fprintf(stderr"\t");
ragge
1.1
700                 down -= 2;
701                 }
ragge
1.71
702         ifdown-- ) fprintf(stderr"    " );
ragge
1.1
703
704
ragge
1.71
705         fprintf(stderr"%p) %s"popst[p->n_op] );
ragge
1.13
706         switchp->n_op ) { /* special cases */
ragge
1.1
707
708         case REG:
ragge
1.71
709                 fprintf(stderr" %s"rnames[p->n_rval] );
ragge
1.1
710                 break;
711
ragge
1.23
712         case TEMP:
ragge
1.71
713                 fprintf(stderr," %d", (int)p->n_lval);
ragge
1.23
714                 break;
715
ragge
1.1
716         case ICON:
717         case NAME:
718         case OREG:
ragge
1.71
719                 fprintf(stderr" " );
720                 adrput(stderrp );
ragge
1.1
721                 break;
722
723         case STCALL:
ragge
1.68
724         case USTCALL:
ragge
1.1
725         case STARG:
726         case STASG:
ragge
1.71
727                 fprintf(stderr" size=%d"p->n_stsize );
728                 fprintf(stderr" align=%d"p->n_stalign );
ragge
1.1
729                 break;
730                 }
731
ragge
1.71
732         fprintf(stderr", " );
733         tprint(stderrp->n_typep->n_qual);
734         fprintf(stderr", " );
735         ifp->n_rall == NOPREF ) fprintf(stderr"NOPREF" );
ragge
1.1
736         else {
ragge
1.71
737                 ifp->n_rall & MUSTDO ) fprintf(stderr"MUSTDO " );
738                 else fprintf(stderr"PREF " );
739                 fprintf(stderr"%s"rnames[p->n_rall&~MUSTDO]);
ragge
1.1
740                 }
ragge
1.71
741         fprintf(stderr", SU= %d(%s,%s,%s)\n",
742             TBLIDX(p->n_su), ltyp[LMASK&p->n_su],
ragge
1.70
743             rtyp[(p->n_su&RMASK) >> 2], p->n_su & DORIGHT ? "DORIGHT" : "");
ragge
1.2
744         return 0;
745 }
ragge
1.30
746 #endif
ragge
1.1
747
748 #ifndef FIELDOPS
ragge
1.7
749 /*
750  * do this if there is no special hardware support for fields
751  */
752 static int
753 ffld(NODE *pint downint *down1int *down2 )
754 {
755         /*
756          * look for fields that are not in an lvalue context,
757          * and rewrite them...
758          */
759         NODE *shp;
760         int sovty;
ragge
1.1
761
ragge
1.13
762         *down1 =  asgopp->n_op );
ragge
1.1
763         *down2 = 0;
764
ragge
1.13
765         if( !down && p->n_op == FLD ){ /* rewrite the node */
ragge
1.1
766
ragge
1.7
767                 if( !rewfld(p) ) return 0;
ragge
1.1
768
ragge
1.48
769                 ty = (szty(p->n_type) == 2)? LONGINT/* XXXX */
ragge
1.13
770                 v = p->n_rval;
ragge
1.1
771                 s = UPKFSZ(v);
772 # ifdef RTOLBYTES
773                 o = UPKFOFF(v);  /* amount to shift */
774 # else
ragge
1.13
775                 o = szty(p->n_type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
ragge
1.1
776 #endif
777
778                 /* make & mask part */
779
ragge
1.13
780                 p->n_left->n_type = ty;
ragge
1.1
781
ragge
1.13
782                 p->n_op = AND;
783                 p->n_right = talloc();
784                 p->n_right->n_op = ICON;
785                 p->n_right->n_rall = NOPREF;
786                 p->n_right->n_type = ty;
787                 p->n_right->n_lval = 1;
788                 p->n_right->n_rval = 0;
789                 p->n_right->n_name = "";
790                 p->n_right->n_lval <<= s;
791                 p->n_right->n_lval--;
ragge
1.1
792
793                 /* now, if a shift is needed, do it */
794
795                 ifo != 0 ){
796                         shp = talloc();
ragge
1.13
797                         shp->n_op = RS;
798                         shp->n_rall = NOPREF;
799                         shp->n_type = ty;
800                         shp->n_left = p->n_left;
801                         shp->n_right = talloc();
802                         shp->n_right->n_op = ICON;
803                         shp->n_right->n_rall = NOPREF;
804                         shp->n_right->n_type = ty;
805                         shp->n_right->n_rval = 0;
806                         shp->n_right->n_lval = o;  /* amount to shift */
807                         shp->n_right->n_name = "";
808                         p->n_left = shp;
ragge
1.1
809                         /* whew! */
810                 }
811         }
ragge
1.7
812         return 0;
813 }
ragge
1.1
814 #endif
815
ragge
1.23
816 /*
817  * change left TEMPs into OREGs
ragge
1.40
818  */
819 void
820 deltemp(NODE *p)
821 {
822         struct templst *w = templst;
823
824         if (p->n_op != TEMP)
825                 return;
826         /*
827          * the size of a TEMP is in multiples of the reg size.
828          */
829         p->n_op = OREG;
830         p->n_rval = FPREG;
831         while (w != NULL) {
832                 if (w->tempnr == p->n_lval)
833                         break;
834                 w = w->next;
835         }
836         if (w == NULL) {
837                 w = tmpalloc(sizeof(struct templst));
838                 w->tempnr = p->n_lval;
839                 w->tempoff = BITOOR(freetemp(szty(p->n_type)));
840                 w->next = templst;
841                 templst = w;
842         }
843         p->n_lval = w->tempoff;
844         p->n_name = "";
845 }
846
847 /*
ragge
1.48
848  * for pointer/integer arithmetic, set pointer at left node
849  */
850 static void
851 setleft(NODE *p)          
852 {        
853         NODE *q;
854
855         /* only additions for now */
856         if (p->n_op != PLUS)
857                 return;
858         if (ISPTR(p->n_right->n_type) && !ISPTR(p->n_left->n_type)) {
859                 q = p->n_right;
860                 p->n_right = p->n_left;
861                 p->n_left = q;
862         }
863 }
864
865 /*
ragge
1.23
866  * look for situations where we can turn * into OREG
867  */
ragge
1.2
868 void
869 oreg2(NODE *p)
870 {
ragge
1.1
871
872         NODE *q;
ragge
1.2
873         int r;
874         char *cp;
875         NODE *ql, *qr;
ragge
1.1
876         CONSZ temp;
ragge
1.23
877
ragge
1.44
878         if (Oflag == 0)
879                 deltemp(p);
ragge
1.1
880
ragge
1.67
881         if (p->n_op == UMUL) {
ragge
1.13
882                 q = p->n_left;
883                 if (q->n_op == REG) {
884                         temp = q->n_lval;
885                         r = q->n_rval;
886                         cp = q->n_name;
ragge
1.1
887                         goto ormake;
ragge
1.12
888                 }
ragge
1.1
889
ragge
1.13
890                 if (q->n_op != PLUS && q->n_op != MINUS)
ragge
1.12
891                         return;
ragge
1.13
892                 ql = q->n_left;
893                 qr = q->n_right;
ragge
1.1
894
895 #ifdef R2REGS
896
897                 /* look for doubly indexed expressions */
898
ragge
1.13
899                 ifq->n_op == PLUS) {
ragge
1.7
900                         int i;
ragge
1.1
901                         if( (r=base(ql))>=0 && (i=offset(qrtlen(p)))>=0) {
902                                 makeor2(pqlri);
903                                 return;
ragge
1.12
904                         } else if((r=base(qr))>=0 && (i=offset(qltlen(p)))>=0) {
ragge
1.1
905                                 makeor2(pqrri);
906                                 return;
907                         }
ragge
1.12
908                 }
ragge
1.1
909
910
911 #endif
912
ragge
1.13
913                 if( (q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
914                                 ql->n_op==REG && szty(qr->n_type)==1) {
915                         temp = qr->n_lval;
916                         ifq->n_op == MINUS ) temp = -temp;
917                         r = ql->n_rval;
918                         temp += ql->n_lval;
919                         cp = qr->n_name;
920                         if( *cp && ( q->n_op == MINUS || *ql->n_name ) ) return;
921                         if( !*cp ) cp = ql->n_name;
ragge
1.1
922
923                         ormake:
ragge
1.13
924                         ifnotoffp->n_typertempcp ) ) return;
925                         p->n_op = OREG;
926                         p->n_rval = r;
927                         p->n_lval = temp;
928                         p->n_name = cp;
ragge
1.1
929                         tfree(q);
930                         return;
931                 }
932         }
ragge
1.12
933 }
ragge
1.1
934
ragge
1.2
935 void
ragge
1.1
936 canon(pNODE *p; {
937         /* put p in canonical form */
938
939 #ifndef FIELDOPS
ragge
1.48
940         fwalk(pffld0);      /* look for field operators */
ragge
1.1
941 # endif
ragge
1.48
942         walkf(psetleft);      /* ptrs at left node for arithmetic */
943         walkf(poreg2);        /* look for and create OREG nodes */
ragge
1.1
944 #ifdef MYCANON
ragge
1.48
945         MYCANON(p);             /* your own canonicalization routine(s) */
ragge
1.1
946 #endif
ragge
1.69
947 #if 0
ragge
1.48
948         walkf(psucomp);       /* do the Sethi-Ullman computation */
ragge
1.69
949 #endif
ragge
1.1
950
ragge
1.2
951 }