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