xref: /csrg-svn/old/pcc/ccom.vax/local.c (revision 34250)
117738Sralph #ifndef lint
2*34250Sdonn static char *sccsid ="@(#)local.c	1.17 (Berkeley) 05/11/88";
317738Sralph #endif lint
417738Sralph 
518555Sralph # include "pass1.h"
69701Slinton 
79701Slinton /*	this file contains code which is dependent on the target machine */
89701Slinton 
99701Slinton NODE *
clocal(p)1032916Sdonn clocal(p) register NODE *p; {
119701Slinton 
129701Slinton 	/* this is called to do local transformations on
139701Slinton 	   an expression tree preparitory to its being
149701Slinton 	   written out in intermediate code.
159701Slinton 	*/
169701Slinton 
179701Slinton 	/* the major essential job is rewriting the
189701Slinton 	   automatic variables and arguments in terms of
199701Slinton 	   REG and OREG nodes */
209701Slinton 	/* conversion ops which are not necessary are also clobbered here */
219701Slinton 	/* in addition, any special features (such as rewriting
229701Slinton 	   exclusive or) are easily handled here as well */
239701Slinton 
249701Slinton 	register struct symtab *q;
259701Slinton 	register NODE *r;
2632916Sdonn 	register int o;
2732916Sdonn 	register int m, ml;
289701Slinton 
299701Slinton 	switch( o = p->in.op ){
309701Slinton 
319701Slinton 	case NAME:
329701Slinton 		if( p->tn.rval < 0 ) { /* already processed; ignore... */
339701Slinton 			return(p);
349701Slinton 			}
359701Slinton 		q = &stab[p->tn.rval];
369701Slinton 		switch( q->sclass ){
379701Slinton 
389701Slinton 		case AUTO:
399701Slinton 		case PARAM:
409701Slinton 			/* fake up a structure reference */
419701Slinton 			r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
429701Slinton 			r->tn.lval = 0;
439701Slinton 			r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG);
449701Slinton 			p = stref( block( STREF, r, p, 0, 0, 0 ) );
459701Slinton 			break;
469701Slinton 
479701Slinton 		case ULABEL:
489701Slinton 		case LABEL:
499701Slinton 		case STATIC:
509701Slinton 			if( q->slevel == 0 ) break;
519701Slinton 			p->tn.lval = 0;
529701Slinton 			p->tn.rval = -q->offset;
539701Slinton 			break;
549701Slinton 
559701Slinton 		case REGISTER:
569701Slinton 			p->in.op = REG;
579701Slinton 			p->tn.lval = 0;
589701Slinton 			p->tn.rval = q->offset;
599701Slinton 			break;
609701Slinton 
619701Slinton 			}
629701Slinton 		break;
639701Slinton 
6432916Sdonn 	case LT:
6532916Sdonn 	case LE:
6632916Sdonn 	case GT:
6732916Sdonn 	case GE:
6832916Sdonn 		if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){
6932916Sdonn 			p->in.op += (ULT-LT);
7032916Sdonn 			}
7132916Sdonn 		break;
7232916Sdonn 
739701Slinton 	case PCONV:
749701Slinton 		/* do pointer conversions for char and longs */
759701Slinton 		ml = p->in.left->in.type;
769701Slinton 		if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
779701Slinton 
789701Slinton 		/* pointers all have the same representation; the type is inherited */
799701Slinton 
809701Slinton 		p->in.left->in.type = p->in.type;
819701Slinton 		p->in.left->fn.cdim = p->fn.cdim;
829701Slinton 		p->in.left->fn.csiz = p->fn.csiz;
839701Slinton 		p->in.op = FREE;
849701Slinton 		return( p->in.left );
859701Slinton 
869701Slinton 	case SCONV:
8732916Sdonn 		m = p->in.type;
8832916Sdonn 		ml = p->in.left->in.type;
8932916Sdonn 		if(m == ml)
9032916Sdonn 			goto clobber;
9117738Sralph 		o = p->in.left->in.op;
9232916Sdonn 		if(m == FLOAT || m == DOUBLE) {
9332916Sdonn 			if(o==SCONV &&
9432916Sdonn 			 ml == DOUBLE &&
9532916Sdonn 			 p->in.left->in.left->in.type==m) {
9632916Sdonn 				p->in.op = p->in.left->in.op = FREE;
9732916Sdonn 				return(p->in.left->in.left);
9832916Sdonn 				}
9932916Sdonn 			/* see makety() for constant conversions */
10032916Sdonn 			break;
10132916Sdonn 			}
10232916Sdonn 		if(ml == FLOAT || ml == DOUBLE){
10332916Sdonn 			if(o != FCON && o != DCON)
10432916Sdonn 				break;
10532916Sdonn 			ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */
10632916Sdonn 			r = block( ICON, (NODE *)NULL, (NODE *)NULL, ml, 0, 0 );
10717738Sralph 			if( o == FCON )
10832916Sdonn 				r->tn.lval = ml == INT ?
10932916Sdonn 					(int) p->in.left->fpn.fval :
11032916Sdonn 					(unsigned) p->in.left->fpn.fval;
11117738Sralph 			else
11232916Sdonn 				r->tn.lval = ml == INT ?
11332916Sdonn 					(int) p->in.left->dpn.dval :
11432916Sdonn 					(unsigned) p->in.left->dpn.dval;
11517738Sralph 			r->tn.rval = NONAME;
11617738Sralph 			p->in.left->in.op = FREE;
11717738Sralph 			p->in.left = r;
11832916Sdonn 			o = ICON;
11932916Sdonn 			if( m == ml )
12032916Sdonn 				goto clobber;
12117738Sralph 			}
1229701Slinton 		/* now, look for conversions downwards */
1239701Slinton 
12432916Sdonn 		if( o == ICON ){ /* simulate the conversion here */
1259701Slinton 			CONSZ val;
1269701Slinton 			val = p->in.left->tn.lval;
1279701Slinton 			switch( m ){
1289701Slinton 			case CHAR:
1299701Slinton 				p->in.left->tn.lval = (char) val;
1309701Slinton 				break;
1319701Slinton 			case UCHAR:
1329701Slinton 				p->in.left->tn.lval = val & 0XFF;
1339701Slinton 				break;
1349701Slinton 			case USHORT:
1359701Slinton 				p->in.left->tn.lval = val & 0XFFFFL;
1369701Slinton 				break;
1379701Slinton 			case SHORT:
1389701Slinton 				p->in.left->tn.lval = (short)val;
1399701Slinton 				break;
1409701Slinton 			case UNSIGNED:
1419701Slinton 				p->in.left->tn.lval = val & 0xFFFFFFFFL;
1429701Slinton 				break;
1439701Slinton 			case INT:
1449701Slinton 				p->in.left->tn.lval = (int)val;
1459701Slinton 				break;
1469701Slinton 				}
1479701Slinton 			p->in.left->in.type = m;
1489701Slinton 			}
14932916Sdonn 		else
15016181Sralph 			break;
1519701Slinton 
15232916Sdonn 	clobber:
1539701Slinton 		p->in.op = FREE;
1549701Slinton 		return( p->in.left );  /* conversion gets clobbered */
1559701Slinton 
1569701Slinton 	case PVCONV:
1579701Slinton 	case PMCONV:
1589701Slinton 		if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
1599701Slinton 		p->in.op = FREE;
1609701Slinton 		return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
1619701Slinton 
1629701Slinton 	case RS:
1639701Slinton 	case ASG RS:
1649701Slinton 		/* convert >> to << with negative shift count */
1659701Slinton 		/* only if type of left operand is not unsigned */
1669701Slinton 
1679701Slinton 		if( ISUNSIGNED(p->in.left->in.type) ) break;
16817738Sralph 		if( p->in.right->in.op != UNARY MINUS )
16917738Sralph 			p->in.right = buildtree( UNARY MINUS, p->in.right, NIL );
17017738Sralph 		else {
17117738Sralph 			r = p->in.right;
17217738Sralph 			p->in.right = p->in.right->in.left;
17317738Sralph 			r->in.op = FREE;
17417738Sralph 		}
1759701Slinton 		if( p->in.op == RS ) p->in.op = LS;
1769701Slinton 		else p->in.op = ASG LS;
1779701Slinton 		break;
1789701Slinton 
1799701Slinton 	case FLD:
1809701Slinton 		/* make sure that the second pass does not make the
1819701Slinton 		   descendant of a FLD operator into a doubly indexed OREG */
1829701Slinton 
1839701Slinton 		if( p->in.left->in.op == UNARY MUL
1849701Slinton 				&& (r=p->in.left->in.left)->in.op == PCONV)
1859701Slinton 			if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
1869701Slinton 				if( ISPTR(r->in.type) ) {
1879701Slinton 					if( ISUNSIGNED(p->in.left->in.type) )
188*34250Sdonn 						p->in.left->in.type = UCHAR;
1899701Slinton 					else
190*34250Sdonn 						p->in.left->in.type = CHAR;
1919701Slinton 				}
1929701Slinton 		break;
1939701Slinton 		}
1949701Slinton 
1959701Slinton 	return(p);
1969701Slinton 	}
1979701Slinton 
19832915Sdonn /*ARGSUSED*/
andable(p)1999701Slinton andable( p ) NODE *p; {
2009701Slinton 	return(1);  /* all names can have & taken on them */
2019701Slinton 	}
2029701Slinton 
cendarg()2039701Slinton cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
2049701Slinton 	autooff = AUTOINIT;
2059701Slinton 	}
2069701Slinton 
cisreg(t)2079701Slinton cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
2089701Slinton 
2099701Slinton #ifdef TRUST_REG_CHAR_AND_REG_SHORT
2109701Slinton 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* tbl */
2119701Slinton 		|| t==CHAR || t==UCHAR || t==SHORT 		/* tbl */
2129701Slinton 		|| t==USHORT || ISPTR(t)) return(1);		/* tbl */
2139701Slinton #else
2149701Slinton 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* wnj */
21517738Sralph #ifdef SPRECC
21617738Sralph 		|| t==FLOAT
21717738Sralph #endif
2189701Slinton 		|| ISPTR(t)) return (1);			/* wnj */
2199701Slinton #endif
2209701Slinton 	return(0);
2219701Slinton 	}
2229701Slinton 
22332915Sdonn /*ARGSUSED*/
2249701Slinton NODE *
offcon(off,t,d,s)2259701Slinton offcon( off, t, d, s ) OFFSZ off; TWORD t; {
2269701Slinton 
2279701Slinton 	/* return a node, for structure references, which is suitable for
2289701Slinton 	   being added to a pointer of type t, in order to be off bits offset
2299701Slinton 	   into a structure */
2309701Slinton 
2319701Slinton 	register NODE *p;
2329701Slinton 
2339701Slinton 	/* t, d, and s are the type, dimension offset, and sizeoffset */
23432915Sdonn 	/* in general they  are necessary for offcon, but not on VAX */
2359701Slinton 
2369701Slinton 	p = bcon(0);
2379701Slinton 	p->tn.lval = off/SZCHAR;
2389701Slinton 	return(p);
2399701Slinton 
2409701Slinton 	}
2419701Slinton 
2429701Slinton 
2439701Slinton static inwd	/* current bit offsed in word */;
24432916Sdonn static CONSZ word	/* word being built from fields */;
2459701Slinton 
incode(p,sz)2469701Slinton incode( p, sz ) register NODE *p; {
2479701Slinton 
2489701Slinton 	/* generate initialization code for assigning a constant c
2499701Slinton 		to a field of width sz */
2509701Slinton 	/* we assume that the proper alignment has been obtained */
2519701Slinton 	/* inoff is updated to have the proper final value */
2529701Slinton 	/* we also assume sz  < SZINT */
2539701Slinton 
254*34250Sdonn 	inoff += sz;
25532916Sdonn 	if(nerrors) return;
2569701Slinton 	if((sz+inwd) > SZINT) cerror("incode: field > int");
2579701Slinton 	word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
2589701Slinton 	inwd += sz;
2599701Slinton 	if(inoff%SZINT == 0) {
26032916Sdonn 		printf( "	.long	0x%lx\n", word);
2619701Slinton 		word = inwd = 0;
2629701Slinton 		}
2639701Slinton 	}
2649701Slinton 
fincode(d,sz)2659701Slinton fincode( d, sz ) double d; {
2669701Slinton 	/* output code to initialize space of size sz to the value d */
2679701Slinton 	/* the proper alignment has been obtained */
2689701Slinton 	/* inoff is updated to have the proper final value */
2699701Slinton 	/* on the target machine, write it out in octal! */
2709701Slinton 
2719701Slinton 
272*34250Sdonn 	if(!nerrors)
2739701Slinton 	printf("	%s	0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
2749701Slinton 		sz == SZDOUBLE ? 'd' : 'f', d);
2759701Slinton 	inoff += sz;
2769701Slinton 	}
2779701Slinton 
cinit(p,sz)2789701Slinton cinit( p, sz ) NODE *p; {
27918437Smckusick 	NODE *l;
28018437Smckusick 
28118437Smckusick 	/*
28218437Smckusick 	 * as a favor (?) to people who want to write
28318437Smckusick 	 *     int i = 9600/134.5;
28418437Smckusick 	 * we will, under the proper circumstances, do
28532916Sdonn 	 * a coercion here.
28618437Smckusick 	 */
28718437Smckusick 	switch (p->in.type) {
28818437Smckusick 	case INT:
28918437Smckusick 	case UNSIGNED:
29018437Smckusick 		l = p->in.left;
29118555Sralph 		if (l->in.op != SCONV ||
29218555Sralph 		    (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
29318555Sralph 			break;
29418437Smckusick 		l->in.op = FREE;
29518437Smckusick 		l = l->in.left;
29618555Sralph 		l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
29718555Sralph 			(long)(l->fpn.fval);
29818437Smckusick 		l->tn.rval = NONAME;
29918437Smckusick 		l->tn.op = ICON;
30018437Smckusick 		l->tn.type = INT;
30118437Smckusick 		p->in.left = l;
30218437Smckusick 		break;
30318437Smckusick 	}
30418437Smckusick 	/* arrange for the initialization of p into a space of size sz */
3059701Slinton 	/* the proper alignment has been opbtained */
3069701Slinton 	/* inoff is updated to have the proper final value */
3079701Slinton 	ecode( p );
3089701Slinton 	inoff += sz;
3099701Slinton 	}
3109701Slinton 
vfdzero(n)3119701Slinton vfdzero( n ){ /* define n bits of zeros in a vfd */
3129701Slinton 
3139701Slinton 	if( n <= 0 ) return;
3149701Slinton 
315*34250Sdonn 	inoff += n;
31632914Sdonn 	if (nerrors) return;
3179701Slinton 	inwd += n;
3189701Slinton 	if( inoff%ALINT ==0 ) {
31932916Sdonn 		printf( "	.long	0x%lx\n", word );
3209701Slinton 		word = inwd = 0;
3219701Slinton 		}
3229701Slinton 	}
3239701Slinton 
3249701Slinton char *
exname(p)3259701Slinton exname( p ) char *p; {
3269701Slinton 	/* make a name look like an external name in the local machine */
3279701Slinton 
3289701Slinton #ifndef FLEXNAMES
3299701Slinton 	static char text[NCHNAM+1];
3309701Slinton #else
3319701Slinton 	static char text[BUFSIZ+1];
3329701Slinton #endif
3339701Slinton 
33432916Sdonn 	register int i;
3359701Slinton 
3369701Slinton 	text[0] = '_';
3379701Slinton #ifndef FLEXNAMES
33824417Smckusick 	for( i=1; *p&&i<NCHNAM; ++i )
3399701Slinton #else
34024417Smckusick 	for( i=1; *p; ++i )
3419701Slinton #endif
3429701Slinton 		text[i] = *p++;
3439701Slinton 
3449701Slinton 	text[i] = '\0';
3459701Slinton #ifndef FLEXNAMES
3469701Slinton 	text[NCHNAM] = '\0';  /* truncate */
3479701Slinton #endif
3489701Slinton 
3499701Slinton 	return( text );
3509701Slinton 	}
3519701Slinton 
ctype(type)35217738Sralph ctype( type ) TWORD type;
35317738Sralph 	{ /* map types which are not defined on the local machine */
3549701Slinton 	switch( BTYPE(type) ){
3559701Slinton 
3569701Slinton 	case LONG:
3579701Slinton 		MODTYPE(type,INT);
3589701Slinton 		break;
3599701Slinton 
3609701Slinton 	case ULONG:
3619701Slinton 		MODTYPE(type,UNSIGNED);
3629701Slinton 		}
3639701Slinton 	return( type );
3649701Slinton 	}
3659701Slinton 
noinit()36617738Sralph noinit() { /* curid is a variable which is defined but
3679701Slinton 	is not initialized (and not a function );
3689701Slinton 	This routine returns the stroage class for an uninitialized declaration */
3699701Slinton 
3709701Slinton 	return(EXTERN);
3719701Slinton 
3729701Slinton 	}
3739701Slinton 
commdec(id)3749701Slinton commdec( id ){ /* make a common declaration for id, if reasonable */
3759701Slinton 	register struct symtab *q;
3769701Slinton 	OFFSZ off, tsize();
3779701Slinton 
37832914Sdonn 	if (nerrors) return;
3799701Slinton 	q = &stab[id];
3809701Slinton 	printf( "	.comm	%s,", exname( q->sname ) );
3819701Slinton 	off = tsize( q->stype, q->dimoff, q->sizoff );
3829701Slinton 	printf( CONFMT, off/SZCHAR );
38332916Sdonn 	putchar( '\n' );
3849701Slinton 	}
3859701Slinton 
prtdcon(p)38632916Sdonn prtdcon(p)
38732916Sdonn 	register NODE *p;
38832916Sdonn {
38932916Sdonn 	register int o = p->in.op;
39032916Sdonn 	int i;
3919701Slinton 
39232916Sdonn 	if (o != DCON && o != FCON)
39332916Sdonn 		return;
39432916Sdonn 	/*
39532916Sdonn 	 * Clobber constants of value zero so
39632916Sdonn 	 * we can generate more efficient code.
39732916Sdonn 	 */
39832916Sdonn 	if ((o == DCON && p->dpn.dval == 0) ||
39932916Sdonn 	    (o == FCON && p->fpn.fval == 0)) {
40032916Sdonn 		p->in.op = ICON;
40132916Sdonn 		p->tn.rval = NONAME;
40232916Sdonn 		return;
4039701Slinton 	}
40432916Sdonn 	locctr(DATA);
40532916Sdonn 	defalign(o == DCON ? ALDOUBLE : ALFLOAT);
40632916Sdonn 	deflab(i = getlab());
40732916Sdonn 	if (o == FCON)
40832916Sdonn 		fincode(p->fpn.fval, SZFLOAT);
40932916Sdonn 	else
41032916Sdonn 		fincode(p->dpn.dval, SZDOUBLE);
41132916Sdonn 	p->tn.lval = 0;
41232916Sdonn 	p->tn.rval = -i;
41332916Sdonn 	p->in.type = (o == DCON ? DOUBLE : FLOAT);
41432916Sdonn 	p->in.op = NAME;
41532916Sdonn }
4169701Slinton 
ecode(p)4179701Slinton ecode( p ) NODE *p; {
4189701Slinton 
4199701Slinton 	/* walk the tree and write out the nodes.. */
4209701Slinton 
4219701Slinton 	if( nerrors ) return;
4229701Slinton 	p2tree( p );
4239701Slinton 	p2compile( p );
4249701Slinton 	}
4259701Slinton 
4269701Slinton #ifndef ONEPASS
tlen(p)4279701Slinton tlen(p) NODE *p;
4289701Slinton {
4299701Slinton 	switch(p->in.type) {
4309701Slinton 		case CHAR:
4319701Slinton 		case UCHAR:
4329701Slinton 			return(1);
4339701Slinton 
4349701Slinton 		case SHORT:
4359701Slinton 		case USHORT:
43632919Sdonn 			return(SZSHORT/SZCHAR);
4379701Slinton 
4389701Slinton 		case DOUBLE:
43932919Sdonn 			return(SZDOUBLE/SZCHAR);
4409701Slinton 
4419701Slinton 		default:
44232919Sdonn 			return(SZINT/SZCHAR);
4439701Slinton 		}
4449701Slinton 	}
4459701Slinton #endif
446