Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040529141145

Diff

Diff from 1.100 to:

Annotations

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

Annotated File View

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