1 /*        Id: reader.c,v 1.299 2015/11/17 19:19:40 ragge Exp          */
2 /*        $NetBSD: reader.c,v 1.1.1.8 2016/02/09 20:29:20 plunky Exp $          */
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  * Redistributions of source code and documentation must retain the above
36  * copyright notice, this list of conditions and the following disclaimer.
37  * Redistributions in binary form must reproduce the above copyright
38  * notice, this list of conditionsand the following disclaimer in the
39  * documentation and/or other materials provided with the distribution.
40  * All advertising materials mentioning features or use of this software
41  * must display the following acknowledgement:
42  *        This product includes software developed or owned by Caldera
43  *        International, Inc.
44  * Neither the name of Caldera International, Inc. nor the names of other
45  * contributors may be used to endorse or promote products derived from
46  * this software without specific prior written permission.
47  *
48  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
49  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
50  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
53  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
57  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
58  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59  * POSSIBILITY OF SUCH DAMAGE.
60  */
61 
62 /*
63  * Everything is entered via pass2_compile().  No functions are
64  * allowed to recurse back into pass2_compile().
65  */
66 
67 # include "pass2.h"
68 
69 #include <string.h>
70 #include <stdarg.h>
71 #include <stdlib.h>
72 
73 /*        some storage declarations */
74 int nrecur;
75 int thisline;
76 int fregs;
77 int p2autooff, p2maxautooff;
78 
79 NODE *nodepole;
80 struct interpass prepole;
81 
82 void saveip(struct interpass *ip);
83 void deltemp(NODE *p, void *);
84 static void cvtemps(struct interpass *ipole, int op, int off);
85 static void fixxasm(struct p2env *);
86 
87 static void gencode(NODE *p, int cookie);
88 static void genxasm(NODE *p);
89 static void afree(void);
90 
91 struct p2env p2env;
92 
93 int crslab2 = 11;
94 /*
95  * Return a number for internal labels.
96  */
97 int
getlab2(void)98 getlab2(void)
99 {
100         crslab2++;
101           if (crslab2 < p2env.ipp->ip_lblnum)
102                     comperr("getlab2 %d outside boundaries %d-%d",
103                         crslab2, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum);
104           if (crslab2 >= p2env.epp->ip_lblnum)
105                     p2env.epp->ip_lblnum = crslab2+1;
106         return crslab2++;
107 }
108 
109 
110 #ifdef PCC_DEBUG
111 static int *lbldef, *lbluse;
112 static void
cktree(NODE * p,void * arg)113 cktree(NODE *p, void *arg)
114 {
115           int i;
116 
117           if (p->n_op > MAXOP)
118                     cerror("%p) op %d slipped through", p, p->n_op);
119 #ifndef FIELDOPS
120           if (p->n_op == FLD)
121                     cerror("%p) FLD slipped through", p);
122 #endif
123           if (BTYPE(p->n_type) > MAXTYPES)
124                     cerror("%p) type %x slipped through", p, p->n_type);
125           if (p->n_op == CBRANCH) {
126                      if (!logop(p->n_left->n_op))
127                               cerror("%p) not logop branch", p);
128                     i = (int)getlval(p->n_right);
129                     if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
130                               cerror("%p) label %d outside boundaries %d-%d",
131                                   p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum);
132                     lbluse[i-p2env.ipp->ip_lblnum] = 1;
133           }
134           if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
135                     cerror("%p) asgop %d slipped through", p, p->n_op);
136           if (p->n_op == TEMP &&
137               (regno(p) < p2env.ipp->ip_tmpnum || regno(p) >= p2env.epp->ip_tmpnum))
138                     cerror("%p) temporary %d outside boundaries %d-%d",
139                         p, regno(p), p2env.ipp->ip_tmpnum, p2env.epp->ip_tmpnum);
140           if (p->n_op == GOTO && p->n_left->n_op == ICON) {
141                     i = (int)getlval(p->n_left);
142                     if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
143                               cerror("%p) label %d outside boundaries %d-%d",
144                                   p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum);
145                     lbluse[i-p2env.ipp->ip_lblnum] = 1;
146           }
147 }
148 
149 /*
150  * Check that the trees are in a suitable state for pass2.
151  */
152 static void
sanitychecks(struct p2env * p2e)153 sanitychecks(struct p2env *p2e)
154 {
155           struct interpass *ip;
156           int i, sz;
157 
158           sz = sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum);
159           lbldef = xcalloc(sz, 1);
160           lbluse = xcalloc(sz, 1);
161 
162           DLIST_FOREACH(ip, &p2env.ipole, qelem) {
163                     if (ip->type == IP_DEFLAB) {
164                               i = ip->ip_lbl;
165                               if (i < p2e->ipp->ip_lblnum || i >= p2e->epp->ip_lblnum)
166                                         cerror("label %d outside boundaries %d-%d",
167                                             i, p2e->ipp->ip_lblnum, p2e->epp->ip_lblnum);
168                               lbldef[i-p2e->ipp->ip_lblnum] = 1;
169                     }
170                     if (ip->type == IP_NODE)
171                               walkf(ip->ip_node, cktree, 0);
172           }
173           for (i = 0; i < (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); i++)
174                     if (lbluse[i] != 0 && lbldef[i] == 0)
175                               cerror("internal label %d not defined",
176                                   i + p2e->ipp->ip_lblnum);
177 
178           free(lbldef);
179           free(lbluse);
180 }
181 #endif
182 
183 /*
184  * Look if a temporary comes from a on-stack argument, in that case
185  * use the already existing stack position instead of moving it to
186  * a new place, and remove the move-to-temp statement.
187  */
188 static int
stkarg(int tnr,int (* soff)[2])189 stkarg(int tnr, int (*soff)[2])
190 {
191           struct p2env *p2e = &p2env;
192           struct interpass *ip;
193           NODE *p;
194 
195           ip = DLIST_NEXT((struct interpass *)p2e->ipp, qelem);
196           while (ip->type != IP_DEFLAB) /* search for first DEFLAB */
197                     ip = DLIST_NEXT(ip, qelem);
198 
199           ip = DLIST_NEXT(ip, qelem); /* first NODE */
200 
201           for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
202                     if (ip->type != IP_NODE)
203                               continue;
204 
205                     p = ip->ip_node;
206                     if (p->n_op == XASM)
207                               continue; /* XXX - hack for x86 PIC */
208 #ifdef notdef
209                     if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
210                               comperr("temparg");
211 #endif
212                     if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
213                               continue; /* unknown tree */
214 
215                     if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
216                               continue; /* arg in register */
217                     if (tnr != regno(p->n_left))
218                               continue; /* wrong assign */
219                     p = p->n_right;
220                     if (p->n_op == UMUL &&
221                         p->n_left->n_op == PLUS &&
222                         p->n_left->n_left->n_op == REG &&
223                         p->n_left->n_right->n_op == ICON) {
224                               soff[0][0] = regno(p->n_left->n_left);
225                               soff[0][1] = (int)getlval(p->n_left->n_right);
226                     } else if (p->n_op == OREG) {
227                               soff[0][0] = regno(p);
228                               soff[0][1] = (int)getlval(p);
229                     } else
230                               comperr("stkarg: bad arg");
231                     tfree(ip->ip_node);
232                     DLIST_REMOVE(ip, qelem);
233                     return 1;
234           }
235           return 0;
236 }
237 
238 /*
239  * See if an ADDROF is somewhere inside the expression tree.
240  * If so, fill in the offset table.
241  */
242 static void
findaof(NODE * p,void * arg)243 findaof(NODE *p, void *arg)
244 {
245           int (*aof)[2] = arg;
246           int tnr;
247 
248           if (p->n_op != ADDROF || p->n_left->n_op != TEMP)
249                     return;
250           tnr = regno(p->n_left);
251           if (aof[tnr][0])
252                     return; /* already gotten stack address */
253           if (stkarg(tnr, &aof[tnr]))
254                     return;   /* argument was on stack */
255           aof[tnr][0] = FPREG;
256           aof[tnr][1] = freetemp(szty(p->n_left->n_type));
257 }
258 
259 /*
260  * Check if a node has side effects.
261  */
262 static int
isuseless(NODE * n)263 isuseless(NODE *n)
264 {
265           switch (n->n_op) {
266           case XASM:
267           case FUNARG:
268           case UCALL:
269           case UFORTCALL:
270           case FORCE:
271           case ASSIGN:
272           case CALL:
273           case FORTCALL:
274           case CBRANCH:
275           case RETURN:
276           case GOTO:
277           case STCALL:
278           case USTCALL:
279           case STASG:
280           case STARG:
281                     return 0;
282           default:
283                     return 1;
284           }
285 }
286 
287 /*
288  * Delete statements with no meaning (like a+b; or 513.4;)
289  */
290 NODE *
deluseless(NODE * p)291 deluseless(NODE *p)
292 {
293           struct interpass *ip;
294           NODE *l, *r;
295 
296           if (optype(p->n_op) == LTYPE) {
297                     nfree(p);
298                     return NULL;
299           }
300           if (isuseless(p) == 0)
301                     return p;
302 
303           if (optype(p->n_op) == UTYPE) {
304                     l = p->n_left;
305                     nfree(p);
306                     return deluseless(l);
307           }
308 
309           /* Be sure that both leaves may be valid */
310           l = deluseless(p->n_left);
311           r = deluseless(p->n_right);
312           nfree(p);
313           if (l && r) {
314                     ip = ipnode(l);
315                     DLIST_INSERT_AFTER(&prepole, ip, qelem);
316                     return r;
317           } else if (l)
318                     return l;
319           else if (r)
320                     return r;
321           return NULL;
322 }
323 
324 #ifdef PASS2
325 
326 #define   SKIPWS(p) while (*p == ' ') p++
327 #define   SZIBUF    256
328 static int inpline;
329 static char inpbuf[SZIBUF];
330 static char *
rdline(void)331 rdline(void)
332 {
333           int l;
334 
335           if (fgets(inpbuf, sizeof(inpbuf), stdin) == NULL)
336                     return NULL;
337           inpline++;
338           l = strlen(inpbuf);
339           if (inpbuf[0] < 33 || inpbuf[1] != ' ' || inpbuf[l-1] != '\n')
340                     comperr("sync error in-line %d string '%s'", inpline, inpbuf);
341           inpbuf[l-1] = 0;
342           return inpbuf;
343 }
344 
345 /*
346  * Read an int and traverse over it. count up s.
347  */
348 static int
rdint(char ** s)349 rdint(char **s)
350 {
351           char *p = *s;
352           int rv;
353 
354           SKIPWS(p);
355           rv = atoi(p);
356           if (*p == '-' || *p == '+') p++;
357           while (*p >= '0' && *p <= '9') p++;
358           *s = p;
359           return rv;
360 }
361 
362 static struct attr *
rdattr(char ** p)363 rdattr(char **p)
364 {
365           struct attr *ap, *app = NULL;
366           int i, a, sz;
367 
368           (*p)++; /* skip + */
369 onemore:
370           a = rdint(p);
371           sz = rdint(p);
372           ap = attr_new(a, sz);
373           for (i = 0; i < sz; i++)
374                     ap->iarg(i) = rdint(p);
375           ap->next = app;
376           app = ap;
377           SKIPWS((*p));
378           if (**p != 0)
379                     goto onemore;
380 
381           return app;
382 }
383 
384 /*
385  * Read in an indentifier and save on tmp heap.  Return saved string.
386  */
387 static char *
rdstr(char ** p)388 rdstr(char **p)
389 {
390           char *t, *s = *p;
391           int sz;
392 
393           SKIPWS(s);
394           *p = s;
395           for (sz = 0; *s && *s != ' '; s++, sz++)
396                     ;
397           t = tmpalloc(sz+1);
398           memcpy(t, *p, sz);
399           t[sz] = 0;
400           *p = s;
401           return t;
402 }
403 
404 /*
405  * Read and check node structs from pass1.
406  */
407 static NODE *
rdnode(char * s)408 rdnode(char *s)
409 {
410           NODE *p = talloc();
411           int ty;
412 
413           if (s[0] != '"')
414                     comperr("rdnode sync error");
415           s++; s++;
416           p->n_regw = NULL;
417           p->n_ap = NULL;
418           p->n_su = p->n_lval = p->n_rval = 0;
419           p->n_op = rdint(&s);
420           p->n_type = rdint(&s);
421           p->n_qual = rdint(&s);
422           p->n_name = "";
423           SKIPWS(s);
424           ty = optype(p->n_op);
425           if (p->n_op == XASM) {
426                     int i = strlen(s);
427                     p->n_name = tmpalloc(i+1);
428                     memcpy(p->n_name, s, i);
429                     p->n_name[i] = 0;
430                     s += i;
431           }
432           if (ty == UTYPE) {
433                     p->n_rval = rdint(&s);
434           } else if (ty == LTYPE) {
435                     p->n_lval = strtoll(s, &s, 10);
436                     if (p->n_op == NAME || p->n_op == ICON) {
437                               SKIPWS(s);
438                               if (*s && *s != '+')
439                                         p->n_name = rdstr(&s);
440                     } else
441                               p->n_rval = rdint(&s);
442           }
443           SKIPWS(s);
444           if (p->n_op == XARG) {
445                     int i = strlen(s);
446                     p->n_name = tmpalloc(i+1);
447                     memcpy(p->n_name, s, i);
448                     p->n_name[i] = 0;
449                     s += i;
450           }
451           if (*s == '+')
452                     p->n_ap = rdattr(&s);
453           SKIPWS(s);
454           if (*s)
455                     comperr("in-line %d failed read, buf '%s'", inpline, inpbuf);
456           if (ty != LTYPE)
457                     p->n_left = rdnode(rdline());
458           if (ty == BITYPE)
459                     p->n_right = rdnode(rdline());
460           return p;
461 }
462 
463 /*
464  * Read everything from pass1.
465  */
466 void
mainp2()467 mainp2()
468 {
469           static int foo[] = { 0 };
470           struct interpass_prolog *ipp;
471           struct interpass *ip;
472           char nam[SZIBUF], *p, *b;
473           extern char *ftitle;
474 
475           while ((p = rdline()) != NULL) {
476                     b = p++;
477                     p++;
478 
479                     switch (*b) {
480                     case '*': /* pass thru line */
481                               printf("%s\n", p);
482                               break;
483                     case '&': /* current filename */
484                               free(ftitle);
485                               ftitle = xstrdup(p);
486                               break;
487                     case '#':
488                               lineno = atoi(p);
489                               break;
490                     case '"':
491                               ip = malloc(sizeof(struct interpass));
492                               ip->type = IP_NODE;
493                               ip->ip_node = rdnode(b);
494                               pass2_compile(ip);
495                               break;
496                     case '^':
497                               ip = malloc(sizeof(struct interpass));
498                               ip->type = IP_DEFLAB;
499                               ip->ip_lbl = atoi(p);
500                               pass2_compile(ip);
501                               break;
502                     case '!': /* prolog */
503                               ipp = malloc(sizeof(struct interpass_prolog));
504                               ip = (void *)ipp;
505                               ip->type = IP_PROLOG;
506                               sscanf(p, "%d %d %d %d %d %s", &ipp->ipp_type,
507                                   &ipp->ipp_vis, &ip->ip_lbl, &ipp->ip_tmpnum,
508                                   &ipp->ip_lblnum, nam);
509                               ipp->ipp_name = xstrdup(nam);
510                               memset(ipp->ipp_regs, -1, sizeof(ipp->ipp_regs));
511                               ipp->ipp_autos = -1;
512                               ipp->ip_labels = foo;
513 #ifdef TARGET_IPP_MEMBERS
514                               if (*(p = rdline()) != '(')
515                                         comperr("target member error");
516                               p += 2;
517                               target_members_read_prolog(ipp);
518                               SKIPWS(p);
519                               if (*p)
520                                         comperr("bad prolog '%s' '%s'", p, inpbuf);
521 #endif
522                               pass2_compile((struct interpass *)ipp);
523                               break;
524 
525                     case '%': /* epilog */
526                               ipp = malloc(sizeof(struct interpass_prolog));
527                               ip = (void *)ipp;
528                               ip->type = IP_EPILOG;
529                               ipp->ipp_autos = rdint(&p);
530                               ip->ip_lbl = rdint(&p);
531                               ipp->ip_tmpnum = rdint(&p);
532                               ipp->ip_lblnum = rdint(&p);
533                               ipp->ipp_name = rdstr(&p);
534                               memset(ipp->ipp_regs, 0, sizeof(ipp->ipp_regs));
535                               SKIPWS(p);
536                               if (*p == '+') {
537                                         int num, i;
538                                         p++;
539                                         num = rdint(&p) + 1;
540                                         ipp->ip_labels = tmpalloc(sizeof(int)*num);
541                                         for (i = 0; i < num; i++)
542                                                   ipp->ip_labels[i] = rdint(&p);
543                                         ipp->ip_labels[num] = 0;
544                               } else
545                                         ipp->ip_labels = foo;
546                               SKIPWS(p);
547                               if (*p)
548                                         comperr("bad epilog '%s' '%s'", p, inpbuf);
549 #ifdef TARGET_IPP_MEMBERS
550                               if (*(p = rdline()) != ')')
551                                         comperr("target epi member error");
552                               p += 2;
553                               target_members_read_epilog(ipp);
554                               SKIPWS(p);
555                               if (*p)
556                                         comperr("bad epilog2 '%s' '%s'", p, inpbuf);
557 #endif
558                               pass2_compile((struct interpass *)ipp);
559                               break;
560 
561                     default:
562                               comperr("bad string %s", b);
563                     }
564           }
565 }
566 
567 
568 #endif
569 
570 /*
571  * Receives interpass structs from pass1.
572  */
573 void
pass2_compile(struct interpass * ip)574 pass2_compile(struct interpass *ip)
575 {
576           void deljumps(struct p2env *);
577           struct p2env *p2e = &p2env;
578           int (*addrp)[2];
579 
580           if (ip->type == IP_PROLOG) {
581                     memset(p2e, 0, sizeof(struct p2env));
582                     p2e->ipp = (struct interpass_prolog *)ip;
583                     if (crslab2 < p2e->ipp->ip_lblnum)
584                               crslab2 = p2e->ipp->ip_lblnum;
585                     DLIST_INIT(&p2e->ipole, qelem);
586           }
587           DLIST_INSERT_BEFORE(&p2e->ipole, ip, qelem);
588           if (ip->type != IP_EPILOG)
589                     return;
590 
591 #ifdef PCC_DEBUG
592           if (e2debug) {
593                     printf("Entering pass2\n");
594                     printip(&p2e->ipole);
595           }
596 #endif
597 
598           afree();
599           p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipole, qelem);
600           p2maxautooff = p2autooff = p2e->epp->ipp_autos;
601 
602 #ifdef PCC_DEBUG
603           sanitychecks(p2e);
604 #endif
605           myreader(&p2e->ipole); /* local massage of input */
606 
607           /*
608            * Do initial modification of the trees.  Two loops;
609            * - first, search for ADDROF of TEMPs, these must be
610            *   converterd to OREGs on stack.
611            * - second, do the actual conversions, in case of not xtemps
612            *   convert all temporaries to stack references.
613            */
614 
615           if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
616                     addrp = xcalloc(sizeof(*addrp),
617                         (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
618                     addrp -= p2e->ipp->ip_tmpnum;
619           } else
620                     addrp = NULL;
621           if (xtemps) {
622                     DLIST_FOREACH(ip, &p2e->ipole, qelem) {
623                               if (ip->type == IP_NODE)
624                                         walkf(ip->ip_node, findaof, addrp);
625                     }
626           }
627           DLIST_FOREACH(ip, &p2e->ipole, qelem)
628                     if (ip->type == IP_NODE)
629                               walkf(ip->ip_node, deltemp, addrp);
630           if (addrp)
631                     free(addrp + p2e->ipp->ip_tmpnum);
632 
633 #ifdef PCC_DEBUG
634           if (e2debug) {
635                     printf("Efter ADDROF/TEMP\n");
636                     printip(&p2e->ipole);
637           }
638 #endif
639 
640           DLIST_INIT(&prepole, qelem);
641           DLIST_FOREACH(ip, &p2e->ipole, qelem) {
642                     if (ip->type != IP_NODE)
643                               continue;
644                     canon(ip->ip_node);
645                     if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) {
646                               DLIST_REMOVE(ip, qelem);
647                     } else while (!DLIST_ISEMPTY(&prepole, qelem)) {
648                               struct interpass *tipp;
649 
650                               tipp = DLIST_NEXT(&prepole, qelem);
651                               DLIST_REMOVE(tipp, qelem);
652                               DLIST_INSERT_BEFORE(ip, tipp, qelem);
653                     }
654           }
655 
656           fixxasm(p2e); /* setup for extended asm */
657 
658           optimize(p2e);
659           ngenregs(p2e);
660 
661           if (xtemps && xdeljumps)
662                     deljumps(p2e);
663 
664           DLIST_FOREACH(ip, &p2e->ipole, qelem)
665                     emit(ip);
666 }
667 
668 void
emit(struct interpass * ip)669 emit(struct interpass *ip)
670 {
671           NODE *p, *r;
672           struct optab *op;
673           int o;
674 
675           switch (ip->type) {
676           case IP_NODE:
677                     p = ip->ip_node;
678 
679                     nodepole = p;
680                     canon(p); /* may convert stuff after genregs */
681 #ifdef PCC_DEBUG
682                     if (c2debug > 1) {
683                               printf("emit IP_NODE:\n");
684                               fwalk(p, e2print, 0);
685                     }
686 #endif
687                     switch (p->n_op) {
688                     case CBRANCH:
689                               /* Only emit branch insn if RESCC */
690                               /* careful when an OPLOG has been elided */
691                               if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
692                                         op = &table[TBLIDX(p->n_left->n_left->n_su)];
693                                         r = p->n_left;
694                               } else {
695                                         op = &table[TBLIDX(p->n_left->n_su)];
696                                         r = p;
697                               }
698                               if (op->rewrite & RESCC) {
699                                         o = p->n_left->n_op;
700                                         gencode(r, FORCC);
701                                         cbgen(o, getlval(p->n_right));
702                               } else {
703                                         gencode(r, FORCC);
704                               }
705                               break;
706                     case FORCE:
707                               gencode(p->n_left, INREGS);
708                               break;
709                     case XASM:
710                               genxasm(p);
711                               break;
712                     default:
713                               if (p->n_op != REG || p->n_type != VOID) /* XXX */
714                                         gencode(p, FOREFF); /* Emit instructions */
715                     }
716 
717                     tfree(p);
718                     break;
719           case IP_PROLOG:
720                     prologue((struct interpass_prolog *)ip);
721                     break;
722           case IP_EPILOG:
723                     eoftn((struct interpass_prolog *)ip);
724                     p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
725                     break;
726           case IP_DEFLAB:
727                     deflab(ip->ip_lbl);
728                     break;
729           case IP_ASM:
730                     printf("%s", ip->ip_asm);
731                     break;
732           default:
733                     cerror("emit %d", ip->type);
734           }
735 }
736 
737 #ifdef PCC_DEBUG
738 char *cnames[] = {
739           "SANY",
740           "SAREG",
741           "SBREG",
742           "SCREG",
743           "SDREG",
744           "SCC",
745           "SNAME",
746           "SCON",
747           "SFLD",
748           "SOREG",
749           "STARNM",
750           "STARREG",
751           "INTEMP",
752           "FORARG",
753           "SWADD",
754           0,
755 };
756 
757 /*
758  * print a nice-looking description of cookie
759  */
760 char *
prcook(int cookie)761 prcook(int cookie)
762 {
763           static char buf[50];
764           int i, flag;
765 
766           if (cookie & SPECIAL) {
767                     switch (cookie) {
768                     case SZERO:
769                               return "SZERO";
770                     case SONE:
771                               return "SONE";
772                     case SMONE:
773                               return "SMONE";
774                     default:
775                               snprintf(buf, sizeof(buf), "SPECIAL+%d", cookie & ~SPECIAL);
776                               return buf;
777                     }
778           }
779 
780           flag = 0;
781           buf[0] = 0;
782           for (i = 0; cnames[i]; ++i) {
783                     if (cookie & (1<<i)) {
784                               if (flag)
785                                         strlcat(buf, "|", sizeof(buf));
786                               ++flag;
787                               strlcat(buf, cnames[i], sizeof(buf));
788                     }
789           }
790           return buf;
791 }
792 #endif
793 
794 int
geninsn(NODE * p,int cookie)795 geninsn(NODE *p, int cookie)
796 {
797           NODE *p1, *p2;
798           int q, o, rv = 0;
799 
800 #ifdef PCC_DEBUG
801           if (o2debug) {
802                     printf("geninsn(%p, %s)\n", p, prcook(cookie));
803                     fwalk(p, e2print, 0);
804           }
805 #endif
806 
807           q = cookie & QUIET;
808           cookie &= ~QUIET; /* XXX - should not be necessary */
809 
810 again:    switch (o = p->n_op) {
811           case EQ:
812           case NE:
813           case LE:
814           case LT:
815           case GE:
816           case GT:
817           case ULE:
818           case ULT:
819           case UGE:
820           case UGT:
821                     p1 = p->n_left;
822                     p2 = p->n_right;
823                     if (p2->n_op == ICON && getlval(p2) == 0 && *p2->n_name == 0 &&
824                         (dope[p1->n_op] & (FLOFLG|DIVFLG|SIMPFLG|SHFFLG))) {
825 #ifdef mach_pdp11 /* XXX all targets? */
826                               if ((rv = geninsn(p1, FORCC|QUIET)) != FFAIL)
827                                         break;
828 #else
829                               if (findops(p1, FORCC) > 0)
830                                         break;
831 #endif
832                     }
833                     rv = relops(p);
834                     break;
835 
836           case PLUS:
837           case MINUS:
838           case MUL:
839           case DIV:
840           case MOD:
841           case AND:
842           case OR:
843           case ER:
844           case LS:
845           case RS:
846                     rv = findops(p, cookie);
847                     break;
848 
849           case ASSIGN:
850 #ifdef FINDMOPS
851                     if ((rv = findmops(p, cookie)) != FFAIL)
852                               break;
853                     /* FALLTHROUGH */
854 #endif
855           case STASG:
856                     rv = findasg(p, cookie);
857                     break;
858 
859           case UMUL: /* May turn into an OREG */
860                     rv = findumul(p, cookie);
861                     break;
862 
863           case REG:
864           case TEMP:
865           case NAME:
866           case ICON:
867           case FCON:
868           case OREG:
869                     rv = findleaf(p, cookie);
870                     break;
871 
872           case STCALL:
873           case CALL:
874                     /* CALL arguments are handled special */
875                     for (p1 = p->n_right; p1->n_op == CM; p1 = p1->n_left)
876                               (void)geninsn(p1->n_right, FOREFF);
877                     (void)geninsn(p1, FOREFF);
878                     /* FALLTHROUGH */
879           case FLD:
880           case COMPL:
881           case UMINUS:
882           case PCONV:
883           case SCONV:
884 /*        case INIT: */
885           case GOTO:
886           case FUNARG:
887           case STARG:
888           case UCALL:
889           case USTCALL:
890           case ADDROF:
891                     rv = finduni(p, cookie);
892                     break;
893 
894           case CBRANCH:
895                     p1 = p->n_left;
896                     p2 = p->n_right;
897                     p1->n_label = (int)getlval(p2);
898                     (void)geninsn(p1, FORCC);
899                     p->n_su = 0;
900                     break;
901 
902           case FORCE: /* XXX needed? */
903                     (void)geninsn(p->n_left, INREGS);
904                     p->n_su = 0; /* su calculations traverse left */
905                     break;
906 
907           case XASM:
908                     for (p1 = p->n_left; p1->n_op == CM; p1 = p1->n_left)
909                               (void)geninsn(p1->n_right, FOREFF);
910                     (void)geninsn(p1, FOREFF);
911                     break;    /* all stuff already done? */
912 
913           case XARG:
914                     /* generate code for correct class here */
915                     break;
916 
917           default:
918                     comperr("geninsn: bad op %s, node %p", opst[o], p);
919           }
920           if (rv == FFAIL && !q)
921                     comperr("Cannot generate code, node %p op %s", p,opst[p->n_op]);
922           if (rv == FRETRY)
923                     goto again;
924 #ifdef PCC_DEBUG
925           if (o2debug) {
926                     printf("geninsn(%p, %s) rv %d\n", p, prcook(cookie), rv);
927                     fwalk(p, e2print, 0);
928           }
929 #endif
930           return rv;
931 }
932 
933 #ifdef PCC_DEBUG
934 #define   CDEBUG(x) if (c2debug) printf x
935 #else
936 #define   CDEBUG(x)
937 #endif
938 
939 /*
940  * Do a register-register move if necessary.
941  * Called if a RLEFT or RRIGHT is found.
942  */
943 static void
ckmove(NODE * p,NODE * q)944 ckmove(NODE *p, NODE *q)
945 {
946           struct optab *t = &table[TBLIDX(p->n_su)];
947           int reg;
948 
949           if (q->n_op != REG || p->n_reg == -1)
950                     return; /* no register */
951 
952           /* do we have a need for special reg? */
953           if ((t->needs & NSPECIAL) &&
954               (reg = rspecial(t, p->n_left == q ? NLEFT : NRIGHT)) >= 0)
955                     ;
956           else
957                     reg = DECRA(p->n_reg, 0);
958 
959           if (reg < 0 || reg == DECRA(q->n_reg, 0))
960                     return; /* no move necessary */
961 
962           CDEBUG(("rmove: node %p, %s -> %s\n", p, rnames[DECRA(q->n_reg, 0)],
963               rnames[reg]));
964           rmove(DECRA(q->n_reg, 0), reg, p->n_type);
965           q->n_reg = q->n_rval = reg;
966 }
967 
968 /*
969  * Rewrite node to register after instruction emit.
970  */
971 static void
rewrite(NODE * p,int dorewrite,int cookie)972 rewrite(NODE *p, int dorewrite, int cookie)
973 {
974           NODE *l, *r;
975           int o;
976 
977           l = getlr(p, 'L');
978           r = getlr(p, 'R');
979           o = p->n_op;
980           p->n_op = REG;
981           setlval(p, 0);
982           p->n_name = "";
983 
984           if (o == ASSIGN || o == STASG) {
985                     /* special rewrite care */
986                     int reg = DECRA(p->n_reg, 0);
987 #define   TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
988                     if (p->n_reg == -1)
989                               ;
990                     else if (TL(l) && (DECRA(l->n_reg, 0) == reg))
991                               ;
992                     else if (TL(r) && (DECRA(r->n_reg, 0) == reg))
993                               ;
994                     else if (TL(l))
995                               rmove(DECRA(l->n_reg, 0), reg, p->n_type);
996                     else if (TL(r))
997                               rmove(DECRA(r->n_reg, 0), reg, p->n_type);
998 #if 0
999                     else
1000                               comperr("rewrite");
1001 #endif
1002 #undef TL
1003           }
1004           if (optype(o) != LTYPE)
1005                     tfree(l);
1006           if (optype(o) == BITYPE)
1007                     tfree(r);
1008           if (dorewrite == 0)
1009                     return;
1010           CDEBUG(("rewrite: %p, reg %s\n", p,
1011               p->n_reg == -1? "<none>" : rnames[DECRA(p->n_reg, 0)]));
1012           p->n_rval = DECRA(p->n_reg, 0);
1013 }
1014 
1015 #ifndef XASM_TARGARG
1016 #define   XASM_TARGARG(x,y) 0
1017 #endif
1018 
1019 /*
1020  * printout extended assembler.
1021  */
1022 void
genxasm(NODE * p)1023 genxasm(NODE *p)
1024 {
1025           NODE *q, **nary;
1026           int n = 1, o = 0, v = 0;
1027           char *w;
1028 
1029           if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) {
1030                     for (q = p->n_left; q->n_op == CM; q = q->n_left)
1031                               n++;
1032                     nary = tmpcalloc(sizeof(NODE *)*(n+1));
1033                     o = n;
1034                     for (q = p->n_left; q->n_op == CM; q = q->n_left) {
1035                               gencode(q->n_right->n_left, INREGS);
1036                               nary[--o] = q->n_right;
1037                     }
1038                     gencode(q->n_left, INREGS);
1039                     nary[--o] = q;
1040           } else
1041                     nary = 0;
1042 
1043           w = p->n_name;
1044           putchar('\t');
1045           while (*w != 0) {
1046                     if (*w == '%') {
1047                               if (w[1] == '%')
1048                                         putchar('%');
1049                               else if (XASM_TARGARG(w, nary))
1050                                         ; /* handled by target */
1051                               else if (w[1] == '=') {
1052                                         if (v == 0) v = getlab2();
1053                                         printf("%d", v);
1054                               } else if (w[1] == 'c') {
1055                                         q = nary[(int)w[2]-'0'];
1056                                         if (q->n_left->n_op != ICON)
1057                                                   uerror("impossible constraint");
1058                                         printf(CONFMT, getlval(q->n_left));
1059                                         w++;
1060                               } else if (w[1] < '0' || w[1] > (n + '0'))
1061                                         uerror("bad xasm arg number %c", w[1]);
1062                               else {
1063                                         if (w[1] == (n + '0'))
1064                                                   q = nary[(int)w[1]-'0' - 1]; /* XXX */
1065                                         else
1066                                                   q = nary[(int)w[1]-'0'];
1067                                         adrput(stdout, q->n_left);
1068                               }
1069                               w++;
1070                     } else if (*w == '\\') { /* Always 3-digit octal */
1071                               int num = *++w - '0';
1072                               num = (num << 3) + *++w - '0';
1073                               num = (num << 3) + *++w - '0';
1074                               putchar(num);
1075                     } else
1076                               putchar(*w);
1077                     w++;
1078           }
1079           putchar('\n');
1080 }
1081 
1082 /*
1083  * Allocate temporary registers for use while emitting this table entry.
1084  */
1085 static void
allo(NODE * p,struct optab * q)1086 allo(NODE *p, struct optab *q)
1087 {
1088           extern int stktemp;
1089           int i, n = ncnt(q->needs);
1090 
1091           for (i = 0; i < NRESC; i++)
1092                     if (resc[i].n_op != FREE)
1093                               comperr("allo: used reg");
1094           if (n == 0 && (q->needs & NTMASK) == 0)
1095                     return;
1096           for (i = 0; i < n+1; i++) {
1097                     resc[i].n_op = REG;
1098                     resc[i].n_type = p->n_type; /* XXX should be correct type */
1099                     resc[i].n_rval = DECRA(p->n_reg, i);
1100                     resc[i].n_su = p->n_su; /* ??? */
1101           }
1102           if (i > NRESC)
1103                     comperr("allo: too many allocs");
1104           if (q->needs & NTMASK) {
1105 #ifdef    MYALLOTEMP
1106                     MYALLOTEMP(resc[i], stktemp);
1107 #else
1108                     resc[i].n_op = OREG;
1109                     setlval(&resc[i], stktemp);
1110                     resc[i].n_rval = FPREG;
1111                     resc[i].n_su = p->n_su; /* ??? */
1112                     resc[i].n_name = "";
1113 #endif
1114           }
1115 }
1116 
1117 static void
afree(void)1118 afree(void)
1119 {
1120           int i;
1121 
1122           for (i = 0; i < NRESC; i++)
1123                     resc[i].n_op = FREE;
1124 }
1125 
1126 void
gencode(NODE * p,int cookie)1127 gencode(NODE *p, int cookie)
1128 {
1129           struct optab *q = &table[TBLIDX(p->n_su)];
1130           NODE *p1, *l, *r;
1131           int o = optype(p->n_op);
1132 #ifdef FINDMOPS
1133           int ismops = (p->n_op == ASSIGN && (p->n_su & ISMOPS));
1134 #endif
1135 
1136           l = p->n_left;
1137           r = p->n_right;
1138 
1139           if (TBLIDX(p->n_su) == 0) {
1140                     if (o == BITYPE && (p->n_su & DORIGHT))
1141                               gencode(r, 0);
1142                     if (optype(p->n_op) != LTYPE)
1143                               gencode(l, 0);
1144                     if (o == BITYPE && !(p->n_su & DORIGHT))
1145                               gencode(r, 0);
1146                     return;
1147           }
1148 
1149           CDEBUG(("gencode: node %p\n", p));
1150 
1151           if (p->n_op == REG && DECRA(p->n_reg, 0) == p->n_rval)
1152                     return; /* meaningless move to itself */
1153 
1154           if (callop(p->n_op))
1155                     lastcall(p); /* last chance before function args */
1156           if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL) {
1157                     /* Print out arguments first */
1158                     for (p1 = r; p1->n_op == CM; p1 = p1->n_left)
1159                               gencode(p1->n_right, FOREFF);
1160                     gencode(p1, FOREFF);
1161                     o = UTYPE; /* avoid going down again */
1162           }
1163 
1164           if (o == BITYPE && (p->n_su & DORIGHT)) {
1165                     gencode(r, INREGS);
1166                     if (q->rewrite & RRIGHT)
1167                               ckmove(p, r);
1168           }
1169           if (o != LTYPE) {
1170                     gencode(l, INREGS);
1171 #ifdef FINDMOPS
1172                     if (ismops)
1173                               ;
1174                     else
1175 #endif
1176                          if (q->rewrite & RLEFT)
1177                               ckmove(p, l);
1178           }
1179           if (o == BITYPE && !(p->n_su & DORIGHT)) {
1180                     gencode(r, INREGS);
1181                     if (q->rewrite & RRIGHT)
1182                               ckmove(p, r);
1183           }
1184 
1185 #ifdef FINDMOPS
1186           if (ismops) {
1187                     /* reduce right tree to make expand() work */
1188                     if (optype(r->n_op) != LTYPE) {
1189                               p->n_op = r->n_op;
1190                               r = tcopy(r->n_right);
1191                               tfree(p->n_right);
1192                               p->n_right = r;
1193                     }
1194           }
1195 #endif
1196 
1197           canon(p);
1198 
1199           if (q->needs & NSPECIAL) {
1200                     int rr = rspecial(q, NRIGHT);
1201                     int lr = rspecial(q, NLEFT);
1202 
1203                     if (rr >= 0) {
1204 #ifdef PCC_DEBUG
1205                               if (optype(p->n_op) != BITYPE)
1206                                         comperr("gencode: rspecial borked");
1207 #endif
1208                               if (r->n_op != REG)
1209                                         comperr("gencode: rop != REG");
1210                               if (rr != r->n_rval)
1211                                         rmove(r->n_rval, rr, r->n_type);
1212                               r->n_rval = r->n_reg = rr;
1213                     }
1214                     if (lr >= 0) {
1215                               if (l->n_op != REG)
1216                                         comperr("gencode: %p lop != REG", p);
1217                               if (lr != l->n_rval)
1218                                         rmove(l->n_rval, lr, l->n_type);
1219                               l->n_rval = l->n_reg = lr;
1220                     }
1221                     if (rr >= 0 && lr >= 0 && (l->n_reg == rr || r->n_reg == lr))
1222                               comperr("gencode: cross-reg-move");
1223           }
1224 
1225           if (p->n_op == ASSIGN &&
1226               p->n_left->n_op == REG && p->n_right->n_op == REG &&
1227               p->n_left->n_rval == p->n_right->n_rval &&
1228               (p->n_su & RVCC) == 0) { /* XXX should check if necessary */
1229                     /* do not emit anything */
1230                     CDEBUG(("gencode(%p) assign nothing\n", p));
1231                     rewrite(p, q->rewrite, cookie);
1232                     return;
1233           }
1234 
1235           CDEBUG(("emitting node %p\n", p));
1236           if (TBLIDX(p->n_su) == 0)
1237                     return;
1238 
1239           allo(p, q);
1240           expand(p, cookie, q->cstring);
1241 
1242 #ifdef FINDMOPS
1243           if (ismops && DECRA(p->n_reg, 0) != regno(l) && cookie != FOREFF) {
1244                     CDEBUG(("gencode(%p) rmove\n", p));
1245                     rmove(regno(l), DECRA(p->n_reg, 0), p->n_type);
1246           } else
1247 #endif
1248           if (callop(p->n_op) && cookie != FOREFF &&
1249               DECRA(p->n_reg, 0) != RETREG(p->n_type)) {
1250                     CDEBUG(("gencode(%p) retreg\n", p));
1251                     rmove(RETREG(p->n_type), DECRA(p->n_reg, 0), p->n_type);
1252           } else if (q->needs & NSPECIAL) {
1253                     int rr = rspecial(q, NRES);
1254 
1255                     if (rr >= 0 && DECRA(p->n_reg, 0) != rr) {
1256                               CDEBUG(("gencode(%p) nspec retreg\n", p));
1257                               rmove(rr, DECRA(p->n_reg, 0), p->n_type);
1258                     }
1259           } else if ((q->rewrite & RESC1) &&
1260               (DECRA(p->n_reg, 1) != DECRA(p->n_reg, 0))) {
1261                     CDEBUG(("gencode(%p) RESC1 retreg\n", p));
1262                     rmove(DECRA(p->n_reg, 1), DECRA(p->n_reg, 0), p->n_type);
1263           }
1264 #if 0
1265                     /* XXX - kolla upp det h{r */
1266              else if (p->n_op == ASSIGN) {
1267                     /* may need move added if RLEFT/RRIGHT */
1268                     /* XXX should be handled in sucomp() */
1269                     if ((q->rewrite & RLEFT) && (p->n_left->n_op == REG) &&
1270                         (p->n_left->n_rval != DECRA(p->n_reg, 0)) &&
1271                         TCLASS(p->n_su)) {
1272                               rmove(p->n_left->n_rval, DECRA(p->n_reg, 0), p->n_type);
1273                     } else if ((q->rewrite & RRIGHT) && (p->n_right->n_op == REG) &&
1274                         (p->n_right->n_rval != DECRA(p->n_reg, 0)) &&
1275                         TCLASS(p->n_su)) {
1276                               rmove(p->n_right->n_rval, DECRA(p->n_reg, 0), p->n_type);
1277                     }
1278           }
1279 #endif
1280           rewrite(p, q->rewrite, cookie);
1281           afree();
1282 }
1283 
1284 int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */
1285 size_t negrelsize = sizeof negrel / sizeof negrel[0];
1286 
1287 #ifdef PCC_DEBUG
1288 #undef    PRTABLE
1289 void
e2print(NODE * p,int down,int * a,int * b)1290 e2print(NODE *p, int down, int *a, int *b)
1291 {
1292           struct attr *ap;
1293 #ifdef PRTABLE
1294           extern int tablesize;
1295 #endif
1296 
1297           *a = *b = down+1;
1298           while( down >= 2 ){
1299                     printf("\t");
1300                     down -= 2;
1301                     }
1302           if( down-- ) printf("    " );
1303 
1304 
1305           printf("%p) %s", p, opst[p->n_op] );
1306           switch( p->n_op ) { /* special cases */
1307 
1308           case FLD:
1309                     printf(" sz=%d, shift=%d",
1310                         UPKFSZ(p->n_rval), UPKFOFF(p->n_rval));
1311                     break;
1312 
1313           case REG:
1314                     printf(" %s", rnames[p->n_rval] );
1315                     break;
1316 
1317           case TEMP:
1318                     printf(" %d", regno(p));
1319                     break;
1320 
1321           case XASM:
1322           case XARG:
1323                     printf(" '%s'", p->n_name);
1324                     break;
1325 
1326           case ICON:
1327           case NAME:
1328           case OREG:
1329                     printf(" " );
1330                     adrput(stdout, p );
1331                     break;
1332 
1333           case STCALL:
1334           case USTCALL:
1335           case STARG:
1336           case STASG:
1337                     ap = attr_find(p->n_ap, ATTR_P2STRUCT);
1338                     printf(" size=%d", ap->iarg(0));
1339                     printf(" align=%d", ap->iarg(1));
1340                     break;
1341                     }
1342 
1343           printf(", " );
1344           tprint(p->n_type, p->n_qual);
1345           printf(", " );
1346 
1347           prtreg(p);
1348           printf(", SU= %d(%cREG,%s,%s,%s,%s)\n",
1349               TBLIDX(p->n_su),
1350               TCLASS(p->n_su)+'@',
1351 #ifdef PRTABLE
1352               TBLIDX(p->n_su) >= 0 && TBLIDX(p->n_su) <= tablesize ?
1353               table[TBLIDX(p->n_su)].cstring : "",
1354 #else
1355               "",
1356 #endif
1357               p->n_su & RVEFF ? "RVEFF" : "", p->n_su & RVCC ? "RVCC" : "",
1358               p->n_su & DORIGHT ? "DORIGHT" : "");
1359 }
1360 #endif
1361 
1362 /*
1363  * change left TEMPs into OREGs
1364  */
1365 void
deltemp(NODE * p,void * arg)1366 deltemp(NODE *p, void *arg)
1367 {
1368           int (*aor)[2] = arg;
1369           NODE *l;
1370 
1371           if (p->n_op == TEMP) {
1372                     if (aor[regno(p)][0] == 0) {
1373                               if (xtemps)
1374                                         return;
1375                               aor[regno(p)][0] = FPREG;
1376                               aor[regno(p)][1] = freetemp(szty(p->n_type));
1377                     }
1378                     storemod(p, aor[regno(p)][1], aor[regno(p)][0]);
1379           } else if (p->n_op == ADDROF && p->n_left->n_op == OREG) {
1380                     p->n_op = PLUS;
1381                     l = p->n_left;
1382                     l->n_op = REG;
1383                     l->n_type = INCREF(l->n_type);
1384                     p->n_right = mklnode(ICON, getlval(l), 0, INT);
1385           } else if (p->n_op == ADDROF && p->n_left->n_op == UMUL) {
1386                     l = p->n_left;
1387                     *p = *p->n_left->n_left;
1388                     nfree(l->n_left);
1389                     nfree(l);
1390           }
1391 }
1392 
1393 /*
1394  * for pointer/integer arithmetic, set pointer at left node
1395  */
1396 static void
setleft(NODE * p,void * arg)1397 setleft(NODE *p, void *arg)
1398 {
1399           NODE *q;
1400 
1401           /* only additions for now */
1402           if (p->n_op != PLUS)
1403                     return;
1404           if (ISPTR(p->n_right->n_type) && !ISPTR(p->n_left->n_type)) {
1405                     q = p->n_right;
1406                     p->n_right = p->n_left;
1407                     p->n_left = q;
1408           }
1409 }
1410 
1411 /* It is OK to have these as externals */
1412 static int oregr;
1413 static CONSZ oregtemp;
1414 static char *oregcp;
1415 /*
1416  * look for situations where we can turn * into OREG
1417  * If sharp then do not allow temps.
1418  */
1419 int
oregok(NODE * p,int sharp)1420 oregok(NODE *p, int sharp)
1421 {
1422 
1423           NODE *q;
1424           NODE *ql, *qr;
1425           int r;
1426           CONSZ temp;
1427           char *cp;
1428 
1429           q = p->n_left;
1430 #if 0
1431           if ((q->n_op == REG || (q->n_op == TEMP && !sharp)) &&
1432               q->n_rval == DECRA(q->n_reg, 0)) {
1433 #endif
1434           if (q->n_op == REG || (q->n_op == TEMP && !sharp)) {
1435                     temp = getlval(q);
1436                     r = q->n_rval;
1437                     cp = q->n_name;
1438                     goto ormake;
1439           }
1440 
1441           if (q->n_op != PLUS && q->n_op != MINUS)
1442                     return 0;
1443           ql = q->n_left;
1444           qr = q->n_right;
1445 
1446 #ifdef R2REGS
1447 
1448           /* look for doubly indexed expressions */
1449           /* XXX - fix checks */
1450 
1451           if( q->n_op == PLUS) {
1452                     int i;
1453                     if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
1454                               makeor2(p, ql, r, i);
1455                               return 1;
1456                     } else if((r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
1457                               makeor2(p, qr, r, i);
1458                               return 1;
1459                     }
1460           }
1461 
1462 
1463 #endif
1464 
1465 #if 0
1466           if( (q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
1467                               (ql->n_op==REG || (ql->n_op==TEMP && !sharp)) &&
1468                               szty(qr->n_type)==1 &&
1469                               (ql->n_rval == DECRA(ql->n_reg, 0) ||
1470                               /* XXX */
1471                                ql->n_rval == FPREG || ql->n_rval == STKREG)) {
1472 #endif
1473           if ((q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
1474               (ql->n_op==REG || (ql->n_op==TEMP && !sharp))) {
1475 
1476                     temp = getlval(qr);
1477                     if( q->n_op == MINUS ) temp = -temp;
1478                     r = ql->n_rval;
1479                     temp += getlval(ql);
1480                     cp = qr->n_name;
1481                     if( *cp && ( q->n_op == MINUS || *ql->n_name ) )
1482                               return 0;
1483                     if( !*cp ) cp = ql->n_name;
1484 
1485                     ormake:
1486                     if( notoff( p->n_type, r, temp, cp ))
1487                               return 0;
1488                     oregtemp = temp;
1489                     oregr = r;
1490                     oregcp = cp;
1491                     return 1;
1492           }
1493           return 0;
1494 }
1495 
1496 static void
1497 ormake(NODE *p)
1498 {
1499           NODE *q = p->n_left;
1500 
1501           p->n_op = OREG;
1502           p->n_rval = oregr;
1503           setlval(p, oregtemp);
1504           p->n_name = oregcp;
1505           tfree(q);
1506 }
1507 
1508 /*
1509  * look for situations where we can turn * into OREG
1510  */
1511 void
1512 oreg2(NODE *p, void *arg)
1513 {
1514           if (p->n_op != UMUL)
1515                     return;
1516           if (oregok(p, 1))
1517                     ormake(p);
1518           if (p->n_op == UMUL)
1519                     myormake(p);
1520 }
1521 
1522 void
1523 canon(NODE *p)
1524 {
1525           /* put p in canonical form */
1526 
1527           walkf(p, setleft, 0);         /* ptrs at left node for arithmetic */
1528           walkf(p, oreg2, 0); /* look for and create OREG nodes */
1529           mycanon(p);                   /* your own canonicalization routine(s) */
1530 }
1531 
1532 void
1533 comperr(char *str, ...)
1534 {
1535           extern char *ftitle;
1536           va_list ap;
1537 
1538           if (nerrors) {
1539                     fprintf(stderr,
1540                         "cannot recover from earlier errors: goodbye!\n");
1541                     exit(1);
1542           }
1543 
1544           va_start(ap, str);
1545           fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline);
1546           vfprintf(stderr, str, ap);
1547           fprintf(stderr, "\n");
1548           va_end(ap);
1549 
1550 #ifdef PCC_DEBUG
1551           if (nodepole && nodepole->n_op != FREE)
1552                     fwalk(nodepole, e2print, 0);
1553 #endif
1554           exit(1);
1555 }
1556 
1557 /*
1558  * allocate k integers worth of temp space
1559  * we also make the convention that, if the number of words is
1560  * more than 1, it must be aligned for storing doubles...
1561  * Returns bytes offset from base register.
1562  */
1563 int
1564 freetemp(int k)
1565 {
1566           int t, al, sz;
1567 
1568           al = (k > 1 ? ALDOUBLE/ALCHAR : ALINT/ALCHAR);
1569           sz = k * (SZINT/SZCHAR);
1570 
1571 #ifndef BACKTEMP
1572           SETOFF(p2autooff, al);
1573           t = p2autooff;
1574           p2autooff += sz;
1575 #else
1576           p2autooff += sz;
1577           SETOFF(p2autooff, al);
1578           t = ( -p2autooff );
1579 #endif
1580           if (p2autooff > p2maxautooff)
1581                     p2maxautooff = p2autooff;
1582           return (t);
1583 }
1584 
1585 NODE *
1586 storenode(TWORD t, int off)
1587 {
1588           NODE *p;
1589 
1590           p = talloc();
1591           p->n_type = t;
1592           storemod(p, off, FPREG); /* XXX */
1593           return p;
1594 }
1595 
1596 #ifndef MYSTOREMOD
1597 void
1598 storemod(NODE *q, int off, int reg)
1599 {
1600           NODE *l, *r, *p;
1601 
1602           l = mklnode(REG, 0, reg, INCREF(q->n_type));
1603           r = mklnode(ICON, off, 0, INT);
1604           p = mkbinode(PLUS, l, r, INCREF(q->n_type));
1605           q->n_op = UMUL;
1606           q->n_left = p;
1607           q->n_rval = q->n_su = 0;
1608 }
1609 #endif
1610 
1611 NODE *
1612 mklnode(int op, CONSZ lval, int rval, TWORD type)
1613 {
1614           NODE *p = talloc();
1615 
1616           p->n_name = "";
1617           p->n_qual = 0;
1618           p->n_ap = 0;
1619           p->n_op = op;
1620           setlval(p, lval);
1621           p->n_rval = rval;
1622           p->n_type = type;
1623           p->n_regw = NULL;
1624           p->n_su = 0;
1625           return p;
1626 }
1627 
1628 NODE *
1629 mkbinode(int op, NODE *left, NODE *right, TWORD type)
1630 {
1631           NODE *p = talloc();
1632 
1633           p->n_name = "";
1634           p->n_qual = 0;
1635           p->n_ap = 0;
1636           p->n_op = op;
1637           p->n_left = left;
1638           p->n_right = right;
1639           p->n_type = type;
1640           p->n_regw = NULL;
1641           p->n_su = 0;
1642           return p;
1643 }
1644 
1645 NODE *
1646 mkunode(int op, NODE *left, int rval, TWORD type)
1647 {
1648           NODE *p = talloc();
1649 
1650           p->n_name = "";
1651           p->n_qual = 0;
1652           p->n_ap = 0;
1653           p->n_op = op;
1654           p->n_left = left;
1655           p->n_rval = rval;
1656           p->n_type = type;
1657           p->n_regw = NULL;
1658           p->n_su = 0;
1659           return p;
1660 }
1661 
1662 struct interpass *
1663 ipnode(NODE *p)
1664 {
1665           struct interpass *ip = tmpalloc(sizeof(struct interpass));
1666 
1667           ip->ip_node = p;
1668           ip->type = IP_NODE;
1669           ip->lineno = thisline;
1670           return ip;
1671 }
1672 
1673 int
1674 rspecial(struct optab *q, int what)
1675 {
1676           struct rspecial *r = nspecial(q);
1677           while (r->op) {
1678                     if (r->op == what)
1679                               return r->num;
1680                     r++;
1681           }
1682           return -1;
1683 }
1684 
1685 #ifndef XASM_NUMCONV
1686 #define   XASM_NUMCONV(x,y,z) 0
1687 #endif
1688 
1689 /*
1690  * change numeric argument redirections to the correct node type after
1691  * cleaning up the other nodes.
1692  * be careful about input operands that may have different value than output.
1693  */
1694 static void
1695 delnums(NODE *p, void *arg)
1696 {
1697           struct interpass *ip = arg, *ip2;
1698           NODE *r = ip->ip_node->n_left;
1699           NODE *q;
1700           TWORD t;
1701           int cnt, num;
1702 
1703           /* gcc allows % in constraints, but we ignore it */
1704           if (p->n_name[0] == '%' && p->n_name[1] >= '0' && p->n_name[1] <= '9')
1705                     p->n_name++;
1706 
1707           if (p->n_name[0] < '0' || p->n_name[0] > '9')
1708                     return; /* not numeric */
1709           if ((q = listarg(r, p->n_name[0] - '0', &cnt)) == NIL)
1710                     comperr("bad delnums");
1711 
1712           /* target may have opinions whether to do this conversion */
1713           if (XASM_NUMCONV(ip, p, q))
1714                     return;
1715 
1716           /* Delete number by adding move-to/from-temp.  Later on */
1717           /* the temps may be rewritten to other LTYPEs */
1718           num = p2env.epp->ip_tmpnum++;
1719 
1720           /* pre node */
1721           t = p->n_left->n_type;
1722           r = mklnode(TEMP, 0, num, t);
1723           ip2 = ipnode(mkbinode(ASSIGN, tcopy(r), p->n_left, t));
1724           DLIST_INSERT_BEFORE(ip, ip2, qelem);
1725           p->n_left = r;
1726 
1727           /* post node */
1728           t = q->n_left->n_type;
1729           r = mklnode(TEMP, 0, num, t);
1730           ip2 = ipnode(mkbinode(ASSIGN, q->n_left, tcopy(r), t));
1731           DLIST_INSERT_AFTER(ip, ip2, qelem);
1732           q->n_left = r;
1733 
1734           p->n_name = tmpstrdup(q->n_name);
1735           if (*p->n_name == '=')
1736                     p->n_name++;
1737 }
1738 
1739 /*
1740  * Ensure that a node is correct for the destination.
1741  */
1742 static void
1743 ltypify(NODE *p, void *arg)
1744 {
1745           struct interpass *ip = arg;
1746           struct interpass *ip2;
1747           TWORD t = p->n_left->n_type;
1748           NODE *q, *r;
1749           int cw, ooff, ww;
1750           char *c;
1751 
1752 again:
1753           if (myxasm(ip, p))
1754                     return;   /* handled by target-specific code */
1755 
1756           cw = xasmcode(p->n_name);
1757           switch (ww = XASMVAL(cw)) {
1758           case 'p':
1759                     /* pointer */
1760                     /* just make register of it */
1761                     p->n_name = tmpstrdup(p->n_name);
1762                     c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */
1763                     *c = 'r';
1764                     /* FALLTHROUGH */
1765           case 'g':  /* general; any operand */
1766                     if (ww == 'g' && p->n_left->n_op == ICON) {
1767                               /* should only be input */
1768                               p->n_name = "i";
1769                               break;
1770                     }
1771                     /* FALLTHROUGH */
1772           case 'r': /* general reg */
1773                     /* set register class */
1774                     if (p->n_left->n_op == REG || p->n_left->n_op == TEMP)
1775                               break;
1776                     q = p->n_left;
1777                     r = (cw & XASMINOUT ? tcopy(q) : q);
1778                     p->n_left = mklnode(TEMP, 0, p2env.epp->ip_tmpnum++, t);
1779                     if ((cw & XASMASG) == 0) {
1780                               ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), r, t));
1781                               DLIST_INSERT_BEFORE(ip, ip2, qelem);
1782                     }
1783                     if (cw & (XASMASG|XASMINOUT)) {
1784                               /* output parameter */
1785                               ip2 = ipnode(mkbinode(ASSIGN, q, tcopy(p->n_left), t));
1786                               DLIST_INSERT_AFTER(ip, ip2, qelem);
1787                     }
1788                     break;
1789 
1790           case '0': case '1': case '2': case '3': case '4':
1791           case '5': case '6': case '7': case '8': case '9':
1792                     break;
1793 
1794           case 'm': /* memory operand */
1795                     /* store and reload value */
1796                     q = p->n_left;
1797                     if (optype(q->n_op) == LTYPE) {
1798                               if (q->n_op == TEMP) {
1799                                         ooff = freetemp(szty(t));
1800                                         cvtemps(ip, q->n_rval, ooff);
1801                               } else if (q->n_op == REG)
1802                                         comperr("xasm m and reg");
1803                     } else if (q->n_op == UMUL &&
1804                         (q->n_left->n_op != TEMP && q->n_left->n_op != REG)) {
1805                               t = q->n_left->n_type;
1806                               ooff = p2env.epp->ip_tmpnum++;
1807                               ip2 = ipnode(mkbinode(ASSIGN,
1808                                   mklnode(TEMP, 0, ooff, t), q->n_left, t));
1809                               q->n_left = mklnode(TEMP, 0, ooff, t);
1810                               DLIST_INSERT_BEFORE(ip, ip2, qelem);
1811                     }
1812                     break;
1813 
1814           case 'i': /* immediate constant */
1815           case 'n': /* numeric constant */
1816                     if (p->n_left->n_op == ICON)
1817                               break;
1818                     p->n_name = tmpstrdup(p->n_name);
1819                     c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */
1820                     if (c[1]) {
1821                               c[0] = c[1], c[1] = 0;
1822                               goto again;
1823                     } else
1824                               uerror("constant required");
1825                     break;
1826 
1827           default:
1828                     uerror("unsupported xasm option string '%s'", p->n_name);
1829           }
1830 }
1831 
1832 /* Extended assembler hacks */
1833 static void
1834 fixxasm(struct p2env *p2e)
1835 {
1836           struct interpass *pole = &p2e->ipole;
1837           struct interpass *ip;
1838           NODE *p;
1839 
1840           DLIST_FOREACH(ip, pole, qelem) {
1841                     if (ip->type != IP_NODE || ip->ip_node->n_op != XASM)
1842                               continue;
1843                     thisline = ip->lineno;
1844                     p = ip->ip_node->n_left;
1845 
1846                     if (p->n_op == ICON && p->n_type == STRTY)
1847                               continue;
1848 
1849                     /* replace numeric redirections with its underlying type */
1850                     flist(p, delnums, ip);
1851 
1852                     /*
1853                      * Ensure that the arg nodes can be directly addressable
1854                      * We decide that everything shall be LTYPE here.
1855                      */
1856                     flist(p, ltypify, ip);
1857           }
1858 }
1859 
1860 /*
1861  * Extract codeword from xasm string */
1862 int
1863 xasmcode(char *s)
1864 {
1865           int cw = 0, nm = 0;
1866 
1867           while (*s) {
1868                     switch ((int)*s) {
1869                     case '=': cw |= XASMASG; break;
1870                     case '&': cw |= XASMCONSTR; break;
1871                     case '+': cw |= XASMINOUT; break;
1872                     case '%': break;
1873                     default:
1874                               if ((*s >= 'a' && *s <= 'z') ||
1875                                   (*s >= 'A' && *s <= 'Z') ||
1876                                   (*s >= '0' && *s <= '9')) {
1877                                         if (nm == 0)
1878                                                   cw |= *s;
1879                                         else
1880                                                   cw |= (*s << ((nm + 1) * 8));
1881                                         nm++;
1882                                         break;
1883                               }
1884                               uerror("bad xasm constraint %c", *s);
1885                     }
1886                     s++;
1887           }
1888           return cw;
1889 }
1890 
1891 static int xasnum, xoffnum;
1892 
1893 static void
1894 xconv(NODE *p, void *arg)
1895 {
1896           if (p->n_op != TEMP || p->n_rval != xasnum)
1897                     return;
1898           storemod(p, xoffnum, FPREG); /* XXX */
1899 }
1900 
1901 /*
1902  * Convert nodes of type TEMP to op with lval off.
1903  */
1904 static void
1905 cvtemps(struct interpass *ipl, int tnum, int off)
1906 {
1907           struct interpass *ip;
1908 
1909           xasnum = tnum;
1910           xoffnum = off;
1911 
1912           DLIST_FOREACH(ip, ipl, qelem)
1913                     if (ip->type == IP_NODE)
1914                               walkf(ip->ip_node, xconv, 0);
1915           walkf(ipl->ip_node, xconv, 0);
1916 }
1917