xref: /netbsd/external/bsd/pcc/dist/pcc/mip/reader.c (revision 6935091c)
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