Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20050627114536

Diff

Diff from 1.134 to:

Annotations

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

Annotated File View

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