Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20031112121311

Diff

Diff from 1.69 to:

Annotations

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

Annotated File View

ragge
1.69
1 /*      $Id: reader.c,v 1.69 2003/11/12 12:13:11 ragge Exp $    */
ragge
1.31
2 /*
3  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * Redistributions of source code and documentation must retain the above
10  * copyright notice, this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditionsand the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * All advertising materials mentioning features or use of this software
15  * must display the following acknowledgement:
16  *      This product includes software developed or owned by Caldera
17  *      International, Inc.
18  * Neither the name of Caldera International, Inc. nor the names of other
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
23  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
27  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
ragge
1.1
35
36 # include "pass2.h"
ragge
1.49
37 #include "external.h"
ragge
1.1
38
39 /*      some storage declarations */
40 int nrecur;
41 int lflag;
ragge
1.9
42 int x2debug;
ragge
1.1
43 int udebug = 0;
ragge
1.32
44 int ftnno;
ragge
1.1
45
46 NODE *stotree;
47 int stocook;
ragge
1.37
48 static int saving;
ragge
1.1
49
ragge
1.23
50 static struct templst {
51         struct templst *next;
52         int tempnr;
53         int tempoff;
54 } *templst;
55
ragge
1.10
56 int e2print(NODE *pint downint *aint *b);
ragge
1.37
57 void saveip(struct interpass *ip);
58 void deljumps(void);
ragge
1.40
59 void deltemp(NODE *p);
ragge
1.37
60 void optdump(struct interpass *ip);
ragge
1.40
61 void cvtemps(struct interpass *epil);
ragge
1.69
62 int findops(NODE *pint);
63 int findasg(NODE *pint);
64 int finduni(NODE *pint);
65 int findleaf(NODE *pint);
ragge
1.65
66 int relops(NODE *p);
67 int asgops(NODE *pint);
68
ragge
1.69
69 static void genregs(NODE *p);
70 static void gencode(NODE *p);
71
72 /*
73  * Layout of findops() return value:
74  *      bit 0-1 where to store left node.
75  *      bit 2-3 where to store right node.
76  *      bit 4   set if right leg should be evaluated first
77  *      bit 5-  table index
78  */
79
80 #define LREG            001
81 #define LOREG           002
82 #define LTEMP           003
83 #define LMASK           003
84 #define RREG            004
85 #define ROREG           010
86 #define RTEMP           014
87 #define RMASK           014
88 #define DORIGHT         020
89 #define TBSH            5
90 #define TBLIDX(idx)     ((idx) >> TBSH)
91 #define MKIDX(tbl,mod)  (((tbl) << TBSH) | (mod))
92
93 static char *ltyp[] = { """LREG""LOREG""LTEMP" };
94 static char *rtyp[] = { """RREG""ROREG""RTEMP" };
ragge
1.37
95
ragge
1.46
96 #define DELAYS 20
97 NODE *deltrees[DELAYS];
98 int deli;
ragge
1.26
99
100 #ifdef PCC_DEBUG
101 static void
102 cktree(NODE *p)
103 {
104         if (p->n_op > MAXOP)
105                 cerror("op %d slipped through"p->n_op);
ragge
1.35
106         if (p->n_op == CBRANCH && !logop(p->n_left->n_op))
107                 cerror("not logop branch");
ragge
1.47
108         if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
109                 cerror("asgop %d slipped through"p->n_op);
ragge
1.26
110 }
111 #endif
ragge
1.8
112
ragge
1.17
113 static void
ragge
1.2
114 p2compile(NODE *p)
115 {
ragge
1.46
116         int i;
117
ragge
1.15
118 #if !defined(MULTIPASS)
119         extern char *ftitle;
120 #endif
ragge
1.1
121
ragge
1.14
122         if (lflag)
123                 lineid(linenoftitle);
124
ragge
1.1
125         /* generate code for the tree p */
ragge
1.26
126 #ifdef PCC_DEBUG
127         walkf(pcktree);
128         if (e2debug)
129                 fwalk(pe2print0);
130 #endif
ragge
1.25
131
ragge
1.1
132 # ifdef MYREADER
133         MYREADER(p);  /* do your own laundering of the input */
134 # endif
135         nrecur = 0;
ragge
1.46
136         deli = 0;
137         delay(p);
ragge
1.25
138         codgen(pFOREFF);
ragge
1.46
139         for (i = 0i < deli; ++i)
140                 codgen(deltrees[i], FOREFF);  /* do the rest */
ragge
1.1
141         reclaimpRNULL0 );
142         allchk();
ragge
1.46
143 }
144
145 /* look for delayable ++ and -- operators */
146 void
147 delay(NODE *p)
148 {
149         int ty = optype(p->n_op);
150
151         switch (p->n_op) {
152         case CALL:
ragge
1.68
153         case UCALL:
ragge
1.46
154         case STCALL:
ragge
1.68
155         case USTCALL:
ragge
1.46
156         case FORTCALL:
ragge
1.68
157         case UFORTCALL:
ragge
1.46
158         case CBRANCH:
159                 /* for the moment, don7t delay past a conditional context, or
160                  * inside of a call */
161                 return;
162
ragge
1.67
163         case UMUL:
ragge
1.46
164                 /* if *p++, do not rewrite */
165                 ifautoincrp ) ) return;
166                 break;
167
168         case INCR:
169         case DECR:
170                 ifdeltestp ) ){
171                         ifdeli < DELAYS ){
172                                 register NODE *q;
173                                 deltrees[deli++] = tcopy(p);
174                                 q = p->n_left;
ragge
1.58
175                                 nfree(p->n_right); /* zap constant */
ragge
1.46
176                                 *p = *q;
ragge
1.58
177                                 nfree(q);
ragge
1.46
178                                 return;
179                                 }
180                         }
181
182                 }
183
184         if (ty == BITYPE)
185                 delay(p->n_right);
186         if (ty != LTYPE)
187                 delay(p->n_left);
ragge
1.2
188 }
ragge
1.1
189
ragge
1.17
190 static void newblock(int myregint aoff);
191 static void epilogue(int regsint autosint retlab);
192
ragge
1.2
193 void
ragge
1.17
194 pass2_compile(struct interpass *ip)
195 {
ragge
1.37
196         if (Oflag) {
197                 if (ip->type == IP_PROLOG)
198                         saving++;
199                 if (saving)
200                         return saveip(ip);
201         }
ragge
1.17
202         switch (ip->type) {
203         case IP_NODE:
204                 p2compile(ip->ip_node);
ragge
1.21
205                 tfree(ip->ip_node);
ragge
1.17
206                 break;
207         case IP_PROLOG:
208                 prologue(ip->ip_regsip->ip_auto);
209                 break;
210         case IP_NEWBLK:
211                 newblock(ip->ip_regsip->ip_auto);
212                 break;
213         case IP_EPILOG:
214                 epilogue(ip->ip_regsip->ip_autoip->ip_retl);
ragge
1.18
215                 break;
216         case IP_LOCCTR:
217                 setlocc(ip->ip_locc);
218                 break;
219         case IP_DEFLAB:
220                 deflab(ip->ip_lbl);
221                 break;
222         case IP_DEFNAM:
223                 defname(ip->ip_nameip->ip_vis);
ragge
1.39
224                 break;
225         case IP_ASM:
226                 printf("%s\n"ip->ip_asm);
ragge
1.18
227                 break;
ragge
1.17
228         default:
229                 cerror("pass2_compile %d"ip->type);
230         }
231 }
232
233 static void
ragge
1.16
234 newblock(int myregint aoff)
ragge
1.2
235 {
ragge
1.1
236         setregs();
ragge
1.2
237 }
ragge
1.1
238
ragge
1.17
239 static void
ragge
1.16
240 epilogue(int regsint autosint retlab)
ragge
1.2
241 {
ragge
1.23
242         templst = NULL;
ragge
1.16
243         eoftn(regsautosretlab);
ragge
1.2
244 }
ragge
1.1
245
ragge
1.2
246 /*
247  * generate the code for p;
248  * order may call codgen recursively
249  * cookie is used to describe the context
250  */
251 void
252 codgen(NODE *pint cookie)
253 {
ragge
1.69
254         canon(p);  /* creats OREG from * if possible and does sucomp */
255 #ifdef PCC_DEBUG
256         if (e2debug) {
257                 printf("geninsn called on:\n");
258                 fwalk(pe2print0);
259         }
260 #endif
ragge
1.1
261
ragge
1.69
262         geninsn(pcookie); /* Assign instructions for tree */
263         sucomp(p);  /* Calculate sub-tree evaluation order */
264 #ifdef PCC_DEBUG
265         if (udebug) {
266                 printf("genregs called on:\n");
267                 fwalk(pe2print0);
268         }
269 #endif
270         genregs(p); /* allocate registers for instructions */
271         gencode(p); /* Emit instructions */
272 #if 0
ragge
1.8
273         for (;;) {
ragge
1.1
274                 canon(p);  /* creats OREG from * if possible and does sucomp */
275                 stotree = NIL;
ragge
1.30
276 #ifdef PCC_DEBUG
ragge
1.8
277                 if (e2debug) {
278                         printf("store called on:\n");
279                         fwalk(pe2print0);
280                 }
ragge
1.30
281 #endif
ragge
1.1
282                 store(p);
283                 ifstotree==NIL ) break;
284
285                 /* because it's minimal, can do w.o. stores */
286
287                 orderstotreestocook );
ragge
1.2
288         }
ragge
1.1
289         orderpcookie );
ragge
1.69
290 #endif
ragge
1.2
291 }
ragge
1.1
292
ragge
1.30
293 #ifdef PCC_DEBUG
ragge
1.1
294 char *cnames[] = {
295         "SANY",
296         "SAREG",
297         "STAREG",
298         "SBREG",
299         "STBREG",
300         "SCC",
301         "SNAME",
302         "SCON",
303         "SFLD",
304         "SOREG",
305         "STARNM",
306         "STARREG",
307         "INTEMP",
308         "FORARG",
309         "SWADD",
310         0,
311         };
312
ragge
1.2
313 /*
314  * print a nice-looking description of cookie
315  */
316 void
317 prcook(int cookie)
318 {
ragge
1.1
319         int iflag;
320
321         ifcookie & SPECIAL ){
322                 ifcookie == SZERO ) printf"SZERO" );
323                 else ifcookie == SONE ) printf"SONE" );
324                 else ifcookie == SMONE ) printf"SMONE" );
325                 else printf"SPECIAL+%d"cookie & ~SPECIAL );
326                 return;
327                 }
328
329         flag = 0;
330         fori=0cnames[i]; ++i ){
331                 ifcookie & (1<<i) ){
332                         ifflag ) printf"|" );
333                         ++flag;
334                         printfcnames[i] );
335                         }
336                 }
337
ragge
1.2
338 }
ragge
1.30
339 #endif
ragge
1.1
340
341 int odebug = 0;
342
ragge
1.2
343 void
ragge
1.69
344 geninsn(NODE *pint cookie)
345 {
346         int orv;
347
348 #ifdef PCC_DEBUG
349         if (odebug) {
350                 printf("geninsn(%p, "p);
351                 prcook(cookie);
352                 printf(")\n");
353                 fwalk(pe2print0);
354         }
355 #endif
356
357 again:  switch (o = p->n_op) {
358         case PLUS:
359         case MINUS:
360         case MUL:
361         case DIV:
362         case MOD:
363         case AND:
364         case OR:
365         case ER:
366         case LS:
367         case RS:
368                 if ((rv = findops(pcookie)) < 0) {
369                         if (setbin(p))
370                                 goto again;
371                         goto failed;
372                 }
373         case ASSIGN:
374                 if (o == ASSIGN)
375                     if ((rv = findasg(pcookie)) < 0) {
376                         if (setasg(pcookie))
377                                 goto again;
378                         goto failed;
379                 }
380                 /*
381                  * Do subnodes conversions (if needed).
382                  */
383                 switch (rv & LMASK) {
384                 case LREG:
385                         geninsn(p->n_leftINTAREG|INTBREG);
386                         break;
387                 case LOREG:
388                         offstar(p->n_left->n_left);
389                         p->n_left->n_su = -1;
390                         break;
391                 case LTEMP:
392                         geninsn(p->n_leftINTEMP);
393                         break;
394                 }
395
396                 switch (rv & RMASK) {
397                 case RREG:
398                         geninsn(p->n_rightINTAREG|INTBREG);
399                         break;
400                 case ROREG:
401                         offstar(p->n_right->n_left);
402                         p->n_right->n_su = -1;
403                         break;
404                 case RTEMP:
405                         geninsn(p->n_rightINTEMP);
406                         break;
407                 }
408                 p->n_su = rv;
409                 break;
410
411         case REG:
412                 if (istnode(p))
413                         cerror("geninsn REG");
414                 /* FALLTHROUGH */
415         case OREG:
416                 if ((cookie & (INTAREG|INTBREG)) == 0)
417                         cerror("geninsn OREG");
418                 if ((rv = findleaf(pcookie)) < 0) {
419                         if (setasg(pcookie))
420                                 goto again;
421                         goto failed;
422                 }
423                 p->n_su = rv;
424                 break;
425
426         case UMUL:
427                 if ((rv = finduni(pcookie)) < 0) {
428                         if (setuni(pcookie))
429                                 goto again;
430                         goto failed;
431                 }
432                 switch (rv & LMASK) {
433                 case LREG:
434                         geninsn(p->n_leftINTAREG|INTBREG);
435                         break;
436                 }
437                 p->n_su = rv;
438                 break;
439
440         default:
441                 cerror("geninsn: bad op %d"o);
442         }
443         return;
444
445 failed:
446 #ifdef PCC_DEBUG
447         fwalk(pe2print0);
448 #endif
449         cerror("Cannot generate code for op %d\n"o);
450 }
451
452 void
ragge
1.2
453 order(NODE *pint cook)
454 {
ragge
1.69
455 //      struct optab *q;
ragge
1.57
456         int otymrv;
ragge
1.1
457         int cookie;
ragge
1.2
458         NODE *p1, *p2;
ragge
1.1
459
ragge
1.8
460         /*
461          * by this time, p should be able to be generated without stores;
462          * the only question is how
463          */
ragge
1.1
464         again:
465
466         cookie = cook;
467         rcount();
468         canon(p);
ragge
1.13
469         rallo(pp->n_rall);
ragge
1.1
470
ragge
1.30
471 #ifdef PCC_DEBUG
ragge
1.8
472         if (odebug) {
473                 printf("order(%p, "p);
474                 prcook(cookie);
475                 printf(")\n");
476                 fwalk(pe2print0);
477         }
ragge
1.30
478 #endif
ragge
1.1
479
ragge
1.13
480         o = p->n_op;
ragge
1.1
481         ty = optype(o);
482
483         /* first of all, for most ops, see if it is in the table */
484
485         /* look for ops */
486
ragge
1.13
487         switch (m = p->n_op) {
ragge
1.1
488
ragge
1.65
489 #if 0
ragge
1.63
490         case ASSIGN:
491                 /*
492                  * For ASSIGN the left node must be directly addressable,
493                  * the right can be put into a register.
494                  * XXX - Will not try to match any smart instructions yet.
495                  */
ragge
1.64
496 //printf("foo\n");
497 //fwalk(p, e2print, 0);
ragge
1.63
498                 if (!canaddr(p->n_left)) {
ragge
1.67
499                         if (p->n_left->n_op == UMUL) {
ragge
1.63
500                                 offstar(p->n_left->n_left);
501                                 goto again;
502                         }
503                         cerror("bad assign lvalue");
504                 }
ragge
1.64
505 //printf("foo1\n");
506 //fwalk(p, e2print, 0);
ragge
1.63
507                 if (!canaddr(p->n_right)) {
ragge
1.67
508                         if (p->n_right->n_op == UMUL) {
ragge
1.63
509                                 offstar(p->n_right->n_left);
510                                 goto again;
511                         }
512                         order(p->n_rightINTAREG|INTBREG);
513                 }
ragge
1.64
514 //printf("foo2\n");
515 //fwalk(p, e2print, 0);
ragge
1.63
516                 rv = asgops(pcook);
ragge
1.64
517 //printf("foo6 : %x\n", rv);
ragge
1.63
518                 if (rv < 0)
519                         goto nomat;
ragge
1.65
520                 if (rv & RREG)
ragge
1.63
521                         order(p->n_rightINTAREG|INTBREG);
522                 q = &table[rv >> 2];
ragge
1.64
523 //printf("foo7\n");
ragge
1.63
524                 if (!allo(pq))
525                         cerror("assign allo failed");
ragge
1.64
526 //printf("foo3\n");
ragge
1.63
527                 expand(pcookq->cstring);
528                 reclaim(pq->rewritecook);
ragge
1.64
529 //printf("foo4\n");
530 //fwalk(p, e2print, 0);
ragge
1.63
531                 goto cleanup;
ragge
1.65
532 #endif
533
ragge
1.48
534         case PLUS:
ragge
1.50
535         case MINUS:
ragge
1.51
536         case AND:
537         case OR:
538         case ER:
ragge
1.52
539         case DIV:
ragge
1.53
540         case MOD:
541         case MUL:
ragge
1.55
542         case LS:
543         case RS:
ragge
1.48
544
ragge
1.60
545                 /*
ragge
1.69
546                  * Get a suitable op.
547                  */
548                 if ((rv = findops(pcook)) < 0) {
549                         if (setbin(p))
550                                 goto again;
551                         goto nomat;
552                 }
553
554                 /*
555                  * Do subnodes conversions (if needed).
556                  */
557                 switch (rv & LMASK) {
558                 case LREG:
559                         order(p->n_leftINTAREG|INTBREG);
560                         break;
561                 case LOREG:
562                         offstar(p->n_left->n_left);
563                         canon(p->n_left);
564                         break;
565                 case LTEMP:
566                         order(p->n_leftINTEMP);
567                         break;
568                 }
569
570                 switch (rv & RMASK) {
571                 case RREG:
572                         order(p->n_rightINTAREG|INTBREG);
573                         break;
574                 case ROREG:
575                         offstar(p->n_right->n_left);
576                         canon(p->n_right);
577                         break;
578                 case RTEMP:
579                         order(p->n_rightINTEMP);
580                         break;
581                 }
582                 p->n_su = rv;
583                 return;
584 #if 0
585                 /*
ragge
1.60
586                  * Be sure that both sides are addressable.
587                  */
ragge
1.50
588 //printf("newstyle node %p\n", p);
ragge
1.60
589                 if (!canaddr(p->n_left)) {
ragge
1.67
590                         if (p->n_left->n_op == UMUL) {
ragge
1.60
591                                 offstar(p->n_left->n_left);
592                                 goto again;
ragge
1.53
593                         }
ragge
1.60
594                         order(p->n_leftINTAREG|INTBREG);
595                 }
ragge
1.50
596 //printf("newstyle addrl %p\n", p);
ragge
1.60
597                 if (!canaddr(p->n_right)) {
ragge
1.67
598                         if (p->n_right->n_op == UMUL) {
ragge
1.60
599                                 offstar(p->n_right->n_left);
600                                 goto again;
ragge
1.53
601                         }
ragge
1.60
602                         order(p->n_rightINTAREG|INTBREG);
603                 }
ragge
1.50
604 //printf("newstyle addrr %p\n", p);
ragge
1.48
605
ragge
1.60
606                 /*
607                  *
608                  */
609                 m = INTAREG|INTBREG;
610                 rv = findops(p);
611 foo:            if (rv < 0) {
ragge
1.61
612                         if (setbin(p))
ragge
1.60
613                                 goto again;
614                         goto nomat;
615                 }
ragge
1.65
616                 if (rv & LREG) {
ragge
1.67
617                         if (p->n_left->n_op == UMUL) {
ragge
1.65
618                                 offstar(p->n_left->n_left);
619                                 goto again;
620                         }
ragge
1.60
621                         order(p->n_leftINTAREG|INTBREG);
ragge
1.65
622                 }
ragge
1.50
623 //printf("newstyle ltmp %p\n", p);
ragge
1.65
624                 if (rv & RREG) {
ragge
1.67
625                         if (p->n_right->n_op == UMUL) {
ragge
1.65
626                                 offstar(p->n_right->n_left);
627                                 goto again;
628                         }
ragge
1.60
629                         order(p->n_rightINTAREG|INTBREG);
ragge
1.65
630                 }
ragge
1.50
631 //printf("newstyle rtmp %p\n", p);
ragge
1.49
632                 
633
ragge
1.60
634                 q = &table[rv >> 2];
635                 if (!allo(pq)) {
636                         /*
637                          * Ran out of suitable temp regs.
638                          * Force everything onto stack.
639                          * Be careful to avoid loops.
640                          * XXX - this is bad code!
641                          */
ragge
1.65
642                         if ((rv & LREG) == 0 && istnode(p->n_left)) {
ragge
1.60
643                                 order(p->n_leftINTEMP);
644                                 goto again;
ragge
1.65
645                         } else if (!(rv & RREG) &&istnode(p->n_right)) {
ragge
1.60
646                                 order(p->n_rightINTEMP);
647                                 goto again;
ragge
1.54
648                         }
ragge
1.60
649                         cerror("allo failed");
650                 }
651                 expand(pmq->cstring);
652                 reclaim(pq->rewritem);
ragge
1.50
653 //printf("newstyle ute %p\n", p);
ragge
1.49
654                 goto cleanup;
655
ragge
1.69
656 #endif
657
ragge
1.57
658                 /*
659                  * For now just be sure that the trees on each side
660                  * are adressable.
661                  */
662         case EQ:
663         case NE:
664         case LE:
665         case LT:
666         case GE:
667         case GT:
668         case ULE:
669         case ULT:
670         case UGE:
671         case UGT:
ragge
1.60
672
ragge
1.57
673                 if (!canaddr(p->n_left)) {
ragge
1.67
674                         if (p->n_left->n_op == UMUL) {
ragge
1.57
675                                 offstar(p->n_left->n_left);
676                                 goto again;
677                         }
ragge
1.60
678                         order(p->n_leftINTAREG|INTBREG|INAREG|INBREG);
ragge
1.57
679                 }
680                 if (!canaddr(p->n_right)) {
ragge
1.67
681                         if (p->n_right->n_op == UMUL) {
ragge
1.57
682                                 offstar(p->n_right->n_left);
683                                 goto again;
684                         }
ragge
1.60
685                         order(p->n_rightINTAREG|INTBREG|INAREG|INBREG);
ragge
1.57
686                 }
687                 rv = relops(p);
688                 m = FORCC;
ragge
1.69
689                 break;
ragge
1.57
690
ragge
1.1
691         default:
692                 /* look for op in table */
ragge
1.8
693                 for (;;) {
694                         if ((m = match(pcookie)) == MDONE)
695                                 goto cleanup;
696                         else if (m == MNOPE) {
697                                 if (!(cookie = nextcook(pcookie)))
698                                         goto nomat;
ragge
1.1
699                                 continue;
ragge
1.8
700                         } else
701                                 break;
702                 }
ragge
1.1
703                 break;
704
705         case FORCE:
706         case CBRANCH:
ragge
1.68
707         case UCALL:
ragge
1.1
708         case CALL:
ragge
1.68
709         case USTCALL:
ragge
1.1
710         case STCALL:
ragge
1.68
711         case UFORTCALL:
ragge
1.1
712         case FORTCALL:
713                 /* don't even go near the table... */
714                 ;
715
ragge
1.8
716         }
ragge
1.25
717         /*
ragge
1.8
718          * get here to do rewriting if no match or
719          * fall through from above for hard ops
720          */
ragge
1.1
721
ragge
1.13
722         p1 = p->n_left;
ragge
1.8
723         if (ty == BITYPE)
ragge
1.13
724                 p2 = p->n_right;
ragge
1.8
725         else
726                 p2 = NIL;
ragge
1.1
727         
ragge
1.30
728 #ifdef PCC_DEBUG
ragge
1.8
729         if (odebug) {
730                 printf("order(%p, "p);
731                 prcook(cook);
732                 printf("), cookie ");
733                 prcook(cookie);
734                 printf(", rewrite %s\n"opst[m]);
735         }
ragge
1.30
736 #endif
ragge
1.8
737         switch (m) {
ragge
1.1
738         default:
739                 nomat:
ragge
1.13
740                 cerror"no table entry for op %s"opst[p->n_op] );
ragge
1.1
741
742         case FORCE:
743                 cook = INTAREG|INTBREG;
ragge
1.19
744                 order(p->n_leftcook);
745                 reclaim(pRLEFTcook);
ragge
1.38
746                 return;
ragge
1.1
747
748         case CBRANCH:
ragge
1.36
749                 p1->n_label = p2->n_lval;
ragge
1.42
750                 o = p1->n_op;
ragge
1.36
751                 codgen(p1FORCC);
ragge
1.42
752                 cbgen(op2->n_lval);
ragge
1.36
753                 reclaim(p1RNULL0);
ragge
1.19
754                 nfree(p2);
755                 nfree(p);
ragge
1.1
756                 return;
757
758         case FLD:       /* fields of funny type */
ragge
1.67
759                 if ( p1->n_op == UMUL ){
ragge
1.13
760                         offstarp1->n_left );
ragge
1.1
761                         goto again;
762                         }
763
ragge
1.67
764         case UMINUS:
ragge
1.30
765                 orderp1INBREG|INAREG);
ragge
1.1
766                 goto again;
767
768         case NAME:
769                 /* all leaves end up here ... */
770                 ifo == REG ) goto nomat;
771                 orderpINTAREG|INTBREG );
772                 goto again;
773
774         case INIT:
ragge
1.12
775                 uerror("init: illegal initialization");
ragge
1.1
776                 return;
777
ragge
1.68
778         case UFORTCALL:
ragge
1.13
779                 p->n_right = NIL;
ragge
1.1
780         case FORTCALL:
ragge
1.68
781                 o = p->n_op = UFORTCALL;
ragge
1.1
782                 ifgenfcallpcookie ) ) goto nomat;
783                 goto cleanup;
784
ragge
1.68
785         case UCALL:
ragge
1.13
786                 p->n_right = NIL;
ragge
1.1
787         case CALL:
ragge
1.68
788                 o = p->n_op = UCALL;
ragge
1.1
789                 ifgencallpcookie ) ) goto nomat;
790                 goto cleanup;
791
ragge
1.68
792         case USTCALL:
ragge
1.13
793                 p->n_right = NIL;
ragge
1.1
794         case STCALL:
ragge
1.68
795                 o = p->n_op = USTCALL;
ragge
1.1
796                 ifgenscallpcookie ) ) goto nomat;
797                 goto cleanup;
798
799                 /* if arguments are passed in register, care must be taken that reclaim
ragge
1.2
800                  * not throw away the register which now has the result... */
ragge
1.1
801
ragge
1.67
802         case UMUL:
ragge
1.1
803                 ifcook == FOREFF ){
804                         /* do nothing */
ragge
1.13
805                         orderp->n_leftFOREFF );
ragge
1.19
806                         nfree(p);
ragge
1.1
807                         return;
ragge
1.19
808                 }
ragge
1.30
809                 offstarp->n_left );
810 #if 0
811                 canon(p);
812                 ifcanaddr(p) && cook != INTEMP )
813                         goto cleanup;
ragge
1.1
814 #endif
815                 goto again;
816
817         case INCR:  /* INCR and DECR */
818                 ifsetincr(p) ) goto again;
819
ragge
1.49
820                 /* x++ becomes (x = x + 1) -1; */
ragge
1.1
821
822                 p1 = tcopy(p);
ragge
1.49
823                 if (cook & FOREFF) {
824                         nfree(p->n_right);
825                         p->n_right = p1;
ragge
1.50
826                         p1->n_op = (p->n_op == INCR) ? PLUSMINUS;
ragge
1.49
827                         p->n_op = ASSIGN;
828                 } else {
829                         p2 = talloc();
830                         p2->n_rall = NOPREF;
831                         p2->n_name = "";
832                         p2->n_op = ASSIGN;
833                         p2->n_type = p->n_type;
834                         p2->n_left = p->n_left;
835                         p2->n_right = p1;
836                         p1->n_op = (p->n_op == INCR) ? PLUSMINUS;
837                         p->n_op = (p->n_op == INCR) ? MINUS : PLUS;
ragge
1.50
838                         p->n_left = p2;
ragge
1.49
839                 }
ragge
1.1
840                 goto again;
841
842         case STASG:
843                 ifsetstrp ) ) goto again;
844                 goto nomat;
845
846         case ASSIGN:
ragge
1.69
847                 if (setasg(pcook))
ragge
1.8
848                         goto again;
ragge
1.1
849                 goto nomat;
850
851         case BITYPE:
852                 ifsetbinp ) ) goto again;
853                 goto nomat;
854
855                 }
856
857         cleanup:
858
859         /* if it is not yet in the right state, put it there */
860
861         ifcook & FOREFF ){
862                 reclaimpRNULL0 );
863                 return;
864                 }
865
ragge
1.13
866         ifp->n_op==FREE ) return;
ragge
1.1
867
868         iftshapepcook ) ) return;
869
870         if( (m=match(p,cook) ) == MDONE ) return;
871
872         /* we are in bad shape, try one last chance */
ragge
1.8
873         if (lastchance(pcook))
874                 goto again;
ragge
1.1
875
876         goto nomat;
ragge
1.8
877 }
ragge
1.1
878
ragge
1.69
879 /*
880  * Count the number of registers needed to evaluate a tree.
881  * This is the trivial implementation, for machines with symmetric
882  * registers. Machines with difficult register assignment strategies
883  * will need to define this function themselves.
884  * Return value is the number of registers used so far.
885  */
886 int
887 sucomp(NODE *p
888 {
889         struct optab *q = &table[TBLIDX(p->n_su)];
890         int leftright;
891         int nreg;
892
893         if (p->n_su == -1)
894                 return sucomp(p->n_left);
895
896         nreg = (q->needs & NACOUNT) * szty(p->n_type);
897
898         switch (p->n_su & RMASK) {
899         case RREG:
900         case ROREG:
901                 right = sucomp(p->n_right);
902                 break;
903         case RTEMP:
904                 cerror("sucomp RTEMP");
905         default:
906                 right = 0;
907         }
908         switch (p->n_su & LMASK) {
909         case LREG:
910         case LOREG:
911                 left = sucomp(p->n_left);
912                 break;
913         case LTEMP:
914                 cerror("sucomp LTEMP");
915         default:
916                 left = 0;
917         }
918 //printf("sucomp: right %d left %d\n", right, left);
919         if (right > left)
920                 p->n_su |= DORIGHT;
921         if (right > nreg)
922                 nreg = right;
923         if (left > nreg)
924                 nreg = right;
925         return nreg;
926 }
927
928 void
929 genregs(NODE *p)
930 {
931         rallo(pNOPREF);
932 }
933
934 void
935 gencode(NODE *p)
936 {
937         struct optab *q = &table[TBLIDX(p->n_su)];
938
939         if (p->n_su == -1/* For OREGs and similar */
940                 return gencode(p->n_left);
941
942         if (p->n_su & DORIGHT) {
943                 gencode(p->n_right);
944                 if ((p->n_su & RMASK) == ROREG)
945                         canon(p);
946         }
947         if (p->n_su & LMASK) {
948                 gencode(p->n_left);
949                 if ((p->n_su & LMASK) == LOREG)
950                         canon(p);
951         }
952         if ((p->n_su & RMASK) && !(p->n_su & DORIGHT)) {
953                 gencode(p->n_right);
954                 if ((p->n_su & RMASK) == ROREG)
955                         canon(p);
956         }
957         if (!allo(pq))
958                 cerror("failed register allocation");
959         expand(pFOREFFq->cstring);
960         reclaim(pq->rewriteINTAREG);
961 }
962
963