Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20050521142921

Diff

Diff from 1.127 to:

Annotations

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

Annotated File View

ragge
1.127
1 /*      $Id: reader.c,v 1.127 2005/05/21 14:29:22 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;
ragge
1.127
426         case IPSTK:
427                 break;
ragge
1.124
428         default:
429                 cerror("compile4 %d"ip->type);
430         }
ragge
1.123
431 }
ragge
1.124
432
ragge
1.123
433 #else
434
ragge
1.113
435 #ifdef TAILCALL
436 int earlylabretlab2;
437 char *cftname;
438 #endif
ragge
1.17
439
ragge
1.2
440 void
ragge
1.17
441 pass2_compile(struct interpass *ip)
442 {
pj
1.114
443 #ifdef TAILCALL
ragge
1.113
444         NODE *p;
pj
1.114
445 #endif
ragge
1.113
446
447 #ifdef TAILCALL
448         if (xtailcallflag) {
449                 if (earlylab == -1) {
450                         if (ip->type != IP_DEFLAB)
451                                 comperr("missing deflab");
452                         earlylab = ip->ip_lbl;
453                 } else if (ip->type == IP_PROLOG) {
454                         earlylab = -1;
455                         retlab2 = ip->ip_lbl;
456                         cftname = ((struct interpass_prolog *)ip)->ipp_name;
457                 } else if (ip->type == IP_EPILOG)
458                         earlylab = 0;
459         }
460 #endif
461
ragge
1.89
462         if (ip->type == IP_NODE) {
ragge
1.103
463                 thisline = ip->lineno;
ragge
1.90
464 #ifdef PCC_DEBUG
465                 if (e2debug) {
ragge
1.92
466                         fprintf(stderr"pass2 called on:\n");
ragge
1.90
467                         fwalk(ip->ip_nodee2print0);
468                 }
469 #endif
ragge
1.89
470                 ip->ip_node = deluseless(ip->ip_node);
471                 if (ip->ip_node == NULL)
472                         return;
ragge
1.103
473
ragge
1.105
474 # ifdef MYREADER
475         MYREADER(ip->ip_node);  /* do your own laundering of the input */
476 # endif
ragge
1.113
477
478 #ifdef TAILCALL
479                 /* Check for tail call optimization early */
480                 if (xtailcallflag) {
481                         static struct interpass *ipp;
482                         static int passany;
483
484                         if (passany == 0) {
485                                 p = ip->ip_node;
486                                 if (ipp) {
487                                         if (p->n_op == GOTO &&
488                                             p->n_left->n_lval == retlab2) {
489                                                 passany = 1;
490                                                 mktailopt(ippip);
491                                                 passany = 0;
492                                                 ipp = NULL;
493                                                 return;
494                                         } else {
495                                                 passany = 1;
496                                                 pass2_compile(ipp);
497                                                 passany = 0;
498                                         }
499                                         ipp = NULL;
500                                 } else if (p->n_op == FORCE &&
501                                     callop(p->n_left->n_op)) {
502                                         ipp = ip;
503                                         return;
504                                 }
505                         }
506                 }
507 #endif
508
ragge
1.103
509                 mkhardops(ip->ip_node);
ragge
1.105
510 //printf("gencall...\n");
511 //fwalk(ip->ip_node, e2print, 0);
512                 gencall(ip->ip_nodeNIL);
ragge
1.97
513 #ifdef notyet
514                 optim1(ip->ip_node);
515 #endif
ragge
1.89
516         }
ragge
1.37
517         if (Oflag) {
518                 if (ip->type == IP_PROLOG)
519                         saving++;
520                 if (saving)
521                         return saveip(ip);
522         }
ragge
1.17
523         switch (ip->type) {
524         case IP_NODE:
525                 p2compile(ip->ip_node);
ragge
1.21
526                 tfree(ip->ip_node);
ragge
1.17
527                 break;
528         case IP_PROLOG:
ragge
1.113
529                 prologue((struct interpass_prolog *)ip);
ragge
1.17
530                 break;
531         case IP_EPILOG:
ragge
1.113
532                 eoftn((struct interpass_prolog *)ip);
ragge
1.121
533                 tmpsave = NULL/* Always forget old nodes */
ragge
1.123
534                 p2maxautooff = p2autooff = AUTOINIT;
535                 break;
536         case IP_STKOFF:
537                 p2autooff = ip->ip_off;
538                 if (p2autooff > p2maxautooff)
539                         p2maxautooff = p2autooff;
ragge
1.18
540                 break;
541         case IP_DEFLAB:
542                 deflab(ip->ip_lbl);
543                 break;
ragge
1.39
544         case IP_ASM:
ragge
1.106
545                 printf("\t%s\n"ip->ip_asm);
ragge
1.18
546                 break;
ragge
1.17
547         default:
548                 cerror("pass2_compile %d"ip->type);
549         }
550 }
551
ragge
1.123
552 #endif
553
ragge
1.125
554 #ifndef NEW_READER
ragge
1.2
555 /*
556  * generate the code for p;
ragge
1.72
557  * store may call codgen recursively
ragge
1.2
558  * cookie is used to describe the context
559  */
560 void
561 codgen(NODE *pint cookie)
562 {
ragge
1.71
563         int o;
ragge
1.70
564
ragge
1.104
565         rcount();
ragge
1.71
566         nodepole = p;
ragge
1.122
567         canon(p);  /* creats OREG from * if possible */
ragge
1.69
568 #ifdef PCC_DEBUG
569         if (e2debug) {
ragge
1.92
570                 fprintf(stderr"geninsn called on:\n");
ragge
1.69
571                 fwalk(pe2print0);
572         }
573 #endif
ragge
1.122
574
575 if (xnewreg == 0) {
ragge
1.70
576         do {
577                 geninsn(pcookie); /* Assign instructions for tree */
ragge
1.78
578 #ifdef PCC_DEBUG
579                 if (udebug) {
ragge
1.92
580                         fprintf(stderr"sucomp called on:\n");
ragge
1.78
581                         fwalk(pe2print0);
582                 }
583 #endif
ragge
1.72
584         } while (sucomp(p) < 0);  /* Calculate sub-tree evaluation order */
ragge
1.122
585 else {
586         geninsn(pcookie);     /* Assign instructions for tree */
587 #ifdef PCC_DEBUG
588                 if (udebug) {
589                         fprintf(stderr"nsucomp called on:\n");
590                         fwalk(pe2print0);
591                 }
592 #endif
593         nsucomp(p);             /* Calculate evaluation order */
594 }
595
ragge
1.69
596 #ifdef PCC_DEBUG
597         if (udebug) {
ragge
1.92
598                 fprintf(stderr"genregs called on:\n");
ragge
1.69
599                 fwalk(pe2print0);
600         }
601 #endif
ragge
1.122
602 if (xnewreg == 0) {
ragge
1.72
603         /*
604          * When here it is known that the tree can be evaluated.
605          * Assign registers for all instructions.
606          */
ragge
1.69
607         genregs(p); /* allocate registers for instructions */
ragge
1.103
608         mygenregs(p);
ragge
1.122
609 else {
610         ngenregs(p);
611 }
612
ragge
1.72
613 #ifdef PCC_DEBUG
614         if (udebug) {
ragge
1.92
615                 fprintf(stderr"gencode called on:\n");
ragge
1.72
616                 fwalk(pe2print0);
617         }
618 #endif
ragge
1.71
619         switch (p->n_op) {
620         case CBRANCH:
ragge
1.97
621                 /* Only emit branch insn if RESCC */
622                 if (table[TBLIDX(p->n_left->n_su)].rewrite & RESCC) {
623                         o = p->n_left->n_op;
624                         gencode(pFORCC);
625                         cbgen(op->n_right->n_lval);
626                 } else
627                         gencode(pFORCC);
ragge
1.71
628                 break;
629         case FORCE:
ragge
1.72
630                 gencode(p->n_leftINTAREG|INTBREG);
ragge
1.71
631                 break;
632         default:
633                 if (p->n_op != REG || p->n_type != VOID/* XXX */
ragge
1.72
634                         gencode(pFOREFF); /* Emit instructions */
ragge
1.71
635         }
ragge
1.2
636 }
ragge
1.125
637 #endif
ragge
1.1
638
ragge
1.30
639 #ifdef PCC_DEBUG
ragge
1.1
640 char *cnames[] = {
641         "SANY",
642         "SAREG",
643         "STAREG",
644         "SBREG",
645         "STBREG",
646         "SCC",
647         "SNAME",
648         "SCON",
649         "SFLD",
650         "SOREG",
651         "STARNM",
652         "STARREG",
653         "INTEMP",
654         "FORARG",
655         "SWADD",
656         0,
ragge
1.72
657 };
ragge
1.1
658
ragge
1.2
659 /*
660  * print a nice-looking description of cookie
661  */
ragge
1.70
662 char *
ragge
1.2
663 prcook(int cookie)
664 {
ragge
1.70
665         static char buf[50];
ragge
1.1
666         int iflag;
667
ragge
1.70
668         if (cookie & SPECIAL) {
669                 switch (cookie) {
670                 case SZERO:
671                         return "SZERO";
672                 case SONE:
673                         return "SONE";
674                 case SMONE:
675                         return "SMONE";
676                 default:
677                         sprintf(buf"SPECIAL+%d"cookie & ~SPECIAL);
678                         return buf;
ragge
1.1
679                 }
ragge
1.70
680         }
ragge
1.1
681
682         flag = 0;
ragge
1.70
683         buf[0] = 0;
684         for (i = 0cnames[i]; ++i) {
685                 if (cookie & (1<<i)) {
686                         if (flag)
687                                 strcat(buf"|");
ragge
1.1
688                         ++flag;
ragge
1.70
689                         strcat(bufcnames[i]);
ragge
1.1
690                 }
ragge
1.70
691         }
692         return buf;
693 }
ragge
1.1
694
ragge
1.30
695 #endif
ragge
1.1
696
697 int odebug = 0;
698
ragge
1.2
699 void
ragge
1.69
700 geninsn(NODE *pint cookie)
701 {
ragge
1.71
702         NODE *p1, *p2;
ragge
1.69
703         int orv;
704
705 #ifdef PCC_DEBUG
706         if (odebug) {
ragge
1.70
707                 printf("geninsn(%p, %s)\n"pprcook(cookie));
ragge
1.69
708                 fwalk(pe2print0);
709         }
710 #endif
711
712 again:  switch (o = p->n_op) {
ragge
1.71
713         case EQ:
714         case NE:
715         case LE:
716         case LT:
717         case GE:
718         case GT:
719         case ULE:
720         case ULT:
721         case UGE:
722         case UGT:
723                 if ((rv = relops(p)) < 0) {
724                         if (setbin(p))
725                                 goto again;
726                         goto failed;
727                 }
728                 goto sw;
729
ragge
1.69
730         case PLUS:
731         case MINUS:
732         case MUL:
733         case DIV:
734         case MOD:
735         case AND:
736         case OR:
737         case ER:
738         case LS:
739         case RS:
740                 if ((rv = findops(pcookie)) < 0) {
741                         if (setbin(p))
742                                 goto again;
743                         goto failed;
744                 }
ragge
1.71
745                 goto sw;
ragge
1.77
746
747         case INCR:
748         case DECR:
749                 if ((rv = findops(pcookie)) < 0) {
750                         if (setbin(p))
751                                 goto again;
ragge
1.96
752                 } else {
753                         /* Do tree rewriting to ensure correct incr */
754                         if ((rv & LMASK) != LREG)
755                                 goto sw;
756                 }
ragge
1.77
757                 /*
758                  * Rewrite x++ to (x = x + 1) -1;
759                  */
760                 p1 = p->n_left;
761                 p->n_op = o == INCR ? MINUS : PLUS;
762                 /* Assign node */
763                 p2 = talloc();
764                 p2->n_type = p->n_type;
765                 p2->n_name = "";
766                 p2->n_op = ASSIGN;
767                 p->n_left = p2;
768                 p->n_left->n_left = p1;
769                 /* incr/decr node */
770                 p2 = talloc();
771                 p2->n_type = p->n_type;
772                 p2->n_name = "";
773                 p2->n_op = o == INCR ? PLUS : MINUS;
774                 p->n_left->n_right = p2;
775                 /* const one node */
776                 p->n_left->n_right->n_right = tcopy(p->n_right);
777                 /* input tree */
778                 p1 = tcopy(p1);
779                 /* idstrip(p1); */
780                 p->n_left->n_right->n_left = p1;
ragge
1.108
781                 canon(p); /* if fields involved */
ragge
1.77
782                 goto again;
ragge
1.71
783
ragge
1.69
784         case ASSIGN:
ragge
1.71
785                 if ((rv = findasg(pcookie)) < 0) {
ragge
1.69
786                         if (setasg(pcookie))
787                                 goto again;
788                         goto failed;
789                 }
790                 /*
791                  * Do subnodes conversions (if needed).
792                  */
ragge
1.71
793 sw:             switch (rv & LMASK) {
ragge
1.69
794                 case LREG:
795                         geninsn(p->n_leftINTAREG|INTBREG);
796                         break;
797                 case LOREG:
ragge
1.102
798                         if (p->n_left->n_op == FLD) {
799                                 offstar(p->n_left->n_left->n_left);
800                                 p->n_left->n_left->n_su = -1;
801                         } else
802                                 offstar(p->n_left->n_left);
ragge
1.69
803                         p->n_left->n_su = -1;
804                         break;
805                 case LTEMP:
806                         geninsn(p->n_leftINTEMP);
807                         break;
808                 }
809
810                 switch (rv & RMASK) {
811                 case RREG:
812                         geninsn(p->n_rightINTAREG|INTBREG);
813                         break;
814                 case ROREG:
815                         offstar(p->n_right->n_left);
816                         p->n_right->n_su = -1;
817                         break;
818                 case RTEMP:
819                         geninsn(p->n_rightINTEMP);
820                         break;
821                 }
822                 p->n_su = rv;
823                 break;
824
825         case REG:
826                 if (istnode(p))
ragge
1.71
827                         comperr("geninsn REG");
ragge
1.69
828                 /* FALLTHROUGH */
ragge
1.72
829         case NAME:
ragge
1.71
830         case ICON:
ragge
1.69
831         case OREG:
ragge
1.83
832 #if 0
ragge
1.69
833                 if ((cookie & (INTAREG|INTBREG)) == 0)
ragge
1.71
834                         comperr("geninsn OREG, node %p"p);
ragge
1.83
835 #endif
ragge
1.69
836                 if ((rv = findleaf(pcookie)) < 0) {
837                         if (setasg(pcookie))
838                                 goto again;
839                         goto failed;
840                 }
841                 p->n_su = rv;
842                 break;
843
ragge
1.82
844         case UMUL:
845                 /*
846                  * If we end up here with an UMUL, try to fold it into
847                  * an OREG anyway.
848                  */
ragge
1.86
849                 if (p->n_type == STRTY) {
850                         /* XXX - what to do here? */
851                         geninsn(p->n_leftcookie);
852                         p->n_su = -1;
853                         break;
854                 }
855 #if 0
ragge
1.82
856                 if ((cookie & INTAREG) == 0)
857                         comperr("bad umul!");
ragge
1.86
858 #endif
ragge
1.84
859                 if (offstar(p->n_left)) {
860                         p->n_op = OREG;
861                         if ((rv = findleaf(pcookie)) < 0)
862                                 comperr("bad findleaf"); /* XXX */
863                         p->n_op = UMUL;
864                         p->n_su = rv | LOREG;
865                         break;
866                 }
ragge
1.109
867                 /* FALLTHROUGH */
ragge
1.82
868
ragge
1.86
869         case COMPL:
ragge
1.85
870         case UMINUS:
ragge
1.71
871         case PCONV:
872         case SCONV:
873         case INIT:
ragge
1.70
874         case GOTO:
875         case FUNARG:
ragge
1.72
876         case UCALL:
ragge
1.103
877         case USTCALL:
ragge
1.69
878                 if ((rv = finduni(pcookie)) < 0) {
879                         if (setuni(pcookie))
880                                 goto again;
881                         goto failed;
882                 }
883                 switch (rv & LMASK) {
884                 case LREG:
ragge
1.109
885                         cookie = INTAREG|INTBREG;
886                         if (rv & LBREG/* XXX - make prettier */
887                                 cookie = INTBREG;
888                         geninsn(p->n_leftcookie);
ragge
1.69
889                         break;
ragge
1.70
890                 case LOREG:
891                         offstar(p->n_left->n_left);
892                         p->n_left->n_su = -1;
893                         break;
894                 case LTEMP:
895                         geninsn(p->n_leftINTEMP);
896                         break;
ragge
1.69
897                 }
898                 p->n_su = rv;
899                 break;
900
ragge
1.71
901         case CBRANCH:
902                 p1 = p->n_left;
903                 p2 = p->n_right;
904                 p1->n_label = p2->n_lval;
905                 o = p1->n_op;
906                 geninsn(p1FORCC);
907                 p->n_su = -1/* su calculations traverse left */
908                 break;
909
910         case FORCE:
911                 geninsn(p->n_leftINTAREG|INTBREG);
912                 p->n_su = -1/* su calculations traverse left */
913                 break;
914
ragge
1.69
915         default:
ragge
1.72
916                 comperr("geninsn: bad op %d, node %p"op);
ragge
1.69
917         }
918         return;
919
920 failed:
ragge
1.84
921         comperr("Cannot generate code, node %p op %s"popst[p->n_op]);
922
ragge
1.69
923 }
924
ragge
1.72
925 /*
926  * Store a given subtree in a temporary location.
927  * Return an OREG node where it is located.
928  */
929 NODE *
930 store(NODE *p)
ragge
1.2
931 {
ragge
1.72
932         NODE *q, *r, *s;
ragge
1.49
933
ragge
1.72
934         q = talloc();
935         r = talloc();
936         s = talloc();
937         q->n_op = OREG;
938         q->n_type = p->n_type;
939         q->n_name = "";
940         q->n_rval = FPREG;
941         q->n_lval = BITOOR(freetemp(szty(p->n_type)));
942         *r = *q;
943         s->n_op = ASSIGN;
944         s->n_type = p->n_type;
945         s->n_name = "";
946         s->n_left = q;
947         s->n_right = p;
ragge
1.125
948 #ifdef NEW_READER
949         if (Oflag) {
950                 extern struct interpass *storesave;
951                 storesave = ipnode(s);
952         } else
953                 emit(ipnode(s));
954 #else
ragge
1.72
955         codgen(sFOREFF);
ragge
1.80
956         tfree(s);
ragge
1.125
957 #endif
ragge
1.72
958         return r;
ragge
1.8
959 }
ragge
1.1
960
ragge
1.69
961 /*
ragge
1.75
962  * Rewrite node after instruction emit.
963  */
964 static void
965 rewrite(NODE *pint rewrite)
966 {
ragge
1.79
967         NODE *l, *r;
968         int