xref: /csrg-svn/old/pcc/mip/reader.c (revision 32828)
117747Sralph #ifndef lint
2*32828Sdonn static char *sccsid ="@(#)reader.c	4.8 (Berkeley) 12/10/87";
317747Sralph #endif lint
417747Sralph 
518394Sralph # include "pass2.h"
617724Sralph 
717724Sralph /*	some storage declarations */
817724Sralph 
917724Sralph # ifndef ONEPASS
1017724Sralph NODE node[TREESZ];
1117724Sralph char filename[100] = "";  /* the name of the file */
1217724Sralph int ftnno;  /* number of current function */
1317724Sralph int lineno;
1417724Sralph # else
1517724Sralph # define NOMAIN
1617724Sralph #endif
1717724Sralph 
1817724Sralph int nrecur;
1917724Sralph int lflag;
2017747Sralph #ifdef FORT
2117747Sralph int Oflag = 0;
2217747Sralph #endif
2317724Sralph extern int Wflag;
2417724Sralph int edebug = 0;
2517724Sralph int xdebug = 0;
2617724Sralph int udebug = 0;
2717724Sralph int vdebug = 0;
2817724Sralph 
2917724Sralph OFFSZ tmpoff;  /* offset for first temporary, in bits for current block */
3017724Sralph OFFSZ maxoff;  /* maximum temporary offset over all blocks in current ftn, in bits */
3117724Sralph int maxtreg;
3217724Sralph 
3317724Sralph NODE *stotree;
3417724Sralph int stocook;
3517724Sralph 
3617724Sralph OFFSZ baseoff = 0;
3717724Sralph OFFSZ maxtemp = 0;
3817724Sralph 
p2init(argc,argv)3917724Sralph p2init( argc, argv ) char *argv[];{
4017724Sralph 	/* set the values of the pass 2 arguments */
4117724Sralph 
4217724Sralph 	register int c;
4317724Sralph 	register char *cp;
4417724Sralph 	register files;
4517724Sralph 
4617724Sralph 	allo0();  /* free all regs */
4717724Sralph 	files = 0;
4817724Sralph 
4917724Sralph 	for( c=1; c<argc; ++c ){
5017724Sralph 		if( *(cp=argv[c]) == '-' ){
5117724Sralph 			while( *++cp ){
5217724Sralph 				switch( *cp ){
5317724Sralph 
5417724Sralph 				case 'X':  /* pass1 flags */
5517724Sralph 					while( *++cp ) { /* VOID */ }
5617724Sralph 					--cp;
5717724Sralph 					break;
5817724Sralph 
5917724Sralph 				case 'l':  /* linenos */
6017724Sralph 					++lflag;
6117724Sralph 					break;
6217724Sralph 
6317724Sralph 				case 'e':  /* expressions */
6417724Sralph 					++edebug;
6517724Sralph 					break;
6617724Sralph 
6717724Sralph 				case 'o':  /* orders */
6817724Sralph 					++odebug;
6917724Sralph 					break;
7017724Sralph 
7117724Sralph 				case 'r':  /* register allocation */
7217724Sralph 					++rdebug;
7317724Sralph 					break;
7417724Sralph 
7517724Sralph 				case 'a':  /* rallo */
7617724Sralph 					++radebug;
7717724Sralph 					break;
7817724Sralph 
7917724Sralph 				case 'v':
8017724Sralph 					++vdebug;
8117724Sralph 					break;
8217724Sralph 
8317724Sralph 				case 't':  /* ttype calls */
8417724Sralph 					++tdebug;
8517724Sralph 					break;
8617724Sralph 
8717724Sralph 				case 's':  /* shapes */
8817724Sralph 					++sdebug;
8917724Sralph 					break;
9017724Sralph 
9117724Sralph 				case 'u':  /* Sethi-Ullman testing (machine dependent) */
9217724Sralph 					++udebug;
9317724Sralph 					break;
9417724Sralph 
9517724Sralph 				case 'x':  /* general machine-dependent debugging flag */
9617724Sralph 					++xdebug;
9717724Sralph 					break;
9817724Sralph 
9917724Sralph 				case 'w':
10017724Sralph 				case 'W':  /* shut up warnings */
10117724Sralph 
10217724Sralph 					++Wflag;
10317724Sralph 					break;
10417724Sralph 
10517747Sralph #ifdef FORT
10617747Sralph 				case 'O':  /* optimizing */
10717747Sralph 					++Oflag;
10817747Sralph 					break;
10917747Sralph #endif
11017747Sralph 
11117724Sralph 				default:
11217724Sralph 					cerror( "bad option: %c", *cp );
11317724Sralph 					}
11417724Sralph 				}
11517724Sralph 			}
11617724Sralph 		else files = 1;  /* assumed to be a filename */
11717724Sralph 		}
11817724Sralph 
11917724Sralph 	mkdope();
12017724Sralph 	setrew();
12117724Sralph 	return( files );
12217724Sralph 
12317724Sralph 	}
12417724Sralph 
12517724Sralph # ifndef NOMAIN
12617724Sralph 
12717724Sralph unsigned int caloff();
12817724Sralph unsigned int offsz;
mainp2(argc,argv)12917724Sralph mainp2( argc, argv ) char *argv[]; {
13017724Sralph 	register files;
13117724Sralph 	register temp;
13217724Sralph 	register c;
13317724Sralph 	register char *cp;
13417724Sralph 	register NODE *p;
13517724Sralph 
13617724Sralph 	offsz = caloff();
13717724Sralph 	files = p2init( argc, argv );
13817724Sralph 	tinit();
13917724Sralph 
14017724Sralph 	reread:
14117724Sralph 
14217724Sralph 	if( files ){
14317724Sralph 		while( files < argc && argv[files][0] == '-' ) {
14417724Sralph 			++files;
14517724Sralph 			}
14617724Sralph 		if( files > argc ) return( nerrors );
14717724Sralph 		freopen( argv[files], "r", stdin );
14817724Sralph 		}
14917724Sralph 	while( (c=getchar()) > 0 ) switch( c ){
15017724Sralph 	case ')':
15117724Sralph 	default:
15217724Sralph 		/* copy line unchanged */
15317724Sralph 		if ( c != ')' )
15417724Sralph 			PUTCHAR( c );  /*  initial tab  */
15517724Sralph 		while( (c=getchar()) > 0 ){
15617724Sralph 			PUTCHAR(c);
15717724Sralph 			if( c == '\n' ) break;
15817724Sralph 			}
15917724Sralph 		continue;
16017724Sralph 
16117724Sralph 	case BBEG:
16217724Sralph 		/* beginning of a block */
16317724Sralph 		temp = rdin(10);  /* ftnno */
16417724Sralph 		tmpoff = baseoff = (unsigned int) rdin(10); /* autooff for block gives max offset of autos in block */
16517724Sralph 		maxtreg = rdin(10);
16617724Sralph 		if( getchar() != '\n' ) cerror( "intermediate file format error");
16717724Sralph 
16817724Sralph 		if( temp != ftnno ){ /* beginning of function */
16917724Sralph 			maxoff = baseoff;
17017724Sralph 			ftnno = temp;
17117724Sralph 			maxtemp = 0;
17217724Sralph 			}
17317724Sralph 		else {
17417724Sralph 			if( baseoff > maxoff ) maxoff = baseoff;
17517724Sralph 			/* maxoff at end of ftn is max of autos and temps
17617724Sralph 			   over all blocks in the function */
17717724Sralph 			}
17817724Sralph 		setregs();
17917724Sralph 		continue;
18017724Sralph 
18117724Sralph 	case BEND:  /* end of block */
18217724Sralph 		SETOFF( maxoff, ALSTACK );
18317724Sralph 		eobl2();
18417724Sralph 		while( (c=getchar()) != '\n' ){
18517724Sralph 			if( c <= 0 ) cerror( "intermediate file format eof" );
18617724Sralph 			}
18717724Sralph 		continue;
18817724Sralph 
18917724Sralph 	case EXPR:
19017724Sralph 		/* compile code for an expression */
19117724Sralph 		lineno = rdin( 10 );
19217724Sralph 		for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */
19317724Sralph 		*cp = '\0';
19417724Sralph 		if( lflag ) lineid( lineno, filename );
19517724Sralph 
19617724Sralph 		tmpoff = baseoff;  /* expression at top level reuses temps */
19717724Sralph 		p = eread();
19817724Sralph 
19917724Sralph # ifndef BUG4
20017724Sralph 		if( edebug ) fwalk( p, eprint, 0 );
20117724Sralph # endif
20217724Sralph 
20317724Sralph # ifdef MYREADER
20417724Sralph 		MYREADER(p);  /* do your own laundering of the input */
20517724Sralph # endif
20617724Sralph 
20717724Sralph 		nrecur = 0;
20817724Sralph 		delay( p );  /* expression statement  throws out results */
20917724Sralph 		reclaim( p, RNULL, 0 );
21017724Sralph 
21117724Sralph 		allchk();
21217724Sralph 		tcheck();
21317724Sralph 		continue;
21417724Sralph 
21517724Sralph 		}
21617724Sralph 
21717724Sralph 	/* EOF */
21817724Sralph 	if( files ) goto reread;
21917724Sralph 	return(nerrors);
22017724Sralph 
22117724Sralph 	}
22217724Sralph 
22317724Sralph # endif
22417724Sralph 
22517724Sralph # ifdef ONEPASS
22617724Sralph 
p2compile(p)22717724Sralph p2compile( p ) NODE *p; {
22817724Sralph 
22917724Sralph 	if( lflag ) lineid( lineno, filename );
23017724Sralph 	tmpoff = baseoff;  /* expression at top level reuses temps */
23117724Sralph 	/* generate code for the tree p */
23217724Sralph # ifndef BUG4
23317724Sralph 	if( edebug ) fwalk( p, eprint, 0 );
23417724Sralph # endif
23517724Sralph 
23617724Sralph # ifdef MYREADER
23717724Sralph 	MYREADER(p);  /* do your own laundering of the input */
23817724Sralph # endif
23917724Sralph 	nrecur = 0;
24017724Sralph 	delay( p );  /* do the code generation */
24117724Sralph 	reclaim( p, RNULL, 0 );
24217724Sralph 	allchk();
24317724Sralph 	/* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
24417724Sralph 	/* first pass will do it... */
24517724Sralph 	}
24617724Sralph 
p2bbeg(aoff,myreg)24717724Sralph p2bbeg( aoff, myreg ) {
24817724Sralph 	static int myftn = -1;
24917724Sralph 
25017724Sralph 	tmpoff = baseoff = (unsigned int) aoff;
25117724Sralph 	maxtreg = myreg;
25217724Sralph 	if( myftn != ftnno ){ /* beginning of function */
25317724Sralph 		maxoff = baseoff;
25417724Sralph 		myftn = ftnno;
25517724Sralph 		maxtemp = 0;
25617724Sralph 		}
25717724Sralph 	else {
25817724Sralph 		if( baseoff > maxoff ) maxoff = baseoff;
25917724Sralph 		/* maxoff at end of ftn is max of autos and temps over all blocks */
26017724Sralph 		}
26117724Sralph 	setregs();
26217724Sralph 	}
26317724Sralph 
p2bend()26417724Sralph p2bend(){
26517724Sralph 	SETOFF( maxoff, ALSTACK );
26617724Sralph 	eobl2();
26717724Sralph 	}
26817724Sralph 
26917724Sralph # endif
27017724Sralph 
27117724Sralph NODE *deltrees[DELAYS];
27217724Sralph int deli;
27317724Sralph 
delay(p)27417724Sralph delay( p ) register NODE *p; {
27517724Sralph 	/* look in all legal places for COMOP's and ++ and -- ops to delay */
27617724Sralph 	/* note; don't delay ++ and -- within calls or things like
27717724Sralph 	/* getchar (in their macro forms) will start behaving strangely */
27817724Sralph 	register i;
27917724Sralph 
28017724Sralph 	/* look for visible COMOPS, and rewrite repeatedly */
28117724Sralph 
28217724Sralph 	while( delay1( p ) ) { /* VOID */ }
28317724Sralph 
28417724Sralph 	/* look for visible, delayable ++ and -- */
28517724Sralph 
28617724Sralph 	deli = 0;
28717724Sralph 	delay2( p );
28817724Sralph 	codgen( p, FOREFF );  /* do what is left */
28917724Sralph 	for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF );  /* do the rest */
29017724Sralph 	}
29117724Sralph 
delay1(p)29217724Sralph delay1( p ) register NODE *p; {  /* look for COMOPS */
29317724Sralph 	register o, ty;
29417724Sralph 
29517724Sralph 	o = p->in.op;
29617724Sralph 	ty = optype( o );
29717724Sralph 	if( ty == LTYPE ) return( 0 );
29817724Sralph 	else if( ty == UTYPE ) return( delay1( p->in.left ) );
29917724Sralph 
30017724Sralph 	switch( o ){
30117724Sralph 
30217724Sralph 	case QUEST:
30317724Sralph 	case ANDAND:
30417724Sralph 	case OROR:
30517724Sralph 		/* don't look on RHS */
30617724Sralph 		return( delay1(p->in.left ) );
30717724Sralph 
30817724Sralph 	case COMOP:  /* the meat of the routine */
30917724Sralph 		delay( p->in.left );  /* completely evaluate the LHS */
31017724Sralph 		/* rewrite the COMOP */
31117724Sralph 		{ register NODE *q;
31217724Sralph 			q = p->in.right;
31317724Sralph 			ncopy( p, p->in.right );
31417724Sralph 			q->in.op = FREE;
31517724Sralph 			}
31617724Sralph 		return( 1 );
31717724Sralph 		}
31817724Sralph 
31917724Sralph 	return( delay1(p->in.left) || delay1(p->in.right ) );
32017724Sralph 	}
32117724Sralph 
delay2(p)32217724Sralph delay2( p ) register NODE *p; {
32317724Sralph 
32417724Sralph 	/* look for delayable ++ and -- operators */
32517724Sralph 
32617724Sralph 	register o, ty;
32717724Sralph 	o = p->in.op;
32817724Sralph 	ty = optype( o );
32917724Sralph 
33017724Sralph 	switch( o ){
33117724Sralph 
33217724Sralph 	case NOT:
33317724Sralph 	case QUEST:
33417724Sralph 	case ANDAND:
33517724Sralph 	case OROR:
33617724Sralph 	case CALL:
33717724Sralph 	case UNARY CALL:
33817724Sralph 	case STCALL:
33917724Sralph 	case UNARY STCALL:
34017724Sralph 	case FORTCALL:
34117724Sralph 	case UNARY FORTCALL:
34217724Sralph 	case COMOP:
34317724Sralph 	case CBRANCH:
34424406Smckusick 		/* for the moment, don't delay past a conditional context, or
34517724Sralph 		/* inside of a call */
34617724Sralph 		return;
34717724Sralph 
34817724Sralph 	case UNARY MUL:
34917724Sralph 		/* if *p++, do not rewrite */
35017724Sralph 		if( autoincr( p ) ) return;
35117724Sralph 		break;
35217724Sralph 
35317724Sralph 	case INCR:
35417724Sralph 	case DECR:
35517724Sralph 		if( deltest( p ) ){
35617724Sralph 			if( deli < DELAYS ){
35717724Sralph 				register NODE *q;
35817724Sralph 				deltrees[deli++] = tcopy(p);
35917724Sralph 				q = p->in.left;
36017724Sralph 				p->in.right->in.op = FREE;  /* zap constant */
36117724Sralph 				ncopy( p, q );
36217724Sralph 				q->in.op = FREE;
36317724Sralph 				return;
36417724Sralph 				}
36517724Sralph 			}
36617724Sralph 
36717724Sralph 		}
36817724Sralph 
36917724Sralph 	if( ty == BITYPE ) delay2( p->in.right );
37017724Sralph 	if( ty != LTYPE ) delay2( p->in.left );
37117724Sralph 	}
37217724Sralph 
codgen(p,cookie)37317724Sralph codgen( p, cookie ) NODE *p; {
37417724Sralph 
37517724Sralph 	/* generate the code for p;
37617724Sralph 	   order may call codgen recursively */
37717724Sralph 	/* cookie is used to describe the context */
37817724Sralph 
37917724Sralph 	for(;;){
38017724Sralph 		canon(p);  /* creats OREG from * if possible and does sucomp */
38117724Sralph 		stotree = NIL;
38217724Sralph # ifndef BUG4
38317724Sralph 		if( edebug ){
38417724Sralph 			printf( "store called on:\n" );
38517724Sralph 			fwalk( p, eprint, 0 );
38617724Sralph 			}
38717724Sralph # endif
38817724Sralph 		store(p);
38917724Sralph 		if( stotree==NIL ) break;
39017724Sralph 
39117724Sralph 		/* because it's minimal, can do w.o. stores */
39217724Sralph 
39317724Sralph 		order( stotree, stocook );
39417724Sralph 		}
39517724Sralph 
39617724Sralph 	order( p, cookie );
39717724Sralph 
39817724Sralph 	}
39917724Sralph 
40017724Sralph # ifndef BUG4
40117724Sralph char *cnames[] = {
40217724Sralph 	"SANY",
40317724Sralph 	"SAREG",
40417724Sralph 	"STAREG",
40517724Sralph 	"SBREG",
40617724Sralph 	"STBREG",
40717724Sralph 	"SCC",
40817724Sralph 	"SNAME",
40917724Sralph 	"SCON",
41017724Sralph 	"SFLD",
41117724Sralph 	"SOREG",
41217724Sralph # ifdef WCARD1
41317724Sralph 	"WCARD1",
41417724Sralph # else
41517724Sralph 	"STARNM",
41617724Sralph # endif
41717747Sralph # ifdef WCARD2
41817724Sralph 	"WCARD2",
41917724Sralph # else
42017724Sralph 	"STARREG",
42117724Sralph # endif
42217724Sralph 	"INTEMP",
42317724Sralph 	"FORARG",
42417724Sralph 	"SWADD",
42517724Sralph 	0,
42617724Sralph 	};
42717724Sralph 
prcook(cookie)42817724Sralph prcook( cookie ){
42917724Sralph 
43017724Sralph 	/* print a nice-looking description of cookie */
43117724Sralph 
43217724Sralph 	int i, flag;
43317724Sralph 
43417724Sralph 	if( cookie & SPECIAL ){
43517724Sralph 		if( cookie == SZERO ) printf( "SZERO" );
43617724Sralph 		else if( cookie == SONE ) printf( "SONE" );
43717724Sralph 		else if( cookie == SMONE ) printf( "SMONE" );
43824406Smckusick 		else if( cookie == SCCON ) printf( "SCCON" );
43924406Smckusick 		else if( cookie == SSCON ) printf( "SSCON" );
44024406Smckusick 		else if( cookie == SSOREG ) printf( "SSOREG" );
44117724Sralph 		else printf( "SPECIAL+%d", cookie & ~SPECIAL );
44217724Sralph 		return;
44317724Sralph 		}
44417724Sralph 
44517724Sralph 	flag = 0;
44617724Sralph 	for( i=0; cnames[i]; ++i ){
44717724Sralph 		if( cookie & (1<<i) ){
44817724Sralph 			if( flag ) printf( "|" );
44917724Sralph 			++flag;
45017724Sralph 			printf( cnames[i] );
45117724Sralph 			}
45217724Sralph 		}
45317724Sralph 
45417724Sralph 	}
45517724Sralph # endif
45617724Sralph 
45717724Sralph int odebug = 0;
45817724Sralph 
order(p,cook)45932827Sdonn order(p,cook) register NODE *p; {
46017724Sralph 
46117724Sralph 	register o, ty, m;
46217724Sralph 	int m1;
46317724Sralph 	int cookie;
46432827Sdonn 	register NODE *p1, *p2;
46517724Sralph 
46617724Sralph 	cookie = cook;
46717724Sralph 	rcount();
46817724Sralph 	canon(p);
46917724Sralph 	rallo( p, p->in.rall );
47017724Sralph 	goto first;
47117724Sralph 	/* by this time, p should be able to be generated without stores;
47217724Sralph 	   the only question is how */
47317724Sralph 
47417724Sralph 	again:
47517724Sralph 
47617724Sralph 	if ( p->in.op == FREE )
47717724Sralph 		return;		/* whole tree was done */
47817724Sralph 	cookie = cook;
47917724Sralph 	rcount();
48017724Sralph 	canon(p);
48117724Sralph 	rallo( p, p->in.rall );
48217724Sralph 	/* if any rewriting and canonicalization has put
48317724Sralph 	 * the tree (p) into a shape that cook is happy
48417724Sralph 	 * with (exclusive of FOREFF, FORREW, and INTEMP)
48517724Sralph 	 * then we are done.
48617724Sralph 	 * this allows us to call order with shapes in
48717724Sralph 	 * addition to cookies and stop short if possible.
48817724Sralph 	 */
48917724Sralph 	if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return;
49017724Sralph 
49117724Sralph 	first:
49217724Sralph # ifndef BUG4
49317724Sralph 	if( odebug ){
49417724Sralph 		printf( "order( %o, ", p );
49517724Sralph 		prcook( cookie );
49617724Sralph 		printf( " )\n" );
49717724Sralph 		fwalk( p, eprint, 0 );
49817724Sralph 		}
49917724Sralph # endif
50017724Sralph 
50117724Sralph 	o = p->in.op;
50217724Sralph 	ty = optype(o);
50317724Sralph 
50417724Sralph 	/* first of all, for most ops, see if it is in the table */
50517724Sralph 
50617724Sralph 	/* look for ops */
50717724Sralph 
50817724Sralph 	switch( m = p->in.op ){
50917724Sralph 
51017724Sralph 	default:
51117724Sralph 		/* look for op in table */
51217724Sralph 		for(;;){
51317724Sralph 			if( (m = match( p, cookie ) ) == MDONE ) goto cleanup;
51417724Sralph 			else if( m == MNOPE ){
51517724Sralph 				if( !(cookie = nextcook( p, cookie ) ) ) goto nomat;
51617724Sralph 				continue;
51717724Sralph 				}
51817724Sralph 			else break;
51917724Sralph 			}
52017724Sralph 		break;
52117724Sralph 
52217724Sralph 	case COMOP:
52317724Sralph 	case FORCE:
52417724Sralph 	case CBRANCH:
52517724Sralph 	case QUEST:
52617724Sralph 	case ANDAND:
52717724Sralph 	case OROR:
52817724Sralph 	case NOT:
52917724Sralph 	case UNARY CALL:
53017724Sralph 	case CALL:
53117724Sralph 	case UNARY STCALL:
53217724Sralph 	case STCALL:
53317724Sralph 	case UNARY FORTCALL:
53417724Sralph 	case FORTCALL:
53517724Sralph 		/* don't even go near the table... */
53617724Sralph 		;
53717724Sralph 
53817724Sralph 		}
53917724Sralph 	/* get here to do rewriting if no match or
54017724Sralph 	   fall through from above for hard ops */
54117724Sralph 
54217724Sralph 	p1 = p->in.left;
54317724Sralph 	if( ty == BITYPE ) p2 = p->in.right;
54417724Sralph 	else p2 = NIL;
54517724Sralph 
54617724Sralph # ifndef BUG4
54717724Sralph 	if( odebug ){
54817724Sralph 		printf( "order( %o, ", p );
54917724Sralph 		prcook( cook );
55017724Sralph 		printf( " ), cookie " );
55117724Sralph 		prcook( cookie );
55217724Sralph 		printf( ", rewrite %s\n", opst[m] );
55317724Sralph 		}
55417724Sralph # endif
55517724Sralph 	switch( m ){
55617724Sralph 	default:
55717724Sralph 		nomat:
55817724Sralph 		cerror( "no table entry for op %s", opst[p->in.op] );
55917724Sralph 
56017724Sralph 	case COMOP:
56117724Sralph 		codgen( p1, FOREFF );
56217724Sralph 		p2->in.rall = p->in.rall;
56317724Sralph 		codgen( p2, cookie );
56417724Sralph 		ncopy( p, p2 );
56517724Sralph 		p2->in.op = FREE;
56617724Sralph 		goto cleanup;
56717724Sralph 
56817724Sralph 	case FORCE:
56917724Sralph 		/* recurse, letting the work be done by rallo */
57017724Sralph 		p = p->in.left;
57117724Sralph 		cook = INTAREG|INTBREG;
57217724Sralph 		goto again;
57317724Sralph 
57417724Sralph 	case CBRANCH:
57517724Sralph 		o = p2->tn.lval;
57617724Sralph 		cbranch( p1, -1, o );
57717724Sralph 		p2->in.op = FREE;
57817724Sralph 		p->in.op = FREE;
57917724Sralph 		return;
58017724Sralph 
58117724Sralph 	case QUEST:
58217724Sralph 		cbranch( p1, -1, m=getlab() );
58317724Sralph 		p2->in.left->in.rall = p->in.rall;
58417724Sralph 		codgen( p2->in.left, INTAREG|INTBREG );
58517724Sralph 		/* force right to compute result into same reg used by left */
58617724Sralph 		p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO;
58717724Sralph 		reclaim( p2->in.left, RNULL, 0 );
58817724Sralph 		cbgen( 0, m1 = getlab(), 'I' );
58917724Sralph 		deflab( m );
59017724Sralph 		codgen( p2->in.right, INTAREG|INTBREG );
59117724Sralph 		deflab( m1 );
59217724Sralph 		p->in.op = REG;  /* set up node describing result */
59317724Sralph 		p->tn.lval = 0;
59417724Sralph 		p->tn.rval = p2->in.right->tn.rval;
59517724Sralph 		p->in.type = p2->in.right->in.type;
59617724Sralph 		tfree( p2->in.right );
59717724Sralph 		p2->in.op = FREE;
59817724Sralph 		goto cleanup;
59917724Sralph 
60017724Sralph 	case ANDAND:
60117724Sralph 	case OROR:
60217724Sralph 	case NOT:  /* logical operators */
60317724Sralph 		/* if here, must be a logical operator for 0-1 value */
60417724Sralph 		cbranch( p, -1, m=getlab() );
60517724Sralph 		p->in.op = CCODES;
60617724Sralph 		p->bn.label = m;
60717724Sralph 		order( p, INTAREG );
60817724Sralph 		goto cleanup;
60917724Sralph 
61017724Sralph 	case FLD:	/* fields of funny type */
61117724Sralph 		if ( p1->in.op == UNARY MUL ){
61217747Sralph 			offstar( p1->in.left );
61317724Sralph 			goto again;
61417724Sralph 			}
61517724Sralph 
61617724Sralph 	case UNARY MINUS:
61729887Ssam 		order( p1, INBREG|INAREG|SOREG );
61817724Sralph 		goto again;
61917724Sralph 
62017724Sralph 	case NAME:
62117724Sralph 		/* all leaves end up here ... */
62217724Sralph 		if( o == REG ) goto nomat;
62317724Sralph 		order( p, INTAREG|INTBREG );
62417724Sralph 		goto again;
62517724Sralph 
62617724Sralph 	case INIT:
62717724Sralph 		uerror( "illegal initialization" );
62817724Sralph 		return;
62917724Sralph 
63017724Sralph 	case UNARY FORTCALL:
63117724Sralph 		p->in.right = NIL;
63217724Sralph 	case FORTCALL:
63317724Sralph 		o = p->in.op = UNARY FORTCALL;
63417724Sralph 		if( genfcall( p, cookie ) ) goto nomat;
63517724Sralph 		goto cleanup;
63617724Sralph 
63717724Sralph 	case UNARY CALL:
63817724Sralph 		p->in.right = NIL;
63917724Sralph 	case CALL:
64017724Sralph 		o = p->in.op = UNARY CALL;
64117724Sralph 		if( gencall( p, cookie ) ) goto nomat;
64217724Sralph 		goto cleanup;
64317724Sralph 
64417724Sralph 	case UNARY STCALL:
64517724Sralph 		p->in.right = NIL;
64617724Sralph 	case STCALL:
64717724Sralph 		o = p->in.op = UNARY STCALL;
64817724Sralph 		if( genscall( p, cookie ) ) goto nomat;
64917724Sralph 		goto cleanup;
65017724Sralph 
65117724Sralph 		/* if arguments are passed in register, care must be taken that reclaim
65217724Sralph 		/* not throw away the register which now has the result... */
65317724Sralph 
65417724Sralph 	case UNARY MUL:
65517724Sralph 		if( cook == FOREFF ){
65617724Sralph 			/* do nothing */
65717724Sralph 			order( p->in.left, FOREFF );
65817724Sralph 			p->in.op = FREE;
65917724Sralph 			return;
66017724Sralph 			}
66132827Sdonn #ifdef R2REGS
66232827Sdonn 		/* try to coax a tree into a doubly indexed OREG */
66332827Sdonn 		p1 = p->in.left;
66432827Sdonn 		if( p1->in.op == PLUS ) {
66532827Sdonn 			if( ISPTR(p1->in.left->in.type) &&
66632827Sdonn 			    offset(p1->in.right, tlen(p)) >= 0 ) {
66732827Sdonn 				order( p1->in.left, INAREG|INTAREG );
66832827Sdonn 				goto again;
66932827Sdonn 				}
67032827Sdonn 			if( ISPTR(p1->in.right->in.type) &&
67132827Sdonn 			    offset(p1->in.left, tlen(p)) >= 0 ) {
67232827Sdonn 				order( p1->in.right, INAREG|INTAREG );
67332827Sdonn 				goto again;
67432827Sdonn 				}
67532827Sdonn 			}
67632827Sdonn #endif
67717747Sralph 		offstar( p->in.left );
67817724Sralph 		goto again;
67917724Sralph 
68017724Sralph 	case INCR:  /* INCR and DECR */
68117747Sralph 		if( setincr(p) ) goto again;
68217724Sralph 
68317724Sralph 		/* x++ becomes (x += 1) -1; */
68417724Sralph 
68517724Sralph 		if( cook & FOREFF ){  /* result not needed so inc or dec and be done with it */
68617724Sralph 			/* x++ => x += 1 */
68717724Sralph 			p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
68817724Sralph 			goto again;
68917724Sralph 			}
69017724Sralph 
69117724Sralph 		p1 = tcopy(p);
69217724Sralph 		reclaim( p->in.left, RNULL, 0 );
69317724Sralph 		p->in.left = p1;
69417724Sralph 		p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
69517724Sralph 		p->in.op = (p->in.op==INCR)?MINUS:PLUS;
69617724Sralph 		goto again;
69717724Sralph 
69817724Sralph 	case STASG:
69917747Sralph 		if( setstr( p ) ) goto again;
70017724Sralph 		goto nomat;
70117724Sralph 
70217724Sralph 	case ASG PLUS:  /* and other assignment ops */
70317747Sralph 		if( setasop(p) ) goto again;
70417724Sralph 
70517724Sralph 		/* there are assumed to be no side effects in LHS */
70617724Sralph 
70717724Sralph 		p2 = tcopy(p);
70817724Sralph 		p->in.op = ASSIGN;
70917724Sralph 		reclaim( p->in.right, RNULL, 0 );
71017724Sralph 		p->in.right = p2;
71117724Sralph 		canon(p);
71217724Sralph 		rallo( p, p->in.rall );
71317724Sralph 
71417724Sralph # ifndef BUG4
71517724Sralph 		if( odebug ) fwalk( p, eprint, 0 );
71617724Sralph # endif
71717724Sralph 
71817724Sralph 		order( p2->in.left, INTBREG|INTAREG );
71917724Sralph 		order( p2, INTBREG|INTAREG );
72017724Sralph 		goto again;
72117724Sralph 
72217724Sralph 	case ASSIGN:
72317747Sralph 		if( setasg( p ) ) goto again;
72417724Sralph 		goto nomat;
72517724Sralph 
72617724Sralph 
72717724Sralph 	case BITYPE:
72817747Sralph 		if( setbin( p ) ) goto again;
72917724Sralph 		/* try to replace binary ops by =ops */
73017724Sralph 		switch(o){
73117724Sralph 
73217724Sralph 		case PLUS:
73317724Sralph 		case MINUS:
73417724Sralph 		case MUL:
73517724Sralph 		case DIV:
73617724Sralph 		case MOD:
73717724Sralph 		case AND:
73817724Sralph 		case OR:
73917724Sralph 		case ER:
74017724Sralph 		case LS:
74117724Sralph 		case RS:
74217724Sralph 			p->in.op = ASG o;
74317724Sralph 			goto again;
74417724Sralph 			}
74517724Sralph 		goto nomat;
74617724Sralph 
74717724Sralph 		}
74817724Sralph 
74917724Sralph 	cleanup:
75017724Sralph 
75117724Sralph 	/* if it is not yet in the right state, put it there */
75217724Sralph 
75317724Sralph 	if( cook & FOREFF ){
75417724Sralph 		reclaim( p, RNULL, 0 );
75517724Sralph 		return;
75617724Sralph 		}
75717724Sralph 
75817724Sralph 	if( p->in.op==FREE ) return;
75917724Sralph 
76017724Sralph 	if( tshape( p, cook ) ) return;
76117724Sralph 
76217724Sralph 	if( (m=match(p,cook) ) == MDONE ) return;
76317724Sralph 
76417724Sralph 	/* we are in bad shape, try one last chance */
76517724Sralph 	if( lastchance( p, cook ) ) goto again;
76617724Sralph 
76717724Sralph 	goto nomat;
76817724Sralph 	}
76917724Sralph 
77017724Sralph int callflag;
77117724Sralph int fregs;
77217724Sralph 
store(p)77317724Sralph store( p ) register NODE *p; {
77417724Sralph 
77517724Sralph 	/* find a subtree of p which should be stored */
77617724Sralph 
77717724Sralph 	register o, ty;
77817724Sralph 
77917724Sralph 	o = p->in.op;
78017724Sralph 	ty = optype(o);
78117724Sralph 
78217724Sralph 	if( ty == LTYPE ) return;
78317724Sralph 
78417724Sralph 	switch( o ){
78517724Sralph 
78617724Sralph 	case UNARY CALL:
78717724Sralph 	case UNARY FORTCALL:
78817724Sralph 	case UNARY STCALL:
78917724Sralph 		++callflag;
79017724Sralph 		break;
79117724Sralph 
79217724Sralph 	case UNARY MUL:
79317724Sralph 		if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL );
79417724Sralph 		break;
79517724Sralph 
79617724Sralph 	case CALL:
79717724Sralph 	case FORTCALL:
79817724Sralph 	case STCALL:
79917724Sralph 		store( p->in.left );
80017724Sralph 		stoarg( p->in.right, o );
80117724Sralph 		++callflag;
80217724Sralph 		return;
80317724Sralph 
80417724Sralph 	case COMOP:
80517724Sralph 		markcall( p->in.right );
80617724Sralph 		if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
80717724Sralph 		store( p->in.left );
80817724Sralph 		return;
80917724Sralph 
81017724Sralph 	case ANDAND:
81117724Sralph 	case OROR:
81217724Sralph 	case QUEST:
81317724Sralph 		markcall( p->in.right );
81417724Sralph 		if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
81517724Sralph 	case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
81617724Sralph 	case NOT:
81717724Sralph 		constore( p->in.left );
81817724Sralph 		return;
81917724Sralph 
82017724Sralph 		}
82117724Sralph 
82217724Sralph 	if( ty == UTYPE ){
82317724Sralph 		store( p->in.left );
82417724Sralph 		return;
82517724Sralph 		}
82617724Sralph 
82717724Sralph 	if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o );
82817724Sralph 
82917724Sralph 	if( p->in.su>fregs ){ /* must store */
83017724Sralph 		mkadrs( p );  /* set up stotree and stocook to subtree
83117724Sralph 				 that must be stored */
83217724Sralph 		}
83317724Sralph 
83417724Sralph 	store( p->in.right );
83517724Sralph 	store( p->in.left );
83617724Sralph 	}
83717724Sralph 
constore(p)83817724Sralph constore( p ) register NODE *p; {
83917724Sralph 
84017724Sralph 	/* store conditional expressions */
84117724Sralph 	/* the point is, avoid storing expressions in conditional
84217724Sralph 	   conditional context, since the evaluation order is predetermined */
84317724Sralph 
84417724Sralph 	switch( p->in.op ) {
84517724Sralph 
84617724Sralph 	case ANDAND:
84717724Sralph 	case OROR:
84817724Sralph 	case QUEST:
84917724Sralph 		markcall( p->in.right );
85017724Sralph 	case NOT:
85117724Sralph 		constore( p->in.left );
85217724Sralph 		return;
85317724Sralph 
85417724Sralph 		}
85517724Sralph 
85617724Sralph 	store( p );
85717724Sralph 	}
85817724Sralph 
markcall(p)85917724Sralph markcall( p ) register NODE *p; {  /* mark off calls below the current node */
86017724Sralph 
86117724Sralph 	again:
86217724Sralph 	switch( p->in.op ){
86317724Sralph 
86417724Sralph 	case UNARY CALL:
86517724Sralph 	case UNARY STCALL:
86617724Sralph 	case UNARY FORTCALL:
86717724Sralph 	case CALL:
86817724Sralph 	case STCALL:
86917724Sralph 	case FORTCALL:
87017724Sralph 		++callflag;
87117724Sralph 		return;
87217724Sralph 
87317724Sralph 		}
87417724Sralph 
87517724Sralph 	switch( optype( p->in.op ) ){
87617724Sralph 
87717724Sralph 	case BITYPE:
87817724Sralph 		markcall( p->in.right );
87917724Sralph 	case UTYPE:
88017724Sralph 		p = p->in.left;
88117724Sralph 		/* eliminate recursion (aren't I clever...) */
88217724Sralph 		goto again;
88317724Sralph 	case LTYPE:
88417724Sralph 		return;
88517724Sralph 		}
88617724Sralph 
88717724Sralph 	}
88817724Sralph 
stoarg(p,calltype)88917724Sralph stoarg( p, calltype ) register NODE *p; {
89017724Sralph 	/* arrange to store the args */
89117724Sralph 
89217724Sralph 	if( p->in.op == CM ){
89317724Sralph 		stoarg( p->in.left, calltype );
89417724Sralph 		p = p->in.right ;
89517724Sralph 		}
89617724Sralph 	if( calltype == CALL ){
89717724Sralph 		STOARG(p);
89817724Sralph 		}
89917724Sralph 	else if( calltype == STCALL ){
90017724Sralph 		STOSTARG(p);
90117724Sralph 		}
90217724Sralph 	else {
90317724Sralph 		STOFARG(p);
90417724Sralph 		}
90517724Sralph 	callflag = 0;
90617724Sralph 	store(p);
90717724Sralph # ifndef NESTCALLS
90817724Sralph 	if( callflag ){ /* prevent two calls from being active at once  */
90917724Sralph 		SETSTO(p,INTEMP);
91017724Sralph 		store(p); /* do again to preserve bottom up nature....  */
91117724Sralph 		}
91217724Sralph #endif
91317724Sralph 	}
91417724Sralph 
91517724Sralph int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */
91617724Sralph 
91717724Sralph cbranch( p, true, false ) NODE *p; {
91817724Sralph 	/* evaluate p for truth value, and branch to true or false
91917724Sralph 	/* accordingly: label <0 means fall through */
92017724Sralph 
92117724Sralph 	register o, lab, flab, tlab;
92217724Sralph 
92317724Sralph 	lab = -1;
92417724Sralph 
92517724Sralph 	switch( o=p->in.op ){
92617724Sralph 
92717724Sralph 	case ULE:
92817724Sralph 	case ULT:
92917724Sralph 	case UGE:
93017724Sralph 	case UGT:
93117724Sralph 	case EQ:
93217724Sralph 	case NE:
93317724Sralph 	case LE:
93417724Sralph 	case LT:
93517724Sralph 	case GE:
93617724Sralph 	case GT:
93717724Sralph 		if( true < 0 ){
93817724Sralph 			o = p->in.op = negrel[ o-EQ ];
93917724Sralph 			true = false;
94017724Sralph 			false = -1;
94117724Sralph 			}
94217724Sralph #ifndef NOOPT
94317724Sralph 		if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){
94417724Sralph 			switch( o ){
94517724Sralph 
94617724Sralph 			case UGT:
94717724Sralph 			case ULE:
94817724Sralph 				o = p->in.op = (o==UGT)?NE:EQ;
94917724Sralph 			case EQ:
95017724Sralph 			case NE:
95117724Sralph 			case LE:
95217724Sralph 			case LT:
95317724Sralph 			case GE:
95417724Sralph 			case GT:
95517724Sralph 				if( logop(p->in.left->in.op) ){
95617724Sralph 					/* strange situation: e.g., (a!=0) == 0 */
95717724Sralph 					/* must prevent reference to p->in.left->lable, so get 0/1 */
95817724Sralph 					/* we could optimize, but why bother */
95917724Sralph 					codgen( p->in.left, INAREG|INBREG );
96017724Sralph 					}
96117724Sralph 				codgen( p->in.left, FORCC );
96217724Sralph 				cbgen( o, true, 'I' );
96317724Sralph 				break;
96417724Sralph 
96517724Sralph 			case UGE:
96617724Sralph 				codgen(p->in.left, FORCC);
96717724Sralph 				cbgen( 0, true, 'I' );  /* unconditional branch */
96817724Sralph 				break;
96917724Sralph 			case ULT:
97017724Sralph 				codgen(p->in.left, FORCC);
97117724Sralph 				}
97217724Sralph 			}
97317724Sralph 		else
97417724Sralph #endif
97517724Sralph 			{
97617724Sralph 			p->bn.label = true;
97717724Sralph 			codgen( p, FORCC );
97817724Sralph 			}
97917724Sralph 		if( false>=0 ) cbgen( 0, false, 'I' );
98017724Sralph 		reclaim( p, RNULL, 0 );
98117724Sralph 		return;
98217724Sralph 
98317724Sralph 	case ANDAND:
98417724Sralph 		lab = false<0 ? getlab() : false ;
98517724Sralph 		cbranch( p->in.left, -1, lab );
98617724Sralph 		cbranch( p->in.right, true, false );
98717724Sralph 		if( false < 0 ) deflab( lab );
98817724Sralph 		p->in.op = FREE;
98917724Sralph 		return;
99017724Sralph 
99117724Sralph 	case OROR:
99217724Sralph 		lab = true<0 ? getlab() : true;
99317724Sralph 		cbranch( p->in.left, lab, -1 );
99417724Sralph 		cbranch( p->in.right, true, false );
99517724Sralph 		if( true < 0 ) deflab( lab );
99617724Sralph 		p->in.op = FREE;
99717724Sralph 		return;
99817724Sralph 
99917724Sralph 	case NOT:
100017724Sralph 		cbranch( p->in.left, false, true );
100117724Sralph 		p->in.op = FREE;
100217724Sralph 		break;
100317724Sralph 
100417724Sralph 	case COMOP:
100517724Sralph 		codgen( p->in.left, FOREFF );
100617724Sralph 		p->in.op = FREE;
100717724Sralph 		cbranch( p->in.right, true, false );
100817724Sralph 		return;
100917724Sralph 
101017724Sralph 	case QUEST:
101117724Sralph 		flab = false<0 ? getlab() : false;
101217724Sralph 		tlab = true<0 ? getlab() : true;
101317724Sralph 		cbranch( p->in.left, -1, lab = getlab() );
101417724Sralph 		cbranch( p->in.right->in.left, tlab, flab );
101517724Sralph 		deflab( lab );
101617724Sralph 		cbranch( p->in.right->in.right, true, false );
101717724Sralph 		if( true < 0 ) deflab( tlab);
101817724Sralph 		if( false < 0 ) deflab( flab );
101917724Sralph 		p->in.right->in.op = FREE;
102017724Sralph 		p->in.op = FREE;
102117724Sralph 		return;
102217724Sralph 
102317724Sralph 	case ICON:
102417724Sralph 		if( p->in.type != FLOAT && p->in.type != DOUBLE ){
102517724Sralph 
102617724Sralph 			if( p->tn.lval || p->in.name[0] ){
102717724Sralph 				/* addresses of C objects are never 0 */
102817724Sralph 				if( true>=0 ) cbgen( 0, true, 'I' );
102917724Sralph 				}
103017724Sralph 			else if( false>=0 ) cbgen( 0, false, 'I' );
103117724Sralph 			p->in.op = FREE;
103217724Sralph 			return;
103317724Sralph 			}
103417724Sralph 		/* fall through to default with other strange constants */
103517724Sralph 
103617724Sralph 	default:
103717724Sralph 		/* get condition codes */
103817724Sralph 		codgen( p, FORCC );
103917724Sralph 		if( true >= 0 ) cbgen( NE, true, 'I' );
104017724Sralph 		if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
104117724Sralph 		reclaim( p, RNULL, 0 );
104217724Sralph 		return;
104317724Sralph 
104417724Sralph 		}
104517724Sralph 
104617724Sralph 	}
104717724Sralph 
rcount()104817724Sralph rcount(){ /* count recursions */
104917724Sralph 	if( ++nrecur > NRECUR ){
105017724Sralph 		cerror( "expression causes compiler loop: try simplifying" );
105117724Sralph 		}
105217724Sralph 
105317724Sralph 	}
105417724Sralph 
105517724Sralph # ifndef BUG4
eprint(p,down,a,b)105617724Sralph eprint( p, down, a, b ) NODE *p; int *a, *b; {
105717724Sralph 
105817724Sralph 	*a = *b = down+1;
105917724Sralph 	while( down >= 2 ){
106017724Sralph 		printf( "\t" );
106117724Sralph 		down -= 2;
106217724Sralph 		}
106317724Sralph 	if( down-- ) printf( "    " );
106417724Sralph 
106517724Sralph 
106617724Sralph 	printf( "%o) %s", p, opst[p->in.op] );
106717724Sralph 	switch( p->in.op ) { /* special cases */
106817724Sralph 
106917724Sralph 	case REG:
107017724Sralph 		printf( " %s", rnames[p->tn.rval] );
107117724Sralph 		break;
107217724Sralph 
107317724Sralph 	case ICON:
107417724Sralph 	case NAME:
107517724Sralph 	case OREG:
107617724Sralph 		printf( " " );
107717724Sralph 		adrput( p );
107817724Sralph 		break;
107917724Sralph 
108017724Sralph 	case STCALL:
108117724Sralph 	case UNARY STCALL:
108217724Sralph 	case STARG:
108317724Sralph 	case STASG:
108417724Sralph 		printf( " size=%d", p->stn.stsize );
108517724Sralph 		printf( " align=%d", p->stn.stalign );
108617724Sralph 		break;
108717724Sralph 		}
108817724Sralph 
108917724Sralph 	printf( ", " );
109017724Sralph 	tprint( p->in.type );
109117724Sralph 	printf( ", " );
109217724Sralph 	if( p->in.rall == NOPREF ) printf( "NOPREF" );
109317724Sralph 	else {
109417724Sralph 		if( p->in.rall & MUSTDO ) printf( "MUSTDO " );
109517724Sralph 		else printf( "PREF " );
109617724Sralph 		printf( "%s", rnames[p->in.rall&~MUSTDO]);
109717724Sralph 		}
109817724Sralph 	printf( ", SU= %d\n", p->in.su );
109917724Sralph 
110017724Sralph 	}
110117724Sralph # endif
110217724Sralph 
110317724Sralph # ifndef NOMAIN
110417724Sralph NODE *
eread()110517724Sralph eread(){
110617724Sralph 
110717724Sralph 	/* call eread recursively to get subtrees, if any */
110817724Sralph 
110917724Sralph 	register NODE *p;
111017724Sralph 	register i, c;
111117724Sralph 	register char *pc;
111217724Sralph 	register j;
111317724Sralph 
111417724Sralph 	i = rdin( 10 );
111517724Sralph 
111617724Sralph 	p = talloc();
111717724Sralph 
111817724Sralph 	p->in.op = i;
111917724Sralph 
112017724Sralph 	i = optype(i);
112117724Sralph 
112217724Sralph 	if( i == LTYPE ) p->tn.lval = rdin( 10 );
112317724Sralph 	if( i != BITYPE ) p->tn.rval = rdin( 10 );
112417724Sralph 
112517724Sralph 	p->in.type = rdin(8 );
112617724Sralph 	p->in.rall = NOPREF;  /* register allocation information */
112717724Sralph 
112817724Sralph 	if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){
112917724Sralph 		p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
113017724Sralph 		p->stn.stalign = rdin(10) / SZCHAR;
113117724Sralph 		if( getchar() != '\n' ) cerror( "illegal \n" );
113217724Sralph 		}
113317724Sralph 	else {   /* usual case */
113417724Sralph 		if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type );  /* non usually, but sometimes justified */
113517724Sralph #ifndef FLEXNAMES
113617724Sralph 		for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){
113717724Sralph 			if( j < NCHNAM ) *pc++ = c;
113817724Sralph 			}
113917724Sralph 		if( j < NCHNAM ) *pc = '\0';
114017724Sralph #else
114117724Sralph 		{ char buf[BUFSIZ];
114217724Sralph 		for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){
114317724Sralph 			if( j < BUFSIZ ) *pc++ = c;
114417724Sralph 			}
114517724Sralph 		if( j < BUFSIZ ) *pc = '\0';
114617724Sralph 		p->in.name = tstr(buf);
114717724Sralph 		}
114817724Sralph #endif
114917724Sralph 		}
115017724Sralph 
115117724Sralph 	/* now, recursively read descendents, if any */
115217724Sralph 
115317724Sralph 	if( i != LTYPE ) p->in.left = eread();
115417724Sralph 	if( i == BITYPE ) p->in.right = eread();
115517724Sralph 
115617724Sralph 	return( p );
115717724Sralph 
115817724Sralph 	}
115917724Sralph 
116017724Sralph CONSZ
rdin(base)116117724Sralph rdin( base ){
116217724Sralph 	register sign, c;
116317724Sralph 	CONSZ val;
116417724Sralph 
116517724Sralph 	sign = 1;
116617724Sralph 	val = 0;
116717724Sralph 
116817724Sralph 	while( (c=getchar()) > 0 ) {
116917724Sralph 		if( c == '-' ){
117017724Sralph 			if( val != 0 ) cerror( "illegal -");
117117724Sralph 			sign = -sign;
117217724Sralph 			continue;
117317724Sralph 			}
117417724Sralph 		if( c == '\t' ) break;
117517724Sralph 		if( c>='0' && c<='9' ) {
117617724Sralph 			val *= base;
117717724Sralph 			if( sign > 0 )
117817724Sralph 				val += c-'0';
117917724Sralph 			else
118017724Sralph 				val -= c-'0';
118117724Sralph 			continue;
118217724Sralph 			}
118317724Sralph 		cerror( "illegal character `%c' on intermediate file", c );
118417724Sralph 		break;
118517724Sralph 		}
118617724Sralph 
118717724Sralph 	if( c <= 0 ) {
118817724Sralph 		cerror( "unexpected EOF");
118917724Sralph 		}
119017724Sralph 	return( val );
119117724Sralph 	}
119217724Sralph # endif
119317724Sralph 
119417724Sralph #ifndef FIELDOPS
119517724Sralph 	/* do this if there is no special hardware support for fields */
119617724Sralph 
ffld(p,down,down1,down2)119717724Sralph ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
119817724Sralph 	 /* look for fields that are not in an lvalue context, and rewrite them... */
119917724Sralph 	register NODE *shp;
120017724Sralph 	register s, o, v, ty;
120117724Sralph 
120217724Sralph 	*down1 =  asgop( p->in.op );
120317724Sralph 	*down2 = 0;
120417724Sralph 
120517724Sralph 	if( !down && p->in.op == FLD ){ /* rewrite the node */
120617724Sralph 
120717724Sralph 		if( !rewfld(p) ) return;
120817724Sralph 
120917724Sralph 		ty = (szty(p->in.type) == 2)? LONG: INT;
121017724Sralph 		v = p->tn.rval;
121117724Sralph 		s = UPKFSZ(v);
121217724Sralph # ifdef RTOLBYTES
121317724Sralph 		o = UPKFOFF(v);  /* amount to shift */
121417724Sralph # else
121517724Sralph 		o = szty(p->in.type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
121617724Sralph #endif
121717724Sralph 
121817724Sralph 		/* make & mask part */
121917724Sralph 
122017724Sralph 		p->in.left->in.type = ty;
122117724Sralph 
122217724Sralph 		p->in.op = AND;
122317724Sralph 		p->in.right = talloc();
122417724Sralph 		p->in.right->in.op = ICON;
122517724Sralph 		p->in.right->in.rall = NOPREF;
122617724Sralph 		p->in.right->in.type = ty;
122717724Sralph 		p->in.right->tn.lval = 1;
122817724Sralph 		p->in.right->tn.rval = 0;
122917724Sralph #ifndef FLEXNAMES
123017724Sralph 		p->in.right->in.name[0] = '\0';
123117724Sralph #else
123217724Sralph 		p->in.right->in.name = "";
123317724Sralph #endif
123417724Sralph 		p->in.right->tn.lval <<= s;
123517724Sralph 		p->in.right->tn.lval--;
123617724Sralph 
123717724Sralph 		/* now, if a shift is needed, do it */
123817724Sralph 
123917724Sralph 		if( o != 0 ){
124017724Sralph 			shp = talloc();
124117724Sralph 			shp->in.op = RS;
124217724Sralph 			shp->in.rall = NOPREF;
124317724Sralph 			shp->in.type = ty;
124417724Sralph 			shp->in.left = p->in.left;
124517724Sralph 			shp->in.right = talloc();
124617724Sralph 			shp->in.right->in.op = ICON;
124717724Sralph 			shp->in.right->in.rall = NOPREF;
124817724Sralph 			shp->in.right->in.type = ty;
124917724Sralph 			shp->in.right->tn.rval = 0;
125017724Sralph 			shp->in.right->tn.lval = o;  /* amount to shift */
125117724Sralph #ifndef FLEXNAMES
125217724Sralph 			shp->in.right->in.name[0] = '\0';
125317724Sralph #else
125417724Sralph 			shp->in.right->in.name = "";
125517724Sralph #endif
125617724Sralph 			p->in.left = shp;
125717724Sralph 			/* whew! */
125817724Sralph 			}
125917724Sralph 		}
126017724Sralph 	}
126117724Sralph #endif
126217724Sralph 
oreg2(p)126317724Sralph oreg2( p ) register NODE *p; {
126417724Sralph 
126517724Sralph 	/* look for situations where we can turn * into OREG */
126617724Sralph 
126717724Sralph 	NODE *q;
126817724Sralph 	register i;
126917724Sralph 	register r;
127017724Sralph 	register char *cp;
127117724Sralph 	register NODE *ql, *qr;
127217724Sralph 	CONSZ temp;
127317724Sralph 
127417724Sralph 	if( p->in.op == UNARY MUL ){
127517724Sralph 		q = p->in.left;
127617724Sralph 		if( q->in.op == REG ){
127717724Sralph 			temp = q->tn.lval;
127817724Sralph 			r = q->tn.rval;
127917724Sralph 			cp = q->in.name;
128017724Sralph 			goto ormake;
128117724Sralph 			}
128217724Sralph 
128317724Sralph 		if( q->in.op != PLUS && q->in.op != MINUS ) return;
128417724Sralph 		ql = q->in.left;
128517724Sralph 		qr = q->in.right;
128617724Sralph 
128717724Sralph #ifdef R2REGS
128817724Sralph 
128917724Sralph 		/* look for doubly indexed expressions */
129017724Sralph 
129117724Sralph 		if( q->in.op == PLUS) {
129217724Sralph 			if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
129317724Sralph 				makeor2(p, ql, r, i);
129417724Sralph 				return;
129517724Sralph 			} else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
129617724Sralph 				makeor2(p, qr, r, i);
129717724Sralph 				return;
129817724Sralph 				}
129917724Sralph 			}
130017724Sralph 
130117724Sralph 
130217724Sralph #endif
130317724Sralph 
130417724Sralph 		if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
130517724Sralph 				ql->in.op==REG && szty(qr->in.type)==1) {
130617724Sralph 			temp = qr->tn.lval;
130717724Sralph 			if( q->in.op == MINUS ) temp = -temp;
130817724Sralph 			r = ql->tn.rval;
130917724Sralph 			temp += ql->tn.lval;
131017724Sralph 			cp = qr->in.name;
131117724Sralph 			if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return;
131217724Sralph 			if( !*cp ) cp = ql->in.name;
131317724Sralph 
131417724Sralph 			ormake:
131517724Sralph 			if( notoff( p->in.type, r, temp, cp ) ) return;
131617724Sralph 			p->in.op = OREG;
131717724Sralph 			p->tn.rval = r;
131817724Sralph 			p->tn.lval = temp;
131917724Sralph #ifndef FLEXNAMES
132017724Sralph 			for( i=0; i<NCHNAM; ++i )
132117724Sralph 				p->in.name[i] = *cp++;
132217724Sralph #else
132317724Sralph 			p->in.name = cp;
132417724Sralph #endif
132517724Sralph 			tfree(q);
132617724Sralph 			return;
132717724Sralph 			}
132817724Sralph 		}
132917724Sralph 
133017724Sralph 	}
133117724Sralph 
canon(p)133217724Sralph canon(p) NODE *p; {
133317724Sralph 	/* put p in canonical form */
133417724Sralph 	int oreg2(), sucomp();
133517724Sralph 
133617724Sralph #ifndef FIELDOPS
133717724Sralph 	int ffld();
133817724Sralph 	fwalk( p, ffld, 0 ); /* look for field operators */
133917724Sralph # endif
134017724Sralph 	walkf( p, oreg2 );  /* look for and create OREG nodes */
134117724Sralph #ifdef MYCANON
134217724Sralph 	MYCANON(p);  /* your own canonicalization routine(s) */
134317724Sralph #endif
134417724Sralph 	walkf( p, sucomp );  /* do the Sethi-Ullman computation */
134517724Sralph 
134617724Sralph 	}
134717724Sralph 
1348