Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20081126173244

Diff

Diff from 1.247 to:

Annotations

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

Annotated File View

ragge
1.247
1 /*      $Id: reader.c,v 1.247 2008/11/26 17:32:44 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 /*
ragge
1.236
64  * Everything is entered via pass2_compile().  No functions are 
65  * allowed to recurse back into pass2_compile().
ragge
1.123
66  */
67
ragge
1.1
68 # include "pass2.h"
69
ragge
1.70
70 #include <string.h>
ragge
1.71
71 #include <stdarg.h>
ragge
1.94
72 #include <stdlib.h>
ragge
1.70
73
ragge
1.1
74 /*      some storage declarations */
75 int nrecur;
76 int lflag;
ragge
1.9
77 int x2debug;
ragge
1.1
78 int udebug = 0;
ragge
1.103
79 int thisline;
ragge
1.72
80 int fregs;
ragge
1.123
81 int p2autooffp2maxautooff;
ragge
1.1
82
ragge
1.72
83 NODE *nodepole;
ragge
1.197
84 FILE *prfil;
ragge
1.238
85 struct interpass prepole;
ragge
1.23
86
ragge
1.37
87 void saveip(struct interpass *ip);
ragge
1.243
88 void deltemp(NODE *pvoid *);
ragge
1.232
89 static void cvtemps(struct interpass *ipoleint opint off);
ragge
1.72
90 NODE *store(NODE *);
ragge
1.242
91 static void fixxasm(struct p2env *);
ragge
1.65
92
ragge
1.72
93 static void gencode(NODE *pint cookie);
ragge
1.216
94 static void genxasm(NODE *p);
ragge
1.69
95
ragge
1.246
96 struct p2env p2env;
ragge
1.121
97
ragge
1.246
98 int
99 getlab2(void)
100 {
101         extern int getlab(void);
102         int rv = getlab();
103 #ifdef PCC_DEBUG
104         if (p2env.epp->ip_lblnum != rv)
105                 comperr("getlab2 error: %d != %d"p2env.epp->ip_lblnumrv);
106 #endif
107         p2env.epp->ip_lblnum++;
108         return rv;
109 }
ragge
1.241
110
ragge
1.26
111 #ifdef PCC_DEBUG
ragge
1.241
112 static int *lbldef, *lbluse;
ragge
1.26
113 static void
ragge
1.243
114 cktree(NODE *pvoid *arg)
ragge
1.26
115 {
ragge
1.241
116         int i;
117
ragge
1.26
118         if (p->n_op > MAXOP)
ragge
1.218
119                 cerror("%p) op %d slipped through"pp->n_op);
ragge
1.199
120         if (BTYPE(p->n_type) > MAXTYPES)
ragge
1.218
121                 cerror("%p) type %x slipped through"pp->n_type);
ragge
1.241
122         if (p->n_op == CBRANCH) {
123                  if (!logop(p->n_left->n_op))
124                         cerror("%p) not logop branch"p);
125                 i = p->n_right->n_lval;
ragge
1.242
126                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
ragge
1.241
127                         cerror("%p) label %d outside boundaries %d-%d",
ragge
1.242
128                             pip2env.ipp->ip_lblnump2env.epp->ip_lblnum);
129                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
ragge
1.241
130         }
ragge
1.47
131         if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
ragge
1.218
132                 cerror("%p) asgop %d slipped through"pp->n_op);
ragge
1.241
133         if (p->n_op == TEMP &&
ragge
1.242
134             (regno(p) < p2env.ipp->ip_tmpnum || regno(p) >= p2env.epp->ip_tmpnum))
ragge
1.241
135                 cerror("%p) temporary %d outside boundaries %d-%d",
ragge
1.242
136                     pregno(p), p2env.ipp->ip_tmpnump2env.epp->ip_tmpnum);
ragge
1.241
137         if (p->n_op == GOTO) {
138                 i = p->n_left->n_lval;
ragge
1.242
139                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
ragge
1.241
140                         cerror("%p) label %d outside boundaries %d-%d",
ragge
1.242
141                             pip2env.ipp->ip_lblnump2env.epp->ip_lblnum);
142                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
ragge
1.241
143         }
144 }
145
146 /*
147  * Check that the trees are in a suitable state for pass2.
148  */
149 static void
ragge
1.244
150 sanitychecks(struct p2env *p2e)
ragge
1.241
151 {
152         struct interpass *ip;
153         int i;
154 #ifdef notyet
155         TMPMARK();
156 #endif
ragge
1.244
157         lbldef = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
158         lbluse = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
ragge
1.241
159
ragge
1.242
160         DLIST_FOREACH(ip, &p2env.ipoleqelem) {
ragge
1.241
161                 if (ip->type == IP_DEFLAB) {
162                         i = ip->ip_lbl;
ragge
1.244
163                         if (i < p2e->ipp->ip_lblnum || i >= p2e->epp->ip_lblnum)
ragge
1.241
164                                 cerror("label %d outside boundaries %d-%d",
ragge
1.244
165                                     ip2e->ipp->ip_lblnump2e->epp->ip_lblnum);
166                         lbldef[i-p2e->ipp->ip_lblnum] = 1;
ragge
1.241
167                 }
168                 if (ip->type == IP_NODE)
ragge
1.243
169                         walkf(ip->ip_nodecktree0);
ragge
1.241
170         }
ragge
1.244
171         for (i = 0i < (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); i++)
ragge
1.241
172                 if (lbluse[i] != 0 && lbldef[i] == 0)
173                         cerror("internal label %d not defined",
ragge
1.244
174                             i + p2e->ipp->ip_lblnum);
ragge
1.241
175
176 #ifdef notyet
177         TMPFREE();
178 #endif
ragge
1.26
179 }
180 #endif
ragge
1.8
181
ragge
1.130
182 /*
ragge
1.244
183  * Look if a temporary comes from a on-stack argument, in that case
184  * use the already existing stack position instead of moving it to
185  * a new place, and remove the move-to-temp statement.
186  */
187 static int
188 stkarg(int tnrint *soff)
189 {
190         struct p2env *p2e = &p2env;
191         struct interpass *ip;
192         NODE *p;
193
194         ip = DLIST_NEXT((struct interpass *)p2e->ippqelem); /* first DEFLAB */
195         ip = DLIST_NEXT(ipqelem); /* first NODE */
196
197         for (; ip->type != IP_DEFLABip = DLIST_NEXT(ipqelem)) {
198                 if (ip->type != IP_NODE)
199                         continue;
200
201                 p = ip->ip_node;
ragge
1.247
202                 if (p->n_op == XASM)
203                         continue/* XXX - hack for x86 PIC */
ragge
1.244
204 #ifdef PCC_DEBUG
205                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
206                         comperr("temparg");
207 #endif
208                 if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
209                         continue/* arg in register */
210                 if (tnr != regno(p->n_left))
211                         continue/* wrong assign */
212                 p = p->n_right;
213                 if (p->n_op == UMUL &&
214                     p->n_left->n_op == PLUS &&
215                     p->n_left->n_left->n_op == REG &&
216                     p->n_left->n_right->n_op == ICON)
217                         *soff = p->n_left->n_right->n_lval;
218                 else if (p->n_op == OREG)
219                         *soff = p->n_lval;
220                 else
221                         comperr("stkarg: bad arg");
222                 tfree(ip->ip_node);
223                 DLIST_REMOVE(ipqelem);
224                 return 1;
225         }
226         return 0;
227 }
228
229 /*
230  * See if an ADDROF is somewhere inside the expression tree.
231  * If so, fill in the offset table.
232  */
233 static void
234 findaof(NODE *pvoid *arg)
235 {
236         int *aof = arg;
237         int tnr;
238
239         if (p->n_op != ADDROF)
240                 return;
241         tnr = regno(p->n_left);
242         if (aof[tnr])
243                 return/* already gotten stack address */
244         if (stkarg(tnr, &aof[tnr]))
245                 return/* argument was on stack */
246         aof[tnr] = BITOOR(freetemp(szty(p->n_left->n_type)));
247 }
248
249 /*
ragge
1.89
250  * Check if a node has side effects.
251  */
252 static int
253 isuseless(NODE *n)
254 {
255         switch (n->n_op) {
ragge
1.216
256         case XASM:
ragge
1.89
257         case FUNARG:
258         case UCALL:
259         case UFORTCALL:
260         case FORCE:
261         case ASSIGN:
262         case CALL:
263         case FORTCALL:
264         case CBRANCH:
265         case RETURN:
266         case GOTO:
267         case STCALL:
268         case USTCALL:
269         case STASG:
270         case STARG:
271                 return 0;
272         default:
273                 return 1;
274         }
275 }
276
ragge
1.130
277 /*
278  * Delete statements with no meaning (like a+b; or 513.4;)
279  */
ragge
1.238
280 NODE *
ragge
1.89
281 deluseless(NODE *p)
282 {
283         struct interpass *ip;
284         NODE *l, *r;
285
286         if (optype(p->n_op) == LTYPE) {
287                 nfree(p);
288                 return NULL;
289         }
290         if (isuseless(p) == 0)
291                 return p;
292
293         if (optype(p->n_op) == UTYPE) {
294                 l = p->n_left;
295                 nfree(p);
296                 return deluseless(l);
297         }
298
299         /* Be sure that both leaves may be valid */
300         l = deluseless(p->n_left);
301         r = deluseless(p->n_right);
302         nfree(p);
303         if (l && r) {
ragge
1.201
304                 ip = ipnode(l);
305                 DLIST_INSERT_AFTER(&prepoleipqelem);
ragge
1.89
306                 return r;
307         } else if (l)
308                 return l;
309         else if (r)
310                 return r;
311         return NULL;
312 }
313
ragge
1.172
314 /*
315  * Receives interpass structs from pass1.
316  */
317 void
318 pass2_compile(struct interpass *ip)
319 {
ragge
1.244
320         struct p2env *p2e = &p2env;
321         int *addrp;
ragge
1.245
322         MARK mark;
ragge
1.244
323
ragge
1.172
324         if (ip->type == IP_PROLOG) {
ragge
1.244
325                 memset(p2e0sizeof(struct p2env));
326                 p2e->ipp = (struct interpass_prolog *)ip;
327                 DLIST_INIT(&p2e->ipoleqelem);
ragge
1.172
328         }
ragge
1.244
329         DLIST_INSERT_BEFORE(&p2e->ipoleipqelem);
ragge
1.172
330         if (ip->type != IP_EPILOG)
331                 return;
332
333 #ifdef PCC_DEBUG
334         if (e2debug) {
335                 printf("Entering pass2\n");
ragge
1.244
336                 printip(&p2e->ipole);
ragge
1.172
337         }
338 #endif
ragge
1.174
339
ragge
1.244
340         p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipoleqelem);
341         p2maxautooff = p2autooff = p2e->epp->ipp_autos;
ragge
1.174
342
ragge
1.241
343 #ifdef PCC_DEBUG
ragge
1.244
344         sanitychecks(p2e);
ragge
1.241
345 #endif
ragge
1.244
346         myreader(&p2e->ipole); /* local massage of input */
ragge
1.174
347
ragge
1.244
348         /*
349          * Do initial modification of the trees.  Two loops;
350          * - first, search for ADDROF of TEMPs, these must be
351          *   converterd to OREGs on stack.
352          * - second, do the actual conversions, in case of not xtemps
353          *   convert all temporaries to stack references.
354          */
ragge
1.245
355         markset(&mark);
ragge
1.244
356         if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
357                 addrp = tmpcalloc(sizeof(int) *
358                     (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
359                 addrp -= p2e->ipp->ip_tmpnum;
360         } else
361                 addrp = NULL;
362         if (xtemps) {
363                 DLIST_FOREACH(ip, &p2e->ipoleqelem) {
364                         if (ip->type == IP_NODE)
365                                 walkf(ip->ip_nodefindaofaddrp);
366                 }
367         }
ragge
1.246
368         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.244
369                 if (ip->type == IP_NODE)
370                         walkf(ip->ip_nodedeltempaddrp);
ragge
1.245
371         markfree(&mark);
ragge
1.244
372
373 #ifdef PCC_DEBUG
374         if (e2debug) {
375                 printf("Efter ADDROF/TEMP\n");
376                 printip(&p2e->ipole);
377         }
378 #endif
379
380 #if 0
381         DLIST_FOREACH(ip, &p2e->ipoleqelem) {
ragge
1.172
382                 if (ip->type != IP_NODE)
383                         continue;
384                 if (xtemps == 0)
ragge
1.243
385                         walkf(ip->ip_nodedeltemp0);
ragge
1.172
386         }
ragge
1.244
387 #endif
388
ragge
1.201
389         DLIST_INIT(&prepoleqelem);
ragge
1.244
390         DLIST_FOREACH(ip, &p2e->ipoleqelem) {
ragge
1.172
391                 if (ip->type != IP_NODE)
392                         continue;
393                 canon(ip->ip_node);
ragge
1.201
394                 if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) {
ragge
1.172
395                         DLIST_REMOVE(ipqelem);
ragge
1.201
396                 } else while (!DLIST_ISEMPTY(&prepoleqelem)) {
gmcgarry
1.224
397                         struct interpass *tipp;
ragge
1.201
398
gmcgarry
1.224
399                         tipp = DLIST_NEXT(&prepoleqelem);
400                         DLIST_REMOVE(tippqelem);
401                         DLIST_INSERT_BEFORE(iptippqelem);
ragge
1.201
402                 }
ragge
1.172
403         }
404
ragge
1.244
405         fixxasm(p2e); /* setup for extended asm */
ragge
1.216
406
ragge
1.244
407         optimize(p2e);
408         ngenregs(p2e);
ragge
1.172
409
ragge
1.244
410         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.172
411                 emit(ip);
412 }
413
ragge
1.124
414 void
ragge
1.125
415 emit(struct interpass *ip)
ragge
1.124
416 {
gmcgarry
1.208
417         NODE *p, *r;
418         struct optab *op;
ragge
1.149
419         int o;
ragge
1.124
420
ragge
1.125
421         switch (ip->type) {
422         case IP_NODE:
423                 p = ip->ip_node;
ragge
1.124
424
ragge
1.149
425                 nodepole = p;
ragge
1.180
426                 canon(p); /* may convert stuff after genregs */
ragge
1.240
427                 if (c2debug > 1) {
428                         printf("emit IP_NODE:\n");
429                         fwalk(pe2print0);
430                 }
ragge
1.124
431                 switch (p->n_op) {
432                 case CBRANCH:
433                         /* Only emit branch insn if RESCC */
gmcgarry
1.208
434                         /* careful when an OPLOG has been elided */
435                         if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
436                                 op = &table[TBLIDX(p->n_left->n_left->n_su)];
437                                 r = p->n_left;
438                         } else {
439                                 op = &table[TBLIDX(p->n_left->n_su)];
440                                 r = p;
441                         }
442                         if (op->rewrite & RESCC) {
ragge
1.124
443                                 o = p->n_left->n_op;
gmcgarry
1.208
444                                 gencode(rFORCC);
ragge
1.124
445                                 cbgen(op->n_right->n_lval);
gmcgarry
1.208
446                         } else {
447                                 gencode(rFORCC);
448                         }
ragge
1.124
449                         break;
450                 case FORCE:
ragge
1.151
451                         gencode(p->n_leftINREGS);
ragge
1.124
452                         break;
ragge
1.216
453                 case XASM:
454                         genxasm(p);
455                         break;
ragge
1.124
456                 default:
457                         if (p->n_op != REG || p->n_type != VOID/* XXX */
458                                 gencode(pFOREFF); /* Emit instructions */
459                 }
460
ragge
1.125
461                 tfree(p);
462                 break;
ragge
1.124
463         case IP_PROLOG:
464                 prologue((struct interpass_prolog *)ip);
465                 break;
466         case IP_EPILOG:
467                 eoftn((struct interpass_prolog *)ip);
ragge
1.174
468                 p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
ragge
1.124
469                 break;
470         case IP_DEFLAB:
471                 deflab(ip->ip_lbl);
472                 break;
473         case IP_ASM:
gmcgarry
1.229
474                 printf("%s"ip->ip_asm);
ragge
1.124
475                 break;
476         default:
ragge
1.216
477                 cerror("emit %d"ip->type);
ragge
1.124
478         }
ragge
1.123
479 }
ragge
1.124
480
ragge
1.30
481 #ifdef PCC_DEBUG
ragge
1.1
482 char *cnames[] = {
483         "SANY",
484         "SAREG",
485         "SBREG",
ragge
1.153
486         "SCREG",
487         "SDREG",
ragge
1.1
488         "SCC",
489         "SNAME",
490         "SCON",
491         "SFLD",
492         "SOREG",
493         "STARNM",
494         "STARREG",
495         "INTEMP",
496         "FORARG",
497         "SWADD",
498         0,
ragge
1.72
499 };
ragge
1.1
500
ragge
1.2
501 /*
502  * print a nice-looking description of cookie
503  */
ragge
1.70
504 char *
ragge
1.2
505 prcook(int cookie)
506 {
ragge
1.70
507         static char buf[50];
ragge
1.1
508         int iflag;
509
ragge
1.70
510         if (cookie & SPECIAL) {
511                 switch (cookie) {
512                 case SZERO:
513                         return "SZERO";
514                 case SONE:
515                         return "SONE";
516                 case SMONE:
517                         return "SMONE";
518                 default:
ragge
1.200
519                         snprintf(bufsizeof(buf), "SPECIAL+%d"cookie & ~SPECIAL);
ragge
1.70
520                         return buf;
ragge
1.1
521                 }
ragge
1.70
522         }
ragge
1.1
523
524         flag = 0;
ragge
1.70
525         buf[0] = 0;
526         for (i = 0cnames[i]; ++i) {
527                 if (cookie & (1<<i)) {
528                         if (flag)
ragge
1.200
529                                 strlcat(buf"|"sizeof(buf));
ragge
1.1
530                         ++flag;
ragge
1.200
531                         strlcat(bufcnames[i], sizeof(buf));
ragge
1.1
532                 }
ragge
1.70
533         }
534         return buf;
535 }
ragge
1.1
536
ragge
1.30
537 #endif
ragge
1.1
538
539 int odebug = 0;
540
ragge
1.151
541 int
ragge
1.69
542 geninsn(NODE *pint cookie)
543 {
ragge
1.71
544         NODE *p1, *p2;
ragge
1.236
545         int qorv = 0;
ragge
1.69
546
547 #ifdef PCC_DEBUG
548         if (odebug) {
ragge
1.70
549                 printf("geninsn(%p, %s)\n"pprcook(cookie));
ragge
1.69
550                 fwalk(pe2print0);
551         }
552 #endif
553
ragge
1.236
554         q = cookie & QUIET;
555         cookie &= ~QUIET/* XXX - should not be necessary */
556
ragge
1.69
557 again:  switch (o = p->n_op) {
ragge
1.71
558         case EQ:
559         case NE:
560         case LE:
561         case LT:
562         case GE:
563         case GT:
564         case ULE:
565         case ULT:
566         case UGE:
567         case UGT:
gmcgarry
1.208
568                 p1 = p->n_left;
569                 p2 = p->n_right;
ragge
1.210
570                 if (p2->n_op == ICON && p2->n_lval == 0 &&
571                     optype(p1->n_op) == BITYPE) {
ragge
1.236
572 #ifdef mach_pdp11 /* XXX all targets? */
573                         if ((rv = geninsn(p1FORCC|QUIET)) != FFAIL)
574                                 break;
575 #else
576                         if (findops(p1FORCC) > 0)
gmcgarry
1.208
577                                 break;
ragge
1.236
578 #endif
gmcgarry
1.208
579                 }
ragge
1.159
580                 rv = relops(p);
581                 break;
ragge
1.71
582
ragge
1.69
583         case PLUS:
584         case MINUS:
585         case MUL:
586         case DIV:
587         case MOD:
588         case AND:
589         case OR:
590         case ER:
591         case LS:
592         case RS:
ragge
1.151
593                 rv = findops(pcookie);
594                 break;
ragge
1.77
595
ragge
1.69
596         case ASSIGN:
ragge
1.236
597 #ifdef FINDMOPS
598                 if ((rv = findmops(pcookie)) != FFAIL)
599                         break;
600                 /* FALLTHROUGH */
601 #endif
ragge
1.174
602         case STASG:
ragge
1.151
603                 rv = findasg(pcookie);
604                 break;
ragge
1.159
605
ragge
1.178
606         case UMUL/* May turn into an OREG */
ragge
1.179
607                 rv = findumul(pcookie);
608                 break;
609
ragge
1.69
610         case REG:
ragge
1.144
611         case TEMP:
ragge
1.72
612         case NAME:
ragge
1.71
613         case ICON:
ragge
1.213
614         case FCON:
ragge
1.69
615         case OREG:
ragge
1.152
616                 rv = findleaf(pcookie);
617                 break;
ragge
1.69
618
ragge
1.172
619         case STCALL:
620         case CALL:
621                 /* CALL arguments are handled special */
622                 for (p1 = p->n_rightp1->n_op == CMp1 = p1->n_left)
ragge
1.239
623                         (void)geninsn(p1->n_rightFOREFF);
624                 (void)geninsn(p1FOREFF);
ragge
1.172
625                 /* FALLTHROUGH */
ragge
1.206
626         case FLD:
ragge
1.86
627         case COMPL:
ragge
1.85
628         case UMINUS:
ragge
1.71
629         case PCONV:
630         case SCONV:
ragge
1.198
631 /*      case INIT: */
ragge
1.70
632         case GOTO:
633         case FUNARG:
ragge
1.172
634         case STARG:
ragge
1.72
635         case UCALL:
ragge
1.103
636         case USTCALL:
ragge
1.207
637         case ADDROF:
ragge
1.155
638                 rv = finduni(pcookie);
639                 break;
ragge
1.69
640
ragge
1.71
641         case CBRANCH:
642                 p1 = p->n_left;
643                 p2 = p->n_right;
644                 p1->n_label = p2->n_lval;
ragge
1.239
645                 (void)geninsn(p1FORCC);
ragge
1.187
646                 p->n_su = 0;
ragge
1.71
647                 break;
648
ragge
1.187
649         case FORCE/* XXX needed? */
ragge
1.239
650                 (void)geninsn(p->n_leftINREGS);
ragge
1.187
651                 p->n_su = 0/* su calculations traverse left */
ragge
1.71
652                 break;
653
ragge
1.216
654         case XASM:
655                 for (p1 = p->n_leftp1->n_op == CMp1 = p1->n_left)
ragge
1.239
656                         (void)geninsn(p1->n_rightFOREFF);
657                 (void)geninsn(p1FOREFF);
ragge
1.216
658                 break;  /* all stuff already done? */
659
660         case XARG:
661                 /* generate code for correct class here */
ragge
1.221
662 //              geninsn(p->n_left, 1 << p->n_label);
ragge
1.216
663                 break;
664
ragge
1.69
665         default:
ragge
1.174
666                 comperr("geninsn: bad op %s, node %p"opst[o], p);
ragge
1.69
667         }
ragge
1.236
668         if (rv == FFAIL && !q)
ragge
1.160
669                 comperr("Cannot generate code, node %p op %s"p,opst[p->n_op]);
670         if (rv == FRETRY)
671                 goto again;
ragge
1.236
672 #ifdef PCC_DEBUG
673         if (odebug) {
674                 printf("geninsn(%p, %s) rv %d\n"pprcook(cookie), rv);
675                 fwalk(pe2print0);
676         }
677 #endif
ragge
1.153
678         return rv;
ragge
1.69
679 }
680
ragge
1.72
681 /*
682  * Store a given subtree in a temporary location.
683  * Return an OREG node where it is located.
684  */
685 NODE *
686 store(NODE *p)
ragge
1.2
687 {
ragge
1.130
688         extern struct interpass *storesave;
689         struct interpass *ip;
690         NODE *q, *r;
691         int s;
ragge
1.49
692
ragge
1.130
693         s = BITOOR(freetemp(szty(p->n_type)));
694         q = mklnode(OREGsFPREGp->n_type);
695         r = mklnode(OREGsFPREGp->n_type);
696         ip = ipnode(mkbinode(ASSIGNqpp->n_type));
697
ragge
1.149
698         storesave = ip;
ragge
1.72
699         return r;
ragge
1.8
700 }
ragge
1.1
701
ragge
1.170
702 #ifdef PCC_DEBUG
703 #define CDEBUG(x) if (c2debug) printf x
704 #else
705 #define CDEBUG(x)
706 #endif
707
ragge
1.69
708 /*
ragge
1.188
709  * Do a register-register move if necessary.
710  */
711 static void
712 ckmove(NODE *pNODE *q)
713 {
ragge
1.189
714         if (q->n_op != REG || p->n_reg == -1)
ragge
1.188
715                 return/* no register */
716         if (DECRA(p->n_reg0) == DECRA(q->n_reg0))
717                 return/* no move necessary */
ragge
1.190
718         CDEBUG(("rmove: node %p, %s -> %s\n"prnames[DECRA(q->n_reg0)],
719             rnames[DECRA(p->n_reg0)]));
ragge
1.188
720         rmove(DECRA(q->n_reg0), DECRA(p->n_reg0), p->n_type);
721         q->n_reg = q->n_rval = DECRA(p->n_reg0);
722 }
723
724 /*
725  * Rewrite node to register after instruction emit.
ragge
1.75
726  */
727 static void
gmcgarry
1.224
728 rewrite(NODE *pint dorewriteint cookie)
ragge
1.75
729 {
ragge
1.79
730         NODE *l, *r;
731         int o;
732
ragge
1.80
733         l = getlr(p'L');
734         r = getlr(p'R');
ragge
1.79
735         o = p->n_op;
ragge
1.75
736         p->n_op = REG;
ragge
1.76
737         p->n_lval = 0;
ragge
1.95
738         p->n_name = "";
ragge
1.158
739
ragge
1.190
740         if (o == ASSIGN) {
741                 /* special rewrite care */
742                 int reg = DECRA(p->n_reg0);
ragge
1.191
743 #define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
ragge
1.190
744                 if (p->n_reg == -1)
745                         ;
ragge
1.191
746                 else if (TL(l) && (DECRA(l->n_reg0) == reg))
ragge
1.190
747                         ;
ragge
1.191
748                 else if (TL(r) && (DECRA(r->n_reg0) == reg))
ragge
1.190
749                         ;
ragge
1.191
750                 else if (TL(l))
ragge
1.190
751                         rmove(DECRA(l->n_reg0), regp->n_type);
ragge
1.191
752                 else if (TL(r))
ragge
1.190
753                         rmove(DECRA(r->n_reg0), regp->n_type);
754 #if 0
755                 else
756                         comperr("rewrite");
757 #endif
ragge
1.191
758 #undef TL
ragge
1.190
759         }
ragge
1.79
760         if (optype(o) != LTYPE)
761                 tfree(l);
762         if (optype(o) == BITYPE)
763                 tfree(r);
gmcgarry
1.224
764         if (dorewrite == 0)
ragge
1.190
765                 return;
mickey
1.205
766         CDEBUG(("rewrite: %p, reg %s\n"p,
767             p->n_reg == -1"<none>" : rnames[DECRA(p->n_reg0)]));
ragge
1.187
768         p->n_rval = DECRA(p->n_reg0);
ragge
1.75
769 }
770
ragge
1.228
771 #ifndef XASM_TARGARG
772 #define XASM_TARGARG(x,y) 0
773 #endif
774
ragge
1.216
775 /*
776  * printout extended assembler.
777  */
778 void
779 genxasm(NODE *p)
780 {
781         NODE *q, **nary;
782         int n = 1o = 0;
783         char *w;
784
ragge
1.228
785         if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) {
786                 for (q = p->n_leftq->n_op == CMq = q->n_left)
787                         n++;
788                 nary = tmpalloc(sizeof(NODE *)*n);
789                 o = n;
790                 for (q = p->n_leftq->n_op == CMq = q->n_left) {
791                         gencode(q->n_right->n_leftINREGS);
792                         nary[--o] = q->n_right;
793                 }
794                 gencode(q->n_leftINREGS);
795                 nary[--o] = q;
796         } else
797                 nary = 0;
ragge
1.216
798
799         w = p->n_name;
800         putchar('\t');
801         while (*w != 0) {
802                 if (*w == '%') {
ragge
1.225
803                         if (w[1] == '%')
804                                 putchar('%');
ragge
1.228
805                         else if (XASM_TARGARG(wnary))
806                                 ; /* handled by target */
ragge
1.225
807                         else if (w[1] < '0' || w[1] > (n + '0'))
ragge
1.228
808                                 uerror("bad xasm arg number %c"w[1]);
ragge
1.216
809                         else
ragge
1.221
810                                 adrput(stdoutnary[(int)w[1]-'0']->n_left);
ragge
1.216
811                         w++;
ragge
1.228
812                 } else if (*w == '\\') { /* Always 3-digit octal */
813                         int num = *++w - '0';
814                         num = (num << 3) + *++w - '0';
815                         num = (num << 3) + *++w - '0';
816                         putchar(num);
ragge
1.216
817                 } else
818                         putchar(*w);
819                 w++;
820         }
821         putchar('\n');
822 }
823
ragge
1.69
824 void
ragge
1.72
825 gencode(NODE *pint cookie)
ragge
1.69
826 {
827         struct optab *q = &table[TBLIDX(p->n_su)];
ragge
1.188
828         NODE *p1, *l, *r;
ragge
1.190
829         int o = optype(p->n_op);
ragge
1.240
830 #ifdef FINDMOPS
831         int ismops = (p->n_op == ASSIGN && (p->n_flags & 1));
832 #endif
ragge
1.188
833
834         l = p->n_left;
835         r = p->n_right;
ragge
1.69
836
ragge
1.186
837         if (TBLIDX(p->n_su) == 0) {
838                 if (o == BITYPE && (p->n_su & DORIGHT))
ragge
1.188
839                         gencode(r0);
ragge
1.185
840                 if (optype(p->n_op) != LTYPE)
ragge
1.188
841                         gencode(l0);
ragge
1.186
842                 if (o == BITYPE && !(p->n_su & DORIGHT))
ragge
1.188
843                         gencode(r0);
ragge
1.185
844                 return;
845         }
ragge
1.69
846
ragge
1.170
847         CDEBUG(("gencode: node %p\n"p));
848
849         if (p->n_op == REG && DECRA(p->n_reg0) == p->n_rval)
ragge
1.156
850                 return/* meaningless move to itself */
ragge
1.175
851
852         if (callop(p->n_op))
853                 lastcall(p); /* last chance before function args */
854         if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL) {
855                 /* Print out arguments first */
ragge
1.188
856                 for (p1 = rp1->n_op == CMp1 = p1->n_left)
ragge
1.175
857                         gencode(p1->n_rightFOREFF);
858                 gencode(p1FOREFF);
ragge
1.190
859                 o = UTYPE/* avoid going down again */
ragge
1.175
860         }
861
ragge
1.190
862         if (o == BITYPE && (p->n_su & DORIGHT)) {
ragge
1.188
863                 gencode(rINREGS);
864                 if (q->rewrite & RRIGHT)
865                         ckmove(pr);
866         }
ragge
1.190
867         if (o != LTYPE) {
ragge
1.188
868                 gencode(lINREGS);
ragge
1.240
869 #ifdef FINDMOPS
870                 if (ismops)
871                         ;
872                 else
873 #endif
874                      if (q->rewrite & RLEFT)
ragge
1.188
875                         ckmove(pl);
876         }
ragge
1.190
877         if (o == BITYPE && !(p->n_su & DORIGHT)) {
ragge
1.188
878                 gencode(rINREGS);
879                 if (q->rewrite & RRIGHT)
880                         ckmove(pr);
881         }
ragge
1.185
882
ragge
1.236
883 #ifdef FINDMOPS
ragge
1.240
884         if (ismops) {
ragge
1.236
885                 /* reduce right tree to make expand() work */
886                 if (optype(r->n_op) != LTYPE) {
ragge
1.240
887                         p->n_op = r->n_op;
ragge
1.236
888                         r = tcopy(r->n_right);
889                         tfree(p->n_right);
890                         p->n_right = r;
891                 }
892         }
893 #endif
894
ragge
1.188
895         canon(p);