Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20050402144817

Diff

Diff from 1.124 to:

Annotations

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

Annotated File View

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