Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20051106171516

Diff

Diff from 1.154 to:

Annotations

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

Annotated File View

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