Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20050120212414

Diff

Diff from 1.113 to:

Annotations

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

Annotated File View

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