Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20120322185140

Diff

Diff from 1.278 to:

Annotations

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

Annotated File View

plunky
1.278
1 /*      $Id: reader.c,v 1.278 2012/03/22 18:51:41 plunky 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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
ragge
1.31
27 /*
28  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without
31  * modification, are permitted provided that the following conditions
32  * are met:
33  *
34  * Redistributions of source code and documentation must retain the above
35  * copyright notice, this list of conditions and the following disclaimer.
36  * Redistributions in binary form must reproduce the above copyright
37  * notice, this list of conditionsand the following disclaimer in the
38  * documentation and/or other materials provided with the distribution.
39  * All advertising materials mentioning features or use of this software
40  * must display the following acknowledgement:
41  *      This product includes software developed or owned by Caldera
42  *      International, Inc.
43  * Neither the name of Caldera International, Inc. nor the names of other
44  * contributors may be used to endorse or promote products derived from
45  * this software without specific prior written permission.
46  *
47  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
48  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
52  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
56  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
57  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
58  * POSSIBILITY OF SUCH DAMAGE.
59  */
ragge
1.1
60
ragge
1.123
61 /*
ragge
1.236
62  * Everything is entered via pass2_compile().  No functions are 
63  * allowed to recurse back into pass2_compile().
ragge
1.123
64  */
65
ragge
1.1
66 # include "pass2.h"
67
ragge
1.70
68 #include <string.h>
ragge
1.71
69 #include <stdarg.h>
ragge
1.94
70 #include <stdlib.h>
ragge
1.70
71
ragge
1.1
72 /*      some storage declarations */
73 int nrecur;
ragge
1.103
74 int thisline;
ragge
1.72
75 int fregs;
ragge
1.123
76 int p2autooffp2maxautooff;
ragge
1.1
77
ragge
1.72
78 NODE *nodepole;
ragge
1.197
79 FILE *prfil;
ragge
1.238
80 struct interpass prepole;
ragge
1.23
81
ragge
1.37
82 void saveip(struct interpass *ip);
ragge
1.243
83 void deltemp(NODE *pvoid *);
ragge
1.232
84 static void cvtemps(struct interpass *ipoleint opint off);
ragge
1.72
85 NODE *store(NODE *);
ragge
1.242
86 static void fixxasm(struct p2env *);
ragge
1.65
87
ragge
1.72
88 static void gencode(NODE *pint cookie);
ragge
1.216
89 static void genxasm(NODE *p);
ragge
1.271
90 static void afree(void);
ragge
1.69
91
ragge
1.246
92 struct p2env p2env;
ragge
1.121
93
ragge
1.246
94 int
95 getlab2(void)
96 {
97         extern int getlab(void);
98         int rv = getlab();
99 #ifdef PCC_DEBUG
100         if (p2env.epp->ip_lblnum != rv)
101                 comperr("getlab2 error: %d != %d"p2env.epp->ip_lblnumrv);
102 #endif
103         p2env.epp->ip_lblnum++;
104         return rv;
105 }
ragge
1.241
106
ragge
1.26
107 #ifdef PCC_DEBUG
ragge
1.241
108 static int *lbldef, *lbluse;
ragge
1.26
109 static void
ragge
1.243
110 cktree(NODE *pvoid *arg)
ragge
1.26
111 {
ragge
1.241
112         int i;
113
ragge
1.26
114         if (p->n_op > MAXOP)
ragge
1.218
115                 cerror("%p) op %d slipped through"pp->n_op);
ragge
1.273
116 #ifndef FIELDOPS
117         if (p->n_op == FLD)
118                 cerror("%p) FLD slipped through"p);
119 #endif
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);
gmcgarry
1.251
125                 i = (int)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.249
137         if (p->n_op == GOTO && p->n_left->n_op == ICON) {
gmcgarry
1.251
138                 i = (int)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
ragge
1.274
188 stkarg(int tnrint (*soff)[2])
ragge
1.244
189 {
190         struct p2env *p2e = &p2env;
191         struct interpass *ip;
192         NODE *p;
193
ragge
1.248
194         ip = DLIST_NEXT((struct interpass *)p2e->ippqelem);
195         while (ip->type != IP_DEFLAB/* search for first DEFLAB */
196                 ip = DLIST_NEXT(ipqelem);
197
ragge
1.244
198         ip = DLIST_NEXT(ipqelem); /* first NODE */
199
200         for (; ip->type != IP_DEFLABip = DLIST_NEXT(ipqelem)) {
201                 if (ip->type != IP_NODE)
202                         continue;
203
204                 p = ip->ip_node;
ragge
1.247
205                 if (p->n_op == XASM)
206                         continue/* XXX - hack for x86 PIC */
ragge
1.264
207 #ifdef notdef
ragge
1.244
208                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
209                         comperr("temparg");
210 #endif
ragge
1.264
211                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
212                         continue/* unknown tree */
213
ragge
1.244
214                 if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
215                         continue/* arg in register */
216                 if (tnr != regno(p->n_left))
217                         continue/* wrong assign */
218                 p = p->n_right;
219                 if (p->n_op == UMUL &&
220                     p->n_left->n_op == PLUS &&
221                     p->n_left->n_left->n_op == REG &&
ragge
1.274
222                     p->n_left->n_right->n_op == ICON) {
223                         soff[0][0] = regno(p->n_left->n_left);
224                         soff[0][1] = (int)p->n_left->n_right->n_lval;
225                 } else if (p->n_op == OREG) {
226                         soff[0][0] = regno(p);
227                         soff[0][1] = (int)p->n_lval;
228                 } else
ragge
1.244
229                         comperr("stkarg: bad arg");
230                 tfree(ip->ip_node);
231                 DLIST_REMOVE(ipqelem);
232                 return 1;
233         }
234         return 0;
235 }
236
237 /*
238  * See if an ADDROF is somewhere inside the expression tree.
239  * If so, fill in the offset table.
240  */
241 static void
242 findaof(NODE *pvoid *arg)
243 {
ragge
1.274
244         int (*aof)[2] = arg;
ragge
1.244
245         int tnr;
246
ragge
1.263
247         if (p->n_op != ADDROF || p->n_left->n_op != TEMP)
ragge
1.244
248                 return;
249         tnr = regno(p->n_left);
ragge
1.274
250         if (aof[tnr][0])
ragge
1.244
251                 return/* already gotten stack address */
252         if (stkarg(tnr, &aof[tnr]))
253                 return/* argument was on stack */
ragge
1.274
254         aof[tnr][0] = FPREG;
255         aof[tnr][1] = BITOOR(freetemp(szty(p->n_left->n_type)));
ragge
1.244
256 }
257
258 /*
ragge
1.89
259  * Check if a node has side effects.
260  */
261 static int
262 isuseless(NODE *n)
263 {
264         switch (n->n_op) {
ragge
1.216
265         case XASM:
ragge
1.89
266         case FUNARG:
267         case UCALL:
268         case UFORTCALL:
269         case FORCE:
270         case ASSIGN:
271         case CALL:
272         case FORTCALL:
273         case CBRANCH:
274         case RETURN:
275         case GOTO:
276         case STCALL:
277         case USTCALL:
278         case STASG:
279         case STARG:
280                 return 0;
281         default:
282                 return 1;
283         }
284 }
285
ragge
1.130
286 /*
287  * Delete statements with no meaning (like a+b; or 513.4;)
288  */
ragge
1.238
289 NODE *
ragge
1.89
290 deluseless(NODE *p)
291 {
292         struct interpass *ip;
293         NODE *l, *r;
294
295         if (optype(p->n_op) == LTYPE) {
296                 nfree(p);
297                 return NULL;
298         }
299         if (isuseless(p) == 0)
300                 return p;
301
302         if (optype(p->n_op) == UTYPE) {
303                 l = p->n_left;
304                 nfree(p);
305                 return deluseless(l);
306         }
307
308         /* Be sure that both leaves may be valid */
309         l = deluseless(p->n_left);
310         r = deluseless(p->n_right);
311         nfree(p);
312         if (l && r) {
ragge
1.201
313                 ip = ipnode(l);
314                 DLIST_INSERT_AFTER(&prepoleipqelem);
ragge
1.89
315                 return r;
316         } else if (l)
317                 return l;
318         else if (r)
319                 return r;
320         return NULL;
321 }
322
ragge
1.172
323 /*
324  * Receives interpass structs from pass1.
325  */
326 void
327 pass2_compile(struct interpass *ip)
328 {
ragge
1.260
329         void deljumps(struct p2env *);
ragge
1.244
330         struct p2env *p2e = &p2env;
ragge
1.274
331         int (*addrp)[2];
ragge
1.245
332         MARK mark;
ragge
1.244
333
ragge
1.172
334         if (ip->type == IP_PROLOG) {
ragge
1.244
335                 memset(p2e0sizeof(struct p2env));
336                 p2e->ipp = (struct interpass_prolog *)ip;
337                 DLIST_INIT(&p2e->ipoleqelem);
ragge
1.172
338         }
ragge
1.244
339         DLIST_INSERT_BEFORE(&p2e->ipoleipqelem);
ragge
1.172
340         if (ip->type != IP_EPILOG)
341                 return;
342
343 #ifdef PCC_DEBUG
344         if (e2debug) {
345                 printf("Entering pass2\n");
ragge
1.244
346                 printip(&p2e->ipole);
ragge
1.172
347         }
348 #endif
ragge
1.174
349
ragge
1.271
350         afree();
ragge
1.244
351         p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipoleqelem);
352         p2maxautooff = p2autooff = p2e->epp->ipp_autos;
ragge
1.174
353
ragge
1.241
354 #ifdef PCC_DEBUG
ragge
1.244
355         sanitychecks(p2e);
ragge
1.241
356 #endif
ragge
1.244
357         myreader(&p2e->ipole); /* local massage of input */
ragge
1.174
358
ragge
1.244
359         /*
360          * Do initial modification of the trees.  Two loops;
361          * - first, search for ADDROF of TEMPs, these must be
362          *   converterd to OREGs on stack.
363          * - second, do the actual conversions, in case of not xtemps
364          *   convert all temporaries to stack references.
365          */
ragge
1.245
366         markset(&mark);
ragge
1.244
367         if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
ragge
1.274
368                 addrp = tmpcalloc(sizeof(*addrp) *
ragge
1.244
369                     (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
370                 addrp -= p2e->ipp->ip_tmpnum;
371         } else
372                 addrp = NULL;
373         if (xtemps) {
374                 DLIST_FOREACH(ip, &p2e->ipoleqelem) {
375                         if (ip->type == IP_NODE)
376                                 walkf(ip->ip_nodefindaofaddrp);
377                 }
378         }
ragge
1.246
379         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.244
380                 if (ip->type == IP_NODE)
381                         walkf(ip->ip_nodedeltempaddrp);
ragge
1.245
382         markfree(&mark);
ragge
1.244
383
384 #ifdef PCC_DEBUG
385         if (e2debug) {
386                 printf("Efter ADDROF/TEMP\n");
387                 printip(&p2e->ipole);
388         }
389 #endif
390
ragge
1.201
391         DLIST_INIT(&prepoleqelem);
ragge
1.244
392         DLIST_FOREACH(ip, &p2e->ipoleqelem) {
ragge
1.172
393                 if (ip->type != IP_NODE)
394                         continue;
395                 canon(ip->ip_node);
ragge
1.201
396                 if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) {
ragge
1.172
397                         DLIST_REMOVE(ipqelem);
ragge
1.201
398                 } else while (!DLIST_ISEMPTY(&prepoleqelem)) {
gmcgarry
1.224
399                         struct interpass *tipp;
ragge
1.201
400
gmcgarry
1.224
401                         tipp = DLIST_NEXT(&prepoleqelem);
402                         DLIST_REMOVE(tippqelem);
403                         DLIST_INSERT_BEFORE(iptippqelem);
ragge
1.201
404                 }
ragge
1.172
405         }
406
ragge
1.244
407         fixxasm(p2e); /* setup for extended asm */
ragge
1.216
408
ragge
1.244
409         optimize(p2e);
410         ngenregs(p2e);
ragge
1.172
411
plunky
1.275
412         if (xssa && xtemps && xdeljumps)
ragge
1.260
413                 deljumps(p2e);
414
ragge
1.244
415         DLIST_FOREACH(ip, &p2e->ipoleqelem)
ragge
1.172
416                 emit(ip);
417 }
418
ragge
1.124
419 void
ragge
1.125
420 emit(struct interpass *ip)
ragge
1.124
421 {
gmcgarry
1.208
422         NODE *p, *r;
423         struct optab *op;
ragge
1.149
424         int o;
ragge
1.124
425
ragge
1.125
426         switch (ip->type) {
427         case IP_NODE:
428                 p = ip->ip_node;
ragge
1.124
429
ragge
1.149
430                 nodepole = p;
ragge
1.180
431                 canon(p); /* may convert stuff after genregs */
ragge
1.240
432                 if (c2debug > 1) {
433                         printf("emit IP_NODE:\n");
434                         fwalk(pe2print0);
435                 }
ragge
1.124
436                 switch (p->n_op) {
437                 case CBRANCH:
438                         /* Only emit branch insn if RESCC */
gmcgarry
1.208
439                         /* careful when an OPLOG has been elided */
440                         if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
441                                 op = &table[TBLIDX(p->n_left->n_left->n_su)];
442                                 r = p->n_left;
443                         } else {
444                                 op = &table[TBLIDX(p->n_left->n_su)];
445                                 r = p;
446                         }
447                         if (op->rewrite & RESCC) {
ragge
1.124
448                                 o = p->n_left->n_op;
gmcgarry
1.208
449                                 gencode(rFORCC);
ragge
1.124
450                                 cbgen(op->n_right->n_lval);
gmcgarry
1.208
451                         } else {
452                                 gencode(rFORCC);
453                         }
ragge
1.124
454                         break;
455                 case FORCE:
ragge
1.151
456                         gencode(p->n_leftINREGS);
ragge
1.124
457                         break;
ragge
1.216
458                 case XASM:
459                         genxasm(p);
460                         break;
ragge
1.124
461                 default:
462                         if (p->n_op != REG || p->n_type != VOID/* XXX */
463                                 gencode(pFOREFF); /* Emit instructions */
464                 }
465
ragge
1.125
466                 tfree(p);
467                 break;
ragge
1.124
468         case IP_PROLOG:
469                 prologue((struct interpass_prolog *)ip);
470                 break;
471         case IP_EPILOG:
472                 eoftn((struct interpass_prolog *)ip);
ragge
1.174
473                 p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
ragge
1.124
474                 break;
475         case IP_DEFLAB:
476                 deflab(ip->ip_lbl);
477                 break;
478         case IP_ASM:
gmcgarry
1.229
479                 printf("%s"ip->ip_asm);
ragge
1.124
480                 break;
481         default:
ragge
1.216
482                 cerror("emit %d"ip->type);
ragge
1.124
483         }
ragge
1.123
484 }
ragge
1.124
485
ragge
1.30
486 #ifdef PCC_DEBUG
ragge
1.1
487 char *cnames[] = {
488         "SANY",
489         "SAREG",
490         "SBREG",
ragge
1.153
491         "SCREG",
492         "SDREG",
ragge
1.1
493         "SCC",
494         "SNAME",
495         "SCON",
496         "SFLD",
497         "SOREG",
498         "STARNM",
499         "STARREG",
500         "INTEMP",
501         "FORARG",
502         "SWADD",
503         0,
ragge
1.72
504 };
ragge
1.1
505
ragge
1.2
506 /*
507  * print a nice-looking description of cookie
508  */
ragge
1.70
509 char *
ragge
1.2
510 prcook(int cookie)
511 {
ragge
1.70
512         static char buf[50];
ragge
1.1
513         int iflag;
514
ragge
1.70
515         if (cookie & SPECIAL) {
516                 switch (cookie) {
517                 case SZERO:
518                         return "SZERO";
519                 case SONE:
520                         return "SONE";
521                 case SMONE:
522                         return "SMONE";
523                 default:
ragge
1.200
524                         snprintf(bufsizeof(buf), "SPECIAL+%d"cookie & ~SPECIAL);
ragge
1.70
525                         return buf;
ragge
1.1
526                 }
ragge
1.70
527         }
ragge
1.1
528
529         flag = 0;
ragge
1.70
530         buf[0] = 0;
531         for (i = 0cnames[i]; ++i) {
532                 if (cookie & (1<<i)) {
533                         if (flag)
ragge
1.200
534                                 strlcat(buf"|"sizeof(buf));
ragge
1.1
535                         ++flag;
ragge
1.200
536                         strlcat(bufcnames[i], sizeof(buf));
ragge
1.1
537                 }
ragge
1.70
538         }
539         return buf;
540 }
ragge
1.30
541 #endif
ragge
1.1
542
ragge
1.151
543 int
ragge
1.69
544 geninsn(NODE *pint cookie)
545 {
ragge
1.71
546         NODE *p1, *p2;
ragge
1.236
547         int qorv = 0;
ragge
1.69
548
549 #ifdef PCC_DEBUG
plunky
1.278
550         if (o2debug) {
ragge
1.70
551                 printf("geninsn(%p, %s)\n"pprcook(cookie));
ragge
1.69
552                 fwalk(pe2print0);
553         }
554 #endif
555
ragge
1.236
556         q = cookie & QUIET;
557         cookie &= ~QUIET/* XXX - should not be necessary */
558
ragge
1.69
559 again:  switch (o = p->n_op) {
ragge
1.71
560         case EQ:
561         case NE:
562         case LE:
563         case LT:
564         case GE:
565         case GT:
566         case ULE:
567         case ULT:
568         case UGE:
569         case UGT:
gmcgarry
1.208
570                 p1 = p->n_left;
571                 p2 = p->n_right;
ragge
1.265
572                 if (p2->n_op == ICON && p2->n_lval == 0 && *p2->n_name == 0 &&
ragge
1.256
573                     (dope[p1->n_op] & (FLOFLG|DIVFLG|SIMPFLG|SHFFLG))) {
ragge
1.236
574 #ifdef mach_pdp11 /* XXX all targets? */
575                         if ((rv = geninsn(p1FORCC|QUIET)) != FFAIL)
576                                 break;
577 #else
578                         if (findops(p1FORCC) > 0)
gmcgarry
1.208
579                                 break;
ragge
1.236
580 #endif
gmcgarry
1.208
581                 }
ragge
1.159
582                 rv = relops(p);
583                 break;
ragge
1.71
584
ragge
1.69
585         case PLUS:
586         case MINUS:
587         case MUL:
588         case DIV:
589         case MOD:
590         case AND:
591         case OR:
592         case ER:
593         case LS:
594         case RS:
ragge
1.151
595                 rv = findops(pcookie);
596                 break;
ragge
1.77
597
ragge
1.69
598         case ASSIGN:
ragge
1.236
599 #ifdef FINDMOPS
600                 if ((rv = findmops(pcookie)) != FFAIL)
601                         break;
602                 /* FALLTHROUGH */
603 #endif
ragge
1.174
604         case STASG:
ragge
1.151
605                 rv = findasg(pcookie);
606                 break;
ragge
1.159
607
ragge
1.178
608         case UMUL/* May turn into an OREG */
ragge
1.179
609                 rv = findumul(pcookie);
610                 break;
611
ragge
1.69
612         case REG:
ragge
1.144
613         case TEMP:
ragge
1.72
614         case NAME:
ragge
1.71
615         case ICON:
ragge
1.213
616         case FCON:
ragge
1.69
617         case OREG:
ragge
1.152
618                 rv = findleaf(pcookie);
619                 break;
ragge
1.69
620
ragge
1.172
621         case STCALL:
622         case CALL:
623                 /* CALL arguments are handled special */
624                 for (p1 = p->n_rightp1->n_op == CMp1 = p1->n_left)
ragge
1.239
625                         (void)geninsn(p1->n_rightFOREFF);
626                 (void)geninsn(p1FOREFF);
ragge
1.172
627                 /* FALLTHROUGH */
ragge
1.206
628         case FLD:
ragge
1.86
629         case COMPL:
ragge
1.85
630         case UMINUS:
ragge
1.71
631         case PCONV:
632         case SCONV:
ragge
1.198
633 /*      case INIT: */
ragge
1.70
634         case GOTO:
635         case FUNARG:
ragge
1.172
636         case STARG:
ragge
1.72
637         case UCALL:
ragge
1.103
638         case USTCALL:
ragge
1.207
639         case ADDROF:
ragge
1.155
640                 rv = finduni(pcookie);
641                 break;
ragge
1.69
642
ragge
1.71
643         case CBRANCH:
644                 p1 = p->n_left;
645                 p2 = p->n_right;
gmcgarry
1.251
646                 p1->n_label = (int)p2->n_lval;
ragge
1.239
647                 (void)geninsn(p1FORCC);
ragge
1.187
648                 p->n_su = 0;
ragge
1.71
649                 break;
650
ragge
1.187
651         case FORCE/* XXX needed? */
ragge
1.239
652                 (void)geninsn(p->n_leftINREGS);
ragge
1.187
653                 p->n_su = 0/* su calculations traverse left */
ragge
1.71
654                 break;
655
ragge
1.216
656         case XASM:
657                 for (p1 = p->n_leftp1->n_op == CMp1 = p1->n_left)
ragge
1.239
658                         (void)geninsn(p1->n_rightFOREFF);
659                 (void)geninsn(p1FOREFF);
ragge
1.216
660                 break;  /* all stuff already done? */
661
662         case XARG:
663                 /* generate code for correct class here */
gmcgarry
1.250
664 #if 0
665                 geninsn(p->n_left1 << p->n_label);
666 #endif
ragge
1.216
667                 break;
668
ragge
1.69
669         default:
ragge
1.174
670                 comperr("geninsn: bad op %s, node %p"opst[o], p);
ragge
1.69
671         }
ragge
1.236
672         if (rv == FFAIL && !q)
ragge
1.160
673                 comperr("Cannot generate code, node %p op %s"p,opst[p->n_op]);
674         if (rv == FRETRY)
675                 goto again;
ragge
1.236
676 #ifdef PCC_DEBUG
plunky
1.278
677         if (o2debug) {
ragge
1.236
678                 printf("geninsn(%p, %s) rv %d\n"pprcook(cookie), rv);
679                 fwalk(pe2print0);
680         }
681 #endif
ragge
1.153
682         return rv;
ragge
1.69
683 }
684
ragge
1.72
685 /*
686  * Store a given subtree in a temporary location.
687  * Return an OREG node where it is located.
688  */
689 NODE *
690 store(NODE *p)
ragge
1.2
691 {
ragge
1.130
692         extern struct interpass *storesave;
693         struct interpass *ip;
694         NODE *q, *r;
695         int s;
ragge
1.49
696
ragge
1.130
697         s = BITOOR(freetemp(szty(p->n_type)));
698         q = mklnode(OREGsFPREGp->n_type);
699         r = mklnode(OREGsFPREGp->n_type);
700         ip = ipnode(mkbinode(ASSIGNqpp->n_type));
701
ragge
1.149
702         storesave = ip;
ragge
1.72
703         return r;
ragge
1.8
704 }
ragge
1.1
705
ragge
1.170
706 #ifdef PCC_DEBUG
707 #define CDEBUG(x) if (c2debug) printf x
708 #else
709 #define CDEBUG(x)
710 #endif
711
ragge
1.69
712 /*
ragge
1.188
713  * Do a register-register move if necessary.
ragge
1.270
714  * Called if a RLEFT or RRIGHT is found.
ragge
1.188
715  */
716 static void
717 ckmove(NODE *pNODE *q)
718 {
ragge
1.270
719         struct optab *t = &table[TBLIDX(p->n_su)];
720         int reg;
721
ragge
1.189
722         if (q->n_op != REG || p->n_reg == -1)
ragge
1.188
723                 return/* no register */
ragge
1.270
724
725         /* do we have a need for special reg? */
ragge
1.277
726         if ((t->needs & NSPECIAL) &&
727             (reg = rspecial(tp->n_left == q ? NLEFT : NRIGHT)) >= 0)
728                 ;
ragge
1.270
729         else
730                 reg = DECRA(p->n_reg0);
731
732         if (reg < 0 || reg == DECRA(q->n_reg0))
ragge
1.188
733                 return/* no move necessary */
ragge
1.270
734
ragge
1.190
735         CDEBUG(("rmove: node %p, %s -> %s\n"prnames[DECRA(q->n_reg0)],
ragge
1.270
736             rnames[reg]));
737         rmove(DECRA(q->n_reg0), regp->n_type);
738         q->n_reg = q->n_rval = reg;
ragge
1.188
739 }
740
741 /*
742  * Rewrite node to register after instruction emit.
ragge
1.75
743  */
744 static void
gmcgarry
1.224
745 rewrite(NODE *pint dorewriteint cookie)
ragge
1.75
746 {
ragge
1.79
747         NODE *l, *r;
748         int o;
749
ragge
1.80
750         l = getlr(p'L');
751         r = getlr(p'R');
ragge
1.79
752         o = p->n_op;
ragge
1.75
753         p->n_op = REG;
ragge
1.76
754         p->n_lval = 0;
ragge
1.95
755         p->n_name = "";
ragge
1.158
756
ragge
1.257
757         if (o == ASSIGN || o == STASG) {
ragge
1.190
758                 /* special rewrite care */
759                 int reg = DECRA(p->n_reg0);
ragge
1.191
760 #define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
ragge
1.190
761                 if (p->n_reg == -1)
762                         ;
ragge
1.191
763                 else if (TL(l) && (DECRA(l->n_reg0) == reg))
ragge
1.190
764                         ;
ragge
1.191
765                 else if (TL(r) && (DECRA(r->n_reg0) == reg))
ragge
1.190
766                         ;
ragge
1.191
767                 else if (TL(l))
ragge
1.190
768                         rmove(DECRA(l->n_reg0), regp->n_type);
ragge
1.191
769                 else if (TL(r))
ragge
1.190
770                         rmove(DECRA(r->n_reg0), regp->n_type);
771 #if 0
772                 else
773                         comperr("rewrite");
774 #endif
ragge
1.191
775 #undef TL
ragge
1.190
776         }
ragge
1.79
777         if (optype(o) != LTYPE)
778                 tfree(l);
779         if (optype(o) == BITYPE)
780                 tfree(r);
gmcgarry
1.224
781         if (dorewrite == 0)
ragge
1.190
782                 return;
mickey
1.205
783         CDEBUG(("rewrite: %p, reg %s\n"p,
784             p->n_reg == -1"<none>" : rnames[DECRA(p->n_reg0)]));
ragge
1.187
785         p->n_rval = DECRA(p->n_reg0);
ragge
1.75
786 }
787
ragge
1.228
788 #ifndef XASM_TARGARG
789 #define XASM_TARGARG(x,y) 0
790 #endif
791
ragge
1.216
792 /*
793  * printout extended assembler.
794  */
795 void
796 genxasm(NODE *p)
797 {
798         NODE *q, **nary;
799         int n = 1o = 0;
800         char *w;
801
ragge
1.228
802         if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) {
803                 for (q = p->n_leftq->n_op == CMq = q->n_left)
804                         n++;
ragge
1.254
805                 nary = tmpcalloc(sizeof(NODE *)*(n+1));
ragge
1.228
806                 o = n;
807                 for (q = p->n_leftq->n_op == CMq = q->n_left) {
808                         gencode(q->n_right->n_leftINREGS);
809                         nary[--o] = q->n_right;
810                 }
811                 gencode(q->n_leftINREGS);
812                 nary[--o] = q;
813         } else
814                 nary = 0;
ragge
1.216
815
816         w = p->n_name;
817         putchar('\t');
818         while (*w != 0) {
819                 if (*w == '%') {
ragge
1.225
820                         if (w[1] == '%')
821                                 putchar('%');
ragge
1.228
822                         else if (XASM_TARGARG(wnary))
823                                 ; /* handled by target */
ragge
1.225
824                         else if (w[1] < '0' || w[1] > (n + '0'))
ragge
1.228
825                                 uerror("bad xasm arg number %c"w[1]);
ragge
1.253
826                         else {
827                                 if (w[1] == (n + '0'))
828                                         q = nary[(int)w[1]-'0' - 1]; /* XXX */
829                                 else
830                                         q = nary[(int)w[1]-'0'];
831                                 adrput(stdoutq->n_left);
832                         }
ragge
1.216
833                         w++;
ragge
1.228
834                 } else if (*w == '\\') { /* Always 3-digit octal */
835                         int num = *++w - '0';
836                         num = (num << 3) + *++w - '0';
837                         num = (num << 3) + *++w - '0';
838                         putchar(num);
ragge
1.216
839                 } else
840                         putchar(*w);
841                 w++;
842         }
843         putchar('\n');
844 }
845
ragge
1.271
846 /*
847  * Allocate temporary registers for use while emitting this table entry.
848  */
849 static void
850 allo(NODE *pstruct optab *q)
851 {
852         extern int stktemp;
853         int in = ncnt(q->needs);
854
855         for (i = 0i < NRESCi++)
856                 if (resc[i].n_op != FREE)
857                         comperr("allo: used reg");
858         if (n == 0 && (q->needs & NTMASK) == 0)
859                 return;
860         for (i = 0i < n+1i++) {
861                 resc[i].n_op = REG;
862                 resc[i].n_type = p->n_type/* XXX should be correct type */
863                 resc[i].n_rval = DECRA(p->n_regi);
864                 resc[i].n_su = p->n_su/* ??? */
865         }
ragge
1.272
866         if (i > NRESC)
867                 comperr("allo: too many allocs");
ragge
1.271
868         if (q->needs & NTMASK) {
869                 resc[i].n_op = OREG;
870                 resc[i].n_lval = stktemp;
871                 resc[i].n_rval = FPREG;
872                 resc[i].n_su = p->n_su/* ??? */
873                 resc[i].n_name = "";
874         }
875 }
876
877 static void
878 afree(void)
879 {
880         int i;
881
882         for (i = 0i < NRESCi++)
883                 resc[i].n_op = FREE;
884 }
885
ragge
1.69
886 void
ragge
1.72
887 gencode(NODE *pint cookie)
ragge
1.69
888 {
889         struct optab *q = &table[TBLIDX(p->n_su)];
ragge
1.188