xref: /csrg-svn/old/pcc/ccom.vax/local2.c (revision 32936)
1 # ifndef lint
2 static char *sccsid ="@(#)local2.c	1.30 (Berkeley) 12/11/87";
3 # endif
4 
5 # include "pass2.h"
6 # include <ctype.h>
7 
8 # define putstr(s)	fputs((s), stdout)
9 
10 # ifdef FORT
11 int ftlab1, ftlab2;
12 # endif
13 /* a lot of the machine dependent parts of the second pass */
14 
15 # define BITMASK(n) ((1L<<n)-1)
16 
17 /*ARGSUSED*/
18 where(c){
19 	fprintf( stderr, "%s, line %d: ", filename, lineno );
20 	}
21 
22 lineid( l, fn ) char *fn; {
23 	/* identify line l and file fn */
24 	printf( "#	line %d, file %s\n", l, fn );
25 	}
26 
27 
28 eobl2(){
29 	register OFFSZ spoff;	/* offset from stack pointer */
30 #ifndef FORT
31 	extern int ftlab1, ftlab2;
32 #endif
33 
34 	spoff = maxoff;
35 	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
36 	spoff /= SZCHAR;
37 	SETOFF(spoff,4);
38 #ifdef FORT
39 #ifndef FLEXNAMES
40 	printf( "	.set	.F%d,%ld\n", ftnno, spoff );
41 #else
42 	/* SHOULD BE L%d ... ftnno but must change pc/f77 */
43 	printf( "	.set	LF%d,%ld\n", ftnno, spoff );
44 #endif
45 #else
46 	printf( "L%d:\n", ftlab1);
47 	if( spoff!=0 )
48 		if( spoff < 64 )
49 			printf( "	subl2	$%ld,sp\n", spoff);
50 		else
51 			printf( "	movab	-%ld(sp),sp\n", spoff);
52 	printf( "	jbr 	L%d\n", ftlab2);
53 #endif
54 	maxargs = -1;
55 	}
56 
57 struct hoptab { int opmask; char * opstring; } ioptab[] = {
58 
59 	PLUS,	"add",
60 	MINUS,	"sub",
61 	MUL,	"mul",
62 	DIV,	"div",
63 	OR,	"bis",
64 	ER,	"xor",
65 	AND,	"bic",
66 	-1, ""    };
67 
68 hopcode( f, o ){
69 	/* output the appropriate string from the above table */
70 
71 	register struct hoptab *q;
72 
73 	if(asgop(o))
74 		o = NOASG o;
75 	for( q = ioptab;  q->opmask>=0; ++q ){
76 		if( q->opmask == o ){
77 			printf( "%s%c", q->opstring, tolower(f));
78 			return;
79 			}
80 		}
81 	cerror( "no hoptab for %s", opst[o] );
82 	}
83 
84 char *
85 rnames[] = {  /* keyed to register number tokens */
86 
87 	"r0", "r1",
88 	"r2", "r3", "r4", "r5",
89 	"r6", "r7", "r8", "r9", "r10", "r11",
90 	"ap", "fp", "sp", "pc",
91 	};
92 
93 int rstatus[] = {
94 	SAREG|STAREG, SAREG|STAREG,
95 	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
96 	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
97 	SAREG, SAREG, SAREG, SAREG,
98 	};
99 
100 tlen(p) NODE *p;
101 {
102 	switch(p->in.type) {
103 		case CHAR:
104 		case UCHAR:
105 			return(1);
106 
107 		case SHORT:
108 		case USHORT:
109 			return(2);
110 
111 		case DOUBLE:
112 			return(8);
113 
114 		default:
115 			return(4);
116 		}
117 }
118 
119 mixtypes(p, q) NODE *p, *q;
120 {
121 	register TWORD tp, tq;
122 
123 	tp = p->in.type;
124 	tq = q->in.type;
125 
126 	return( (tp==FLOAT || tp==DOUBLE) !=
127 		(tq==FLOAT || tq==DOUBLE) );
128 }
129 
130 prtype(n) NODE *n;
131 {
132 	switch (n->in.type)
133 		{
134 
135 		case DOUBLE:
136 			putchar('d');
137 			return;
138 
139 		case FLOAT:
140 			putchar('f');
141 			return;
142 
143 		case LONG:
144 		case ULONG:
145 		case INT:
146 		case UNSIGNED:
147 			putchar('l');
148 			return;
149 
150 		case SHORT:
151 		case USHORT:
152 			putchar('w');
153 			return;
154 
155 		case CHAR:
156 		case UCHAR:
157 			putchar('b');
158 			return;
159 
160 		default:
161 			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
162 			else {
163 				putchar('l');
164 				return;
165 				}
166 		}
167 }
168 
169 zzzcode( p, c ) register NODE *p; {
170 	register int m;
171 	int val;
172 	switch( c ){
173 
174 	case 'N':  /* logical ops, turned into 0-1 */
175 		/* use register given by register 1 */
176 		cbgen( 0, m=getlab(), 'I' );
177 		deflab( p->bn.label );
178 		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );
179 		deflab( m );
180 		return;
181 
182 	case 'P':
183 		cbgen( p->in.op, p->bn.label, c );
184 		return;
185 
186 	case 'A':
187 	case 'V':
188 		sconv( p, c == 'V' );
189 		return;
190 
191 	case 'G':	/* i *= f; asgops with int lhs and float rhs */
192 		{
193 		register NODE *l, *r, *s;
194 		int rt;
195 
196 		l = p->in.left;
197 		r = p->in.right;
198 		s = talloc();
199 		rt = r->in.type;
200 
201 		s->in.op = SCONV;
202 		s->in.left = l;
203 		s->in.type = rt;
204 		zzzcode(s, 'A');
205 		putstr("\n\t");
206 
207 		hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
208 		putstr("2\t");
209 		adrput(r);
210 		putchar(',');
211 		adrput(resc);
212 		putstr("\n\t");
213 
214 		s->in.op = ASSIGN;
215 		s->in.left = l;
216 		s->in.right = resc;
217 		s->in.type = l->in.type;
218 		zzzcode(s, 'A');
219 
220 		s->in.op = FREE;
221 		return;
222 		}
223 
224 	case 'J':	/* unsigned DIV/MOD with constant divisors */
225 		{
226 		register int ck = INAREG;
227 		int label1, label2;
228 
229 		/* case constant <= 1 is handled by optim() in pass 1 */
230 		/* case constant < 0x80000000 is handled in table */
231 		switch( p->in.op ) {
232 		/* case DIV: handled in hardops() */
233 		case MOD:
234 			if( p->in.left->in.op == REG &&
235 			    p->in.left->tn.rval == resc->tn.rval )
236 				goto asgmod;
237 			label1 = getlab();
238 			expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n");
239 			printf("\tjlssu\tL%d\n", label1);
240 			expand(p, ck, "\tsubl2\tAR,A1\n");
241 			printf("L%d:", label1);
242 			break;
243 		case ASG DIV:
244 			label1 = getlab();
245 			label2 = getlab();
246 			expand(p, ck, "cmpl\tAL,AR\n");
247 			printf("\tjgequ\tL%d\n", label1);
248 			expand(p, ck, "\tmovl\t$1,AL\n");
249 			printf("\tjbr\tL%d\nL%d:\n", label2, label1);
250 			expand(p, ck, "\tclrl\tAL\n");
251 			printf("L%d:", label2);
252 			break;
253 		case ASG MOD:
254 		asgmod:
255 			label1 = getlab();
256 			expand(p, ck, "cmpl\tAL,AR\n");
257 			printf("\tjlssu\tL%d\n", label1);
258 			expand(p, ck, "\tsubl2\tAR,AL\n");
259 			printf("L%d:", label1);
260 			break;
261 			}
262 		return;
263 		}
264 
265 	case 'B':	/* get oreg value in temp register for left shift */
266 		{
267 		register NODE *r;
268 		if (xdebug) eprint(p, 0, &val, &val);
269 		r = p->in.right;
270 		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
271 			putstr("movl");
272 		else {
273 			putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
274 			prtype(r);
275 			putchar('l');
276 			}
277 		return;
278 		}
279 
280 	case 'C':	/* num words pushed on arg stack */
281 		{
282 		extern int gc_numbytes;
283 		extern int xdebug;
284 
285 		if (xdebug) printf("->%d<-",gc_numbytes);
286 
287 		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
288 		return;
289 		}
290 
291 	case 'D':	/* INCR and DECR */
292 		zzzcode(p->in.left, 'A');
293 		putchar('\n');
294 		putchar('\t');
295 
296 	case 'E':	/* INCR and DECR, FOREFF */
297 		if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1)
298 			{
299 			putstr(p->in.op == INCR ? "inc" : "dec");
300 			prtype(p->in.left);
301 			putchar('\t');
302 			adrput(p->in.left);
303 			return;
304 			}
305 		putstr(p->in.op == INCR ? "add" : "sub");
306 		prtype(p->in.left);
307 		putchar('2');
308 		putchar('\t');
309 		adrput(p->in.right);
310 		putchar(',');
311 		adrput(p->in.left);
312 		return;
313 
314 	case 'F':	/* register type of right operand */
315 		{
316 		register NODE *n;
317 		extern int xdebug;
318 		register int ty;
319 
320 		n = getlr( p, 'R' );
321 		ty = n->in.type;
322 
323 		if (xdebug) printf("->%d<-", ty);
324 
325 		if ( ty==DOUBLE) putchar('d');
326 		else if ( ty==FLOAT ) putchar('f');
327 		else putchar('l');
328 		return;
329 		}
330 
331 	case 'L':	/* type of left operand */
332 	case 'R':	/* type of right operand */
333 		{
334 		register NODE *n;
335 		extern int xdebug;
336 
337 		n = getlr( p, c );
338 		if (xdebug) printf("->%d<-", n->in.type);
339 
340 		prtype(n);
341 		return;
342 		}
343 
344 	case 'Z':	/* complement mask for bit instr */
345 		printf("$%ld", ~p->in.right->tn.lval);
346 		return;
347 
348 	case 'U':	/* 32 - n, for unsigned right shifts */
349 		printf("$%d", 32 - p->in.right->tn.lval );
350 		return;
351 
352 	case 'T':	/* rounded structure length for arguments */
353 		{
354 		int size;
355 
356 		size = p->stn.stsize;
357 		SETOFF( size, 4);
358 		printf("$%d", size);
359 		return;
360 		}
361 
362 	case 'S':  /* structure assignment */
363 		stasg(p);
364 		break;
365 
366 	default:
367 		cerror( "illegal zzzcode" );
368 		}
369 	}
370 
371 stasg(p)
372 	register NODE *p;
373 {
374 	register NODE *l, *r;
375 	register size;
376 
377 	if( p->in.op == STASG ){
378 		l = p->in.left;
379 		r = p->in.right;
380 
381 		}
382 	else if( p->in.op == STARG ){  /* store an arg into a temporary */
383 		r = p->in.left;
384 		}
385 	else cerror( "STASG bad" );
386 
387 	if( r->in.op == ICON ) r->in.op = NAME;
388 	else if( r->in.op == REG ) r->in.op = OREG;
389 	else if( r->in.op != OREG ) cerror( "STASG-r" );
390 
391 	size = p->stn.stsize;
392 
393 	if( size <= 0 || size > 65535 )
394 		cerror("structure size <0=0 or >65535");
395 
396 	switch(size) {
397 		case 1:
398 			putstr("	movb	");
399 			break;
400 		case 2:
401 			putstr("	movw	");
402 			break;
403 		case 4:
404 			putstr("	movl	");
405 			break;
406 		case 8:
407 			putstr("	movq	");
408 			break;
409 		default:
410 			printf("	movc3	$%d,", size);
411 			break;
412 	}
413 	adrput(r);
414 	if( p->in.op == STASG ){
415 		putchar(',');
416 		adrput(l);
417 		putchar('\n');
418 		}
419 	else
420 		putstr(",(sp)\n");
421 
422 	if( r->in.op == NAME ) r->in.op = ICON;
423 	else if( r->in.op == OREG ) r->in.op = REG;
424 	}
425 
426 NODE *makearg( ty ) int ty; {
427 	register NODE *p, *q;
428 
429 	/* build a -(sp) operand */
430 	p = talloc();
431 	p->in.op = REG;
432 	/* the type needn't be right, just consistent */
433 	p->in.type = INCREF(ty);
434 	p->tn.rval = SP;
435 	p->tn.lval = 0;
436 	q = talloc();
437 	q->in.op = ASG MINUS;
438 	q->in.type = INCREF(ty);
439 	q->in.left = p;
440 	p = talloc();
441 	p->in.op = ICON;
442 	p->in.type = INT;
443 	p->tn.name = "";
444 	p->tn.lval = tlen(ty);
445 	q->in.right = p;
446 	p = talloc();
447 	p->in.op = UNARY MUL;
448 	p->in.left = q;
449 	return( p );
450 	}
451 
452 sconv( p, forarg ) register NODE *p; {
453 	register NODE *l, *r;
454 	int m, val;
455 
456 	if (xdebug) eprint(p, 0, &val, &val);
457 	r = getlr(p, 'R');
458 	if (p->in.op == ASSIGN)
459 		l = getlr(p, 'L');
460 	else if (p->in.op == SCONV) {
461 #if defined(FORT) || defined(SPRECC)
462 		m = r->in.type;
463 #else
464 		m = r->in.type==FLOAT ? DOUBLE : r->in.type;
465 #endif
466 		if (forarg)
467 			l = makearg( m );
468 		else
469 			l = resc;
470 		l->in.type = m;
471 		r = getlr(p, 'L');
472 		}
473 	else {		/* OPLTYPE */
474 #if defined(FORT) || defined(SPRECC)
475 		m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
476 #else
477 		m = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
478 #endif
479 		if (forarg)
480 			l = makearg( m );
481 		else
482 			l = resc;
483 		l->in.type = m;
484 		}
485 	if (r->in.op == ICON)
486 		if (r->in.name[0] == '\0') {
487 			if (r->tn.lval == 0) {
488 				putstr("clr");
489 				prtype(l);
490 				putchar('\t');
491 				adrput(l);
492 				goto cleanup;
493 				}
494 			if (r->tn.lval < 0 && r->tn.lval >= -63) {
495 				putstr("mneg");
496 				prtype(l);
497 				r->tn.lval = -r->tn.lval;
498 				goto ops;
499 				}
500 			if (r->tn.lval < 0)
501 				r->in.type = r->tn.lval >= -128 ? CHAR
502 					: (r->tn.lval >= -32768 ? SHORT
503 					: INT);
504 			else if (l->in.type == FLOAT ||
505 			    l->in.type == DOUBLE)
506 				r->in.type = r->tn.lval <= 63 ? INT
507 					: (r->tn.lval <= 127 ? CHAR
508 					: (r->tn.lval <= 32767 ? SHORT
509 					: INT));
510 			else
511 				r->in.type = r->tn.lval <= 63 ? INT
512 					: (r->tn.lval <= 127 ? CHAR
513 					: (r->tn.lval <= 255 ? UCHAR
514 					: (r->tn.lval <= 32767 ? SHORT
515 					: (r->tn.lval <= 65535 ? USHORT
516 					: INT))));
517 			}
518 		else {
519 			putstr("moval");
520 			putchar('\t');
521 			acon(r);
522 			putchar(',');
523 			adrput(l);
524 			goto cleanup;
525 			}
526 
527 	if (p->in.op == SCONV &&
528 	    !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
529 	    !mixtypes(l, r)) {
530 		/*
531 		 * Because registers must always contain objects
532 		 * of the same width as INTs, we may have to
533 		 * perform two conversions to get an INT.  Can
534 		 * the conversions be collapsed into one?
535 		 */
536 		if (m = collapsible(l, r))
537 			r->in.type = m;
538 		else {
539 			/*
540 			 * Two steps are required.
541 			 */
542 			NODE *x = &resc[1];
543 
544 			*x = *l;
545 			if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
546 				putstr("movz");
547 			else
548 				putstr("cvt");
549 			prtype(r);
550 			prtype(x);
551 			putchar('\t');
552 			adrput(r);
553 			putchar(',');
554 			adrput(x);
555 			putchar('\n');
556 			putchar('\t');
557 			r = x;
558 			}
559 		l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
560 		}
561 
562 	if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
563 	    mixtypes(l, r)) {
564 		int label1, label2;
565 
566 		label1 = getlab();
567 		label2 = getlab();
568 
569 		putstr("movl\t");
570 		adrput(r);
571 		putchar(',');
572 		adrput(l);
573 		putstr("\n\tjbsc\t$31,");
574 		adrput(l);
575 		printf(",L%d\n\tcvtl", label1);
576 		prtype(l);
577 		putchar('\t');
578 		adrput(l);
579 		putchar(',');
580 		adrput(l);
581 		printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1);
582 		prtype(l);
583 		putchar('\t');
584 		adrput(l);
585 		putchar(',');
586 		adrput(l);
587 		putstr("\n\tadd");
588 		prtype(l);
589 		putstr("2\t$0");
590 		prtype(l);
591 		putstr("2.147483648e9,");
592 		adrput(l);
593 		printf("\nL%d:", label2);
594 
595 		goto cleanup;
596 		}
597 
598 	if (!mixtypes(l,r)) {
599 		if (tlen(l) == tlen(r)) {
600 			putstr("mov");
601 #ifdef FORT
602 			if (Oflag)
603 				prtype(l);
604 			else {
605 				if (l->in.type == DOUBLE)
606 					putchar('q');
607 				else if(l->in.type == FLOAT)
608 					putchar('l');
609 				else
610 					prtype(l);
611 				}
612 #else
613 			prtype(l);
614 #endif FORT
615 			goto ops;
616 			}
617 		else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
618 			putstr("movz");
619 		else
620 			putstr("cvt");
621 		}
622 	else
623 		putstr("cvt");
624 	prtype(r);
625 	prtype(l);
626 ops:
627 	putchar('\t');
628 	adrput(r);
629 	putchar(',');
630 	adrput(l);
631 
632 cleanup:
633 	if (forarg)
634 		tfree(l);
635 	}
636 
637 /*
638  * collapsible(dest, src) -- if a conversion with a register destination
639  *	can be accomplished in one instruction, return the type of src
640  *	that will do the job correctly; otherwise return 0.  Note that
641  *	a register must always end up having type INT or UNSIGNED.
642  */
643 int
644 collapsible(dest, src)
645 NODE *dest, *src;
646 {
647 	int st = src->in.type;
648 	int dt = dest->in.type;
649 	int newt = 0;
650 
651 	/*
652 	 * Are there side effects of evaluating src?
653 	 * If the derived type will not be the same size as src,
654 	 * we may have to use two steps.
655 	 */
656 	if (tlen(src) > tlen(dest)) {
657 		if (tshape(src, STARREG))
658 			return (0);
659 		if (src->in.op == OREG && R2TEST(src->tn.rval))
660 			return (0);
661 		}
662 
663 	/*
664 	 * Can we get an object of dest's type by punning src?
665 	 * Praises be to great Cthulhu for little-endian machines...
666 	 */
667 	if (st == CHAR && dt == USHORT)
668 		/*
669 		 * Special case -- we must sign-extend to 16 bits.
670 		 */
671 		return (0);
672 
673 	if (tlen(src) < tlen(dest))
674 		newt = st;
675 	else
676 		newt = dt;
677 
678 	return (newt);
679 	}
680 
681 rmove( rt, rs, t ) TWORD t; {
682 	printf( "	%s	%s,%s\n",
683 #ifdef FORT
684 		!Oflag ? (t==DOUBLE ? "movq" : "movl") :
685 #endif
686 		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
687 		rnames[rs], rnames[rt] );
688 	}
689 
690 struct respref
691 respref[] = {
692 	INTAREG|INTBREG,	INTAREG|INTBREG,
693 	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
694 	INTEMP,	INTEMP,
695 	FORARG,	FORARG,
696 	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
697 	0,	0 };
698 
699 setregs(){ /* set up temporary registers */
700 	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */
701 	}
702 
703 /*ARGSUSED*/
704 rewfld( p ) NODE *p; {
705 	return(1);
706 	}
707 
708 /*ARGSUSED*/
709 callreg(p) NODE *p; {
710 	return( R0 );
711 	}
712 
713 base( p ) register NODE *p; {
714 	register int o = p->in.op;
715 
716 	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
717 	if( o==REG ) return( p->tn.rval );
718     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
719 		return( p->in.left->tn.rval );
720     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
721 		return( p->tn.rval + 0200*1 );
722 	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
723 	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
724 	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
725 	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
726 		return( p->in.left->in.left->tn.rval + 0200*(1+2) );
727 	return( -1 );
728 	}
729 
730 offset( p, tyl ) register NODE *p; int tyl; {
731 
732 	if( tyl==1 &&
733 	    p->in.op==REG &&
734 	    (p->in.type==INT || p->in.type==UNSIGNED) )
735 		return( p->tn.rval );
736 	if( p->in.op==LS &&
737 	    p->in.left->in.op==REG &&
738 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
739 	    p->in.right->in.op==ICON &&
740 	    p->in.right->in.name[0]=='\0' &&
741 	    (1<<p->in.right->tn.lval)==tyl)
742 		return( p->in.left->tn.rval );
743 	if( tyl==2 &&
744 	    p->in.op==PLUS &&
745 	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
746 	    p->in.left->in.op==REG &&
747 	    p->in.right->in.op==REG &&
748 	    p->in.left->tn.rval==p->in.right->tn.rval )
749 		return( p->in.left->tn.rval );
750 	return( -1 );
751 	}
752 
753 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
754 	register NODE *t;
755 	NODE *f;
756 
757 	p->in.op = OREG;
758 	f = p->in.left; 	/* have to free this subtree later */
759 
760 	/* init base */
761 	switch (q->in.op) {
762 		case ICON:
763 		case REG:
764 		case OREG:
765 			t = q;
766 			break;
767 
768 		case MINUS:
769 			q->in.right->tn.lval = -q->in.right->tn.lval;
770 		case PLUS:
771 			t = q->in.right;
772 			break;
773 
774 		case INCR:
775 		case ASG MINUS:
776 			t = q->in.left;
777 			break;
778 
779 		case UNARY MUL:
780 			t = q->in.left->in.left;
781 			break;
782 
783 		default:
784 			cerror("illegal makeor2");
785 	}
786 
787 	p->tn.lval = t->tn.lval;
788 #ifndef FLEXNAMES
789 	{
790 		register int i;
791 		for(i=0; i<NCHNAM; ++i)
792 			p->in.name[i] = t->in.name[i];
793 	}
794 #else
795 	p->in.name = t->in.name;
796 #endif
797 
798 	/* init offset */
799 	p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
800 
801 	tfree(f);
802 	return;
803 	}
804 
805 canaddr( p ) NODE *p; {
806 	register int o = p->in.op;
807 
808 	if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
809 	return(0);
810 	}
811 
812 flshape( p ) NODE *p; {
813 	register int o = p->in.op;
814 
815 	return( o == REG || o == NAME || o == ICON ||
816 		(o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
817 	}
818 
819 /* INTEMP shapes must not contain any temporary registers */
820 shtemp( p ) register NODE *p; {
821 	int r;
822 
823 	if( p->in.op == STARG ) p = p->in.left;
824 
825 	switch (p->in.op) {
826 	case REG:
827 		return( !istreg(p->tn.rval) );
828 	case OREG:
829 		r = p->tn.rval;
830 		if( R2TEST(r) ) {
831 			if( istreg(R2UPK1(r)) )
832 				return(0);
833 			r = R2UPK2(r);
834 			}
835 		return( !istreg(r) );
836 	case UNARY MUL:
837 		p = p->in.left;
838 		return( p->in.op != UNARY MUL && shtemp(p) );
839 		}
840 
841 	if( optype( p->in.op ) != LTYPE ) return(0);
842 	return(1);
843 	}
844 
845 shumul( p ) register NODE *p; {
846 	register int o;
847 	extern int xdebug;
848 
849 	if (xdebug) {
850 		int val;
851 		printf("shumul:\n");
852 		eprint(p, 0, &val, &val);
853 		}
854 
855 	o = p->in.op;
856 	if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
857 
858 	if( ( o == INCR || o == ASG MINUS ) &&
859 	    ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
860 	    p->in.right->in.name[0] == '\0' )
861 		{
862 		switch (p->in.type)
863 			{
864 			case CHAR|PTR:
865 			case UCHAR|PTR:
866 				o = 1;
867 				break;
868 
869 			case SHORT|PTR:
870 			case USHORT|PTR:
871 				o = 2;
872 				break;
873 
874 			case INT|PTR:
875 			case UNSIGNED|PTR:
876 			case LONG|PTR:
877 			case ULONG|PTR:
878 			case FLOAT|PTR:
879 				o = 4;
880 				break;
881 
882 			case DOUBLE|PTR:
883 				o = 8;
884 				break;
885 
886 			default:
887 				if ( ISPTR(p->in.type) &&
888 				     ISPTR(DECREF(p->in.type)) ) {
889 					o = 4;
890 					break;
891 					}
892 				else return(0);
893 			}
894 		return( p->in.right->tn.lval == o ? STARREG : 0);
895 		}
896 
897 	return( 0 );
898 	}
899 
900 adrcon( val ) CONSZ val; {
901 	putchar( '$' );
902 	printf( CONFMT, val );
903 	}
904 
905 conput( p ) register NODE *p; {
906 	switch( p->in.op ){
907 
908 	case ICON:
909 		acon( p );
910 		return;
911 
912 	case REG:
913 		putstr( rnames[p->tn.rval] );
914 		return;
915 
916 	default:
917 		cerror( "illegal conput" );
918 		}
919 	}
920 
921 /*ARGSUSED*/
922 insput( p ) NODE *p; {
923 	cerror( "insput" );
924 	}
925 
926 upput( p, size ) NODE *p; int size; {
927 	if( size == SZLONG && p->in.op == REG ) {
928 		putstr( rnames[p->tn.rval + 1] );
929 		return;
930 		}
931 	cerror( "upput" );
932 	}
933 
934 adrput( p ) register NODE *p; {
935 	register int r;
936 	/* output an address, with offsets, from p */
937 
938 	if( p->in.op == FLD ){
939 		p = p->in.left;
940 		}
941 	switch( p->in.op ){
942 
943 	case NAME:
944 		acon( p );
945 		return;
946 
947 	case ICON:
948 		/* addressable value of the constant */
949 		putchar( '$' );
950 		acon( p );
951 		return;
952 
953 	case REG:
954 		putstr( rnames[p->tn.rval] );
955 		return;
956 
957 	case OREG:
958 		r = p->tn.rval;
959 		if( R2TEST(r) ){ /* double indexing */
960 			register int flags;
961 
962 			flags = R2UPK3(r);
963 			if( flags & 1 ) putchar('*');
964 			if( flags & 4 ) putchar('-');
965 			if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
966 			if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
967 			if( flags & 2 ) putchar('+');
968 			printf( "[%s]", rnames[R2UPK2(r)] );
969 			return;
970 			}
971 		if( r == AP ){  /* in the argument region */
972 			if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
973 			printf( CONFMT, p->tn.lval );
974 			putstr( "(ap)" );
975 			return;
976 			}
977 		if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
978 		printf( "(%s)", rnames[p->tn.rval] );
979 		return;
980 
981 	case UNARY MUL:
982 		/* STARNM or STARREG found */
983 		if( tshape(p, STARNM) ) {
984 			putchar( '*' );
985 			adrput( p->in.left);
986 			}
987 		else {	/* STARREG - really auto inc or dec */
988 			register NODE *q;
989 
990 			q = p->in.left;
991 			if( q->in.right->tn.lval != tlen(p) )
992 				cerror("adrput: bad auto-increment/decrement");
993 			printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
994 				rnames[q->in.left->tn.rval],
995 				(q->in.op==INCR ? "+" : "") );
996 			p->in.op = OREG;
997 			p->tn.rval = q->in.left->tn.rval;
998 			p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
999 #ifndef FLEXNAMES
1000 			p->in.name[0] = '\0';
1001 #else
1002 			p->in.name = "";
1003 #endif
1004 			tfree(q);
1005 		}
1006 		return;
1007 
1008 	default:
1009 		cerror( "illegal address" );
1010 		return;
1011 
1012 		}
1013 
1014 	}
1015 
1016 acon( p ) register NODE *p; { /* print out a constant */
1017 
1018 	if( p->in.name[0] == '\0' )
1019 		printf( CONFMT, p->tn.lval);
1020 	else {
1021 #ifndef FLEXNAMES
1022 		printf( "%.8s", p->in.name );
1023 #else
1024 		putstr( p->in.name );
1025 #endif
1026 		if( p->tn.lval != 0 ) {
1027 			putchar( '+' );
1028 			printf( CONFMT, p->tn.lval );
1029 			}
1030 		}
1031 	}
1032 
1033 genscall( p, cookie ) register NODE *p; {
1034 	/* structure valued call */
1035 	return( gencall( p, cookie ) );
1036 	}
1037 
1038 /* tbl */
1039 int gc_numbytes;
1040 /* tbl */
1041 
1042 /*ARGSUSED*/
1043 gencall( p, cookie ) register NODE *p; {
1044 	/* generate the call given by p */
1045 	register NODE *p1;
1046 	register int temp, temp1;
1047 	register int m;
1048 
1049 	if( p->in.right ) temp = argsize( p->in.right );
1050 	else temp = 0;
1051 
1052 	if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1053 		/* set aside room for structure return */
1054 
1055 		if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1056 		else temp1 = temp;
1057 		}
1058 
1059 	if( temp > maxargs ) maxargs = temp;
1060 	SETOFF(temp1,4);
1061 
1062 	if( p->in.right ){ /* make temp node, put offset in, and generate args */
1063 		genargs( p->in.right );
1064 		}
1065 
1066 	p1 = p->in.left;
1067 	if( p1->in.op != ICON ){
1068 		if( p1->in.op != REG ){
1069 			if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1070 				if( p1->in.op != NAME ){
1071 					order( p1, INAREG );
1072 					}
1073 				}
1074 			}
1075 		}
1076 
1077 /* tbl
1078 	setup gc_numbytes so reference to ZC works */
1079 
1080 	gc_numbytes = temp&(0x3ff);
1081 /* tbl */
1082 
1083 	p->in.op = UNARY CALL;
1084 	m = match( p, INTAREG|INTBREG );
1085 
1086 	/* compensate for deficiency in 'ret' instruction ... wah,kre */
1087 	/* (plus in assignment to gc_numbytes above, for neatness only) */
1088 	if (temp >= 1024)
1089 		printf("	addl2	$%d,sp\n", (temp&(~0x3ff)));
1090 
1091 	return(m != MDONE);
1092 	}
1093 
1094 /* tbl */
1095 char *
1096 ccbranches[] = {
1097 	"eql",
1098 	"neq",
1099 	"leq",
1100 	"lss",
1101 	"geq",
1102 	"gtr",
1103 	"lequ",
1104 	"lssu",
1105 	"gequ",
1106 	"gtru",
1107 	};
1108 /* tbl */
1109 
1110 /*ARGSUSED*/
1111 cbgen( o, lab, mode ) { /*   printf conditional and unconditional branches */
1112 
1113 	if( o != 0 && ( o < EQ || o > UGT ) )
1114 		cerror( "bad conditional branch: %s", opst[o] );
1115 	printf( "	j%s	L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab );
1116 	}
1117 
1118 nextcook( p, cookie ) NODE *p; {
1119 	/* we have failed to match p with cookie; try another */
1120 	if( cookie == FORREW ) return( 0 );  /* hopeless! */
1121 	if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1122 	if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1123 	return( FORREW );
1124 	}
1125 
1126 /*ARGSUSED*/
1127 lastchance( p, cook ) NODE *p; {
1128 	/* forget it! */
1129 	return(0);
1130 	}
1131 
1132 optim2( p ) register NODE *p; {
1133 	/* do local tree transformations and optimizations */
1134 
1135 	int o;
1136 	int i, mask;
1137 	register NODE *l, *r;
1138 
1139 	switch( o = p->in.op ) {
1140 
1141 	case AND:
1142 		/* commute L and R to eliminate complements and constants */
1143 		if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
1144 		    l->in.op == COMPL ) {
1145 			p->in.left = p->in.right;
1146 			p->in.right = l;
1147 			}
1148 	case ASG AND:
1149 		/* change meaning of AND to ~R&L - bic on pdp11 */
1150 		r = p->in.right;
1151 		if( r->in.op==ICON && r->in.name[0]==0 ) {
1152 			/* check for degenerate operations */
1153 			l = p->in.left;
1154 			mask = (1 << tlen(l) * SZCHAR) - 1;
1155 			if( ISUNSIGNED(r->in.type) ) {
1156 				i = (r->tn.lval & mask);
1157 				if( i == mask ) {
1158 					r->in.op = FREE;
1159 					ncopy(p, l);
1160 					l->in.op = FREE;
1161 					break;
1162 					}
1163 				else if( i == 0 )
1164 					goto zero;
1165 				else
1166 					r->tn.lval = i;
1167 				}
1168 			else if( r->tn.lval == mask &&
1169 				 tlen(l) < SZINT/SZCHAR ) {
1170 				r->in.op = SCONV;
1171 				r->in.left = l;
1172 				r->in.right = 0;
1173 				r->in.type = ENUNSIGN(l->in.type);
1174 				r->in.su = l->in.su > 1 ? l->in.su : 1;
1175 				ncopy(p, r);
1176 				p->in.left = r;
1177 				p->in.type = INT;
1178 				break;
1179 				}
1180 			/* complement constant */
1181 			r->tn.lval = ~r->tn.lval;
1182 			}
1183 		else if( r->in.op==COMPL ) { /* ~~A => A */
1184 			r->in.op = FREE;
1185 			p->in.right = r->in.left;
1186 			}
1187 		else { /* insert complement node */
1188 			p->in.right = l = talloc();
1189 			l->in.op = COMPL;
1190 			l->in.rall = NOPREF;
1191 			l->in.type = r->in.type;
1192 			l->in.left = r;
1193 			l->in.right = NULL;
1194 			}
1195 		break;
1196 
1197 	case SCONV:
1198 		l = p->in.left;
1199 #if defined(FORT) || defined(SPRECC)
1200 		if( p->in.type == FLOAT || p->in.type == DOUBLE ||
1201 		    l->in.type == FLOAT || l->in.type == DOUBLE )
1202 			return;
1203 #else
1204 		if( mixtypes(p, l) ) return;
1205 #endif
1206 		if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL )
1207 			return;
1208 
1209 		/* Only trust it to get it right if the size is the same */
1210 		if( tlen(p) != tlen(l) )
1211 			return;
1212 
1213 		/* clobber conversion */
1214 		if( l->in.op != FLD )
1215 			l->in.type = p->in.type;
1216 		ncopy( p, l );
1217 		l->in.op = FREE;
1218 
1219 		break;
1220 
1221 	case ASSIGN:
1222 		/*
1223 		 * Conversions are equivalent to assignments;
1224 		 * when the two operations are combined,
1225 		 * we can sometimes zap the conversion.
1226 		 */
1227 		r = p->in.right;
1228 		l = p->in.left;
1229 		if ( r->in.op == SCONV &&
1230 		     !mixtypes(l, r) &&
1231 		     l->in.op != FLD &&
1232 		     tlen(l) == tlen(r) ) {
1233 				p->in.right = r->in.left;
1234 				r->in.op = FREE;
1235 			}
1236 		break;
1237 
1238 	case ULE:
1239 	case ULT:
1240 	case UGE:
1241 	case UGT:
1242 		p->in.op -= (UGE-GE);
1243 		if( degenerate(p) )
1244 			break;
1245 		p->in.op += (UGE-GE);
1246 		break;
1247 
1248 	case EQ:
1249 	case NE:
1250 	case LE:
1251 	case LT:
1252 	case GE:
1253 	case GT:
1254 		(void) degenerate(p);
1255 		break;
1256 
1257 	case DIV:
1258 		if( p->in.right->in.op == ICON &&
1259 		    p->in.right->tn.name[0] == '\0' &&
1260 		    ISUNSIGNED(p->in.right->in.type) &&
1261 		    (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
1262 			/* easy to do here, harder to do in zzzcode() */
1263 			p->in.op = UGE;
1264 			break;
1265 			}
1266 	case MOD:
1267 	case ASG DIV:
1268 	case ASG MOD:
1269 		/*
1270 		 * optimize DIV and MOD
1271 		 *
1272 		 * basically we spot UCHAR and USHORT and try to do them
1273 		 * as signed ints...  apparently div+mul+sub is always
1274 		 * faster than ediv for finding MOD on the VAX, when
1275 		 * full unsigned MOD isn't needed.
1276 		 *
1277 		 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
1278 		 * are faster for unsigned dividend and a constant divisor
1279 		 * in the right range (.5 to 1 of dividend's range for the
1280 		 * first, .333+ to .5 for the second).  full unsigned is
1281 		 * already done cmp+sub in the appropriate case; the
1282 		 * other cases are less common and require more ambition.
1283 		 */
1284 		if( degenerate(p) )
1285 			break;
1286 		l = p->in.left;
1287 		r = p->in.right;
1288 		if( !ISUNSIGNED(r->in.type) ||
1289 		    tlen(l) >= SZINT/SZCHAR ||
1290 		    !(tlen(r) < SZINT/SZCHAR ||
1291 		      (r->in.op == ICON && r->tn.name[0] == '\0')) )
1292 			break;
1293 		if( r->in.op == ICON )
1294 			r->tn.type = INT;
1295 		else {
1296 			NODE *t = talloc();
1297 			t->in.left = r;
1298 			r = t;
1299 			r->in.op = SCONV;
1300 			r->in.type = INT;
1301 			r->in.right = 0;
1302 			p->in.right = r;
1303 			}
1304 		if( o == DIV || o == MOD ) {
1305 			NODE *t = talloc();
1306 			t->in.left = l;
1307 			l = t;
1308 			l->in.op = SCONV;
1309 			l->in.type = INT;
1310 			l->in.right = 0;
1311 			p->in.left = l;
1312 			}
1313 		/* handle asgops in table */
1314 		break;
1315 
1316 	case RS:
1317 	case ASG RS:
1318 	case LS:
1319 	case ASG LS:
1320 		/* pick up degenerate shifts */
1321 		l = p->in.left;
1322 		r = p->in.right;
1323 		if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
1324 			break;
1325 		i = r->tn.lval;
1326 		if( i < 0 )
1327 			/* front end 'fixes' this? */
1328 			if( o == LS || o == ASG LS )
1329 				o += (RS-LS);
1330 			else
1331 				o += (LS-RS);
1332 		if( (o == RS || o == ASG RS) &&
1333 		    !ISUNSIGNED(l->in.type) )
1334 			/* can't optimize signed right shifts */
1335 			break;
1336 		if( o == LS ) {
1337 			if( i < SZINT )
1338 				break;
1339 			}
1340 		else {
1341 			if( i < tlen(l) * SZCHAR )
1342 				break;
1343 			}
1344 	zero:
1345 		if( !asgop( o ) )
1346 			if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1347 				/* no side effects */
1348 				tfree(l);
1349 				ncopy(p, r);
1350 				r->in.op = FREE;
1351 				p->tn.lval = 0;
1352 				}
1353 			else {
1354 				p->in.op = COMOP;
1355 				r->tn.lval = 0;
1356 				}
1357 		else {
1358 			p->in.op = ASSIGN;
1359 			r->tn.lval = 0;
1360 			}
1361 		break;
1362 		}
1363 	}
1364 
1365 degenerate(p) register NODE *p; {
1366 	int o;
1367 	int result, i;
1368 	int lower, upper;
1369 	register NODE *l, *r;
1370 
1371 	/*
1372 	 * try to keep degenerate comparisons with constants
1373 	 * out of the table.
1374 	 */
1375 	r = p->in.right;
1376 	l = p->in.left;
1377 	if( r->in.op != ICON ||
1378 	    r->tn.name[0] != '\0' ||
1379 	    tlen(l) >= tlen(r) )
1380 		return (0);
1381 	switch( l->in.type ) {
1382 	case CHAR:
1383 		lower = -(1 << SZCHAR - 1);
1384 		upper = (1 << SZCHAR - 1) - 1;
1385 		break;
1386 	case UCHAR:
1387 		lower = 0;
1388 		upper = (1 << SZCHAR) - 1;
1389 		break;
1390 	case SHORT:
1391 		lower = -(1 << SZSHORT - 1);
1392 		upper = (1 << SZSHORT - 1) - 1;
1393 		break;
1394 	case USHORT:
1395 		lower = 0;
1396 		upper = (1 << SZSHORT) - 1;
1397 		break;
1398 	default:
1399 		cerror("unsupported type in degenerate()");
1400 		}
1401 	i = r->tn.lval;
1402 	switch( o = p->in.op ) {
1403 	case DIV:
1404 	case ASG DIV:
1405 	case MOD:
1406 	case ASG MOD:
1407 		/* DIV and MOD work like EQ */
1408 	case EQ:
1409 	case NE:
1410 		if( lower == 0 && (unsigned) i > upper )
1411 			result = o == NE;
1412 		else if( i < lower || i > upper )
1413 			result = o == NE;
1414 		else
1415 			return (0);
1416 		break;
1417 	case LT:
1418 	case GE:
1419 		if( lower == 0 && (unsigned) i > upper )
1420 			result = o == LT;
1421 		else if( i <= lower )
1422 			result = o != LT;
1423 		else if( i > upper )
1424 			result = o == LT;
1425 		else
1426 			return (0);
1427 		break;
1428 	case LE:
1429 	case GT:
1430 		if( lower == 0 && (unsigned) i >= upper )
1431 			result = o == LE;
1432 		else if( i < lower )
1433 			result = o != LE;
1434 		else if( i >= upper )
1435 			result = o == LE;
1436 		else
1437 			return (0);
1438 		break;
1439 	default:
1440 		cerror("unknown op in degenerate()");
1441 		}
1442 
1443 	if( o == MOD || o == ASG MOD ) {
1444 		r->in.op = FREE;
1445 		ncopy(p, l);
1446 		l->in.op = FREE;
1447 		}
1448 	else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1449 		/* no side effects */
1450 		tfree(l);
1451 		ncopy(p, r);
1452 		r->in.op = FREE;
1453 		p->tn.lval = result;
1454 		}
1455 	else {
1456 		if( o == ASG DIV )
1457 			p->in.op = ASSIGN;
1458 		else {
1459 			p->in.op = COMOP;
1460 			r->tn.type = INT;
1461 			}
1462 		r->tn.lval = result;
1463 		}
1464 	if( logop(o) )
1465 		p->in.type = INT;
1466 
1467 	return (1);
1468 	}
1469 
1470 /* added by jwf */
1471 struct functbl {
1472 	int fop;
1473 	TWORD ftype;
1474 	char *func;
1475 	} opfunc[] = {
1476 	DIV,		TANY,	"udiv",
1477 	MOD,		TANY,	"urem",
1478 	ASG DIV,	TANY,	"audiv",
1479 	ASG MOD,	TANY,	"aurem",
1480 	0,	0,	0 };
1481 
1482 hardops(p)  register NODE *p; {
1483 	/* change hard to do operators into function calls.  */
1484 	register NODE *q;
1485 	register struct functbl *f;
1486 	register o;
1487 	NODE *old,*temp;
1488 
1489 	o = p->in.op;
1490 	if( ! (optype(o)==BITYPE &&
1491 	       (ISUNSIGNED(p->in.left->in.type) ||
1492 		ISUNSIGNED(p->in.right->in.type))) )
1493 		return;
1494 
1495 	for( f=opfunc; f->fop; f++ ) {
1496 		if( o==f->fop ) goto convert;
1497 		}
1498 	return;
1499 
1500 	convert:
1501 	if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
1502 		/* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
1503 		/* save a subroutine call -- use at most 5 instructions */
1504 		return;
1505 	if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
1506 		/* optim2() will modify the op into an ordinary int op */
1507 		return;
1508 	if( asgop( o ) ) {
1509 		old = NIL;
1510 		switch( p->in.left->in.op ){
1511 		case FLD:
1512 			q = p->in.left->in.left;
1513 			/*
1514 			 * rewrite (lval.fld /= rval); as
1515 			 *  ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1516 			 * else the compiler will evaluate lval twice.
1517 			 */
1518 			if( q->in.op == UNARY MUL ){
1519 				/* first allocate a temp storage */
1520 				temp = talloc();
1521 				temp->in.op = OREG;
1522 				temp->tn.rval = TMPREG;
1523 				temp->tn.lval = BITOOR(freetemp(1));
1524 				temp->in.type = INCREF(p->in.type);
1525 #ifdef FLEXNAMES
1526 				temp->in.name = "";
1527 #else
1528 				temp->in.name[0] = '\0';
1529 #endif
1530 				old = q->in.left;
1531 				q->in.left = temp;
1532 			}
1533 			/* fall thru ... */
1534 
1535 		case REG:
1536 		case NAME:
1537 		case OREG:
1538 			/* change ASG OP to a simple OP */
1539 			q = talloc();
1540 			q->in.op = NOASG p->in.op;
1541 			q->in.rall = NOPREF;
1542 			q->in.type = p->in.type;
1543 			q->in.left = tcopy(p->in.left);
1544 			q->in.right = p->in.right;
1545 			p->in.op = ASSIGN;
1546 			p->in.right = q;
1547 			p = q;
1548 			f -= 2; /* Note: this depends on the table order */
1549 			/* on the right side only - replace *temp with
1550 			 *(temp = &lval), build the assignment node */
1551 			if( old ){
1552 				temp = q->in.left->in.left; /* the "*" node */
1553 				q = talloc();
1554 				q->in.op = ASSIGN;
1555 				q->in.left = temp->in.left;
1556 				q->in.right = old;
1557 				q->in.type = old->in.type;
1558 #ifdef FLEXNAMES
1559 				q->in.name = "";
1560 #else
1561 				q->in.name[0] = '\0';
1562 #endif
1563 				temp->in.left = q;
1564 			}
1565 			break;
1566 
1567 		case UNARY MUL:
1568 			/* avoid doing side effects twice */
1569 			q = p->in.left;
1570 			p->in.left = q->in.left;
1571 			q->in.op = FREE;
1572 			break;
1573 
1574 		default:
1575 			cerror( "hardops: can't compute & LHS" );
1576 			}
1577 		}
1578 
1579 	/* build comma op for args to function */
1580 	q = talloc();
1581 	q->in.op = CM;
1582 	q->in.rall = NOPREF;
1583 	q->in.type = INT;
1584 	q->in.left = p->in.left;
1585 	q->in.right = p->in.right;
1586 	p->in.op = CALL;
1587 	p->in.right = q;
1588 
1589 	/* put function name in left node of call */
1590 	p->in.left = q = talloc();
1591 	q->in.op = ICON;
1592 	q->in.rall = NOPREF;
1593 	q->in.type = INCREF( FTN + p->in.type );
1594 #ifndef FLEXNAMES
1595 	strcpy( q->in.name, f->func );
1596 #else
1597 	q->in.name = f->func;
1598 #endif
1599 	q->tn.lval = 0;
1600 	q->tn.rval = 0;
1601 
1602 	}
1603 
1604 zappost(p) NODE *p; {
1605 	/* look for ++ and -- operators and remove them */
1606 
1607 	register int o, ty;
1608 	register NODE *q;
1609 	o = p->in.op;
1610 	ty = optype( o );
1611 
1612 	switch( o ){
1613 
1614 	case INCR:
1615 	case DECR:
1616 			q = p->in.left;
1617 			p->in.right->in.op = FREE;  /* zap constant */
1618 			ncopy( p, q );
1619 			q->in.op = FREE;
1620 			return;
1621 
1622 		}
1623 
1624 	if( ty == BITYPE ) zappost( p->in.right );
1625 	if( ty != LTYPE ) zappost( p->in.left );
1626 }
1627 
1628 fixpre(p) NODE *p; {
1629 
1630 	register int o, ty;
1631 	o = p->in.op;
1632 	ty = optype( o );
1633 
1634 	switch( o ){
1635 
1636 	case ASG PLUS:
1637 			p->in.op = PLUS;
1638 			break;
1639 	case ASG MINUS:
1640 			p->in.op = MINUS;
1641 			break;
1642 		}
1643 
1644 	if( ty == BITYPE ) fixpre( p->in.right );
1645 	if( ty != LTYPE ) fixpre( p->in.left );
1646 }
1647 
1648 /*ARGSUSED*/
1649 NODE * addroreg(l) NODE *l;
1650 				/* OREG was built in clocal()
1651 				 * for an auto or formal parameter
1652 				 * now its address is being taken
1653 				 * local code must unwind it
1654 				 * back to PLUS/MINUS REG ICON
1655 				 * according to local conventions
1656 				 */
1657 {
1658 	cerror("address of OREG taken");
1659 	/*NOTREACHED*/
1660 }
1661 
1662 
1663 
1664 # ifndef ONEPASS
1665 main( argc, argv ) char *argv[]; {
1666 	return( mainp2( argc, argv ) );
1667 	}
1668 # endif
1669 
1670 strip(p) register NODE *p; {
1671 	NODE *q;
1672 
1673 	/* strip nodes off the top when no side effects occur */
1674 	for( ; ; ) {
1675 		switch( p->in.op ) {
1676 		case SCONV:			/* remove lint tidbits */
1677 			q = p->in.left;
1678 			ncopy( p, q );
1679 			q->in.op = FREE;
1680 			break;
1681 		/* could probably add a few more here */
1682 		default:
1683 			return;
1684 			}
1685 		}
1686 	}
1687 
1688 myreader(p) register NODE *p; {
1689 	strip( p );		/* strip off operations with no side effects */
1690 	canon( p );		/* expands r-vals for fields */
1691 	walkf( p, hardops );	/* convert ops to function calls */
1692 	walkf( p, optim2 );
1693 	}
1694