Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20050402075617

Diff

Diff from 1.123 to:

Annotations

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

Annotated File View

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