Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20050403145852

Diff

Diff from 1.125 to:

Annotations

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

Annotated File View

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