xref: /csrg-svn/old/pcc/ccom.vax/local.c (revision 18555)
117738Sralph #ifndef lint
2*18555Sralph static char *sccsid ="@(#)local.c	1.7 (Berkeley) 04/02/85";
317738Sralph #endif lint
417738Sralph 
5*18555Sralph # include "pass1.h"
69701Slinton 
79701Slinton /*	this file contains code which is dependent on the target machine */
89701Slinton 
99701Slinton NODE *
109701Slinton cast( p, t ) register NODE *p; TWORD t; {
119701Slinton 	/* cast node p to type t */
129701Slinton 
139701Slinton 	p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
149701Slinton 	p->in.left->in.op = FREE;
159701Slinton 	p->in.op = FREE;
169701Slinton 	return( p->in.right );
179701Slinton 	}
189701Slinton 
199701Slinton NODE *
209701Slinton clocal(p) NODE *p; {
219701Slinton 
229701Slinton 	/* this is called to do local transformations on
239701Slinton 	   an expression tree preparitory to its being
249701Slinton 	   written out in intermediate code.
259701Slinton 	*/
269701Slinton 
279701Slinton 	/* the major essential job is rewriting the
289701Slinton 	   automatic variables and arguments in terms of
299701Slinton 	   REG and OREG nodes */
309701Slinton 	/* conversion ops which are not necessary are also clobbered here */
319701Slinton 	/* in addition, any special features (such as rewriting
329701Slinton 	   exclusive or) are easily handled here as well */
339701Slinton 
349701Slinton 	register struct symtab *q;
359701Slinton 	register NODE *r;
369701Slinton 	register o;
379701Slinton 	register m, ml;
389701Slinton 
399701Slinton 	switch( o = p->in.op ){
409701Slinton 
419701Slinton 	case NAME:
429701Slinton 		if( p->tn.rval < 0 ) { /* already processed; ignore... */
439701Slinton 			return(p);
449701Slinton 			}
459701Slinton 		q = &stab[p->tn.rval];
469701Slinton 		switch( q->sclass ){
479701Slinton 
489701Slinton 		case AUTO:
499701Slinton 		case PARAM:
509701Slinton 			/* fake up a structure reference */
519701Slinton 			r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
529701Slinton 			r->tn.lval = 0;
539701Slinton 			r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG);
549701Slinton 			p = stref( block( STREF, r, p, 0, 0, 0 ) );
559701Slinton 			break;
569701Slinton 
579701Slinton 		case ULABEL:
589701Slinton 		case LABEL:
599701Slinton 		case STATIC:
609701Slinton 			if( q->slevel == 0 ) break;
619701Slinton 			p->tn.lval = 0;
629701Slinton 			p->tn.rval = -q->offset;
639701Slinton 			break;
649701Slinton 
659701Slinton 		case REGISTER:
669701Slinton 			p->in.op = REG;
679701Slinton 			p->tn.lval = 0;
689701Slinton 			p->tn.rval = q->offset;
699701Slinton 			break;
709701Slinton 
719701Slinton 			}
729701Slinton 		break;
739701Slinton 
749701Slinton 	case PCONV:
759701Slinton 		/* do pointer conversions for char and longs */
769701Slinton 		ml = p->in.left->in.type;
779701Slinton 		if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
789701Slinton 
799701Slinton 		/* pointers all have the same representation; the type is inherited */
809701Slinton 
819701Slinton 		p->in.left->in.type = p->in.type;
829701Slinton 		p->in.left->fn.cdim = p->fn.cdim;
839701Slinton 		p->in.left->fn.csiz = p->fn.csiz;
849701Slinton 		p->in.op = FREE;
859701Slinton 		return( p->in.left );
869701Slinton 
879701Slinton 	case SCONV:
889701Slinton 		m = (p->in.type == FLOAT || p->in.type == DOUBLE );
899701Slinton 		ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE );
9017738Sralph 		o = p->in.left->in.op;
9117738Sralph 		if( (o == FCON || o == DCON) && ml && !m ) {
9217738Sralph 			/* float type to int type */
9317738Sralph 			r = block( ICON, (NODE *)NULL, (NODE *)NULL, INT, 0, 0 );
9417738Sralph 			if( o == FCON )
9517738Sralph 				r->tn.lval = (int) p->in.left->fpn.fval;
9617738Sralph 			else
9717738Sralph 				r->tn.lval = (int) p->in.left->dpn.dval;
9817738Sralph 			r->tn.rval = NONAME;
9917738Sralph 			p->in.left->in.op = FREE;
10017738Sralph 			p->in.left = r;
10117738Sralph 			}
10217738Sralph 		else
10317738Sralph #ifdef SPRECC
10417738Sralph 			if ( ml || m )
10517738Sralph #else
10617738Sralph 			if ( ml != m )
10717738Sralph #endif
10817738Sralph 				break;
1099701Slinton 
1109701Slinton 		/* now, look for conversions downwards */
1119701Slinton 
1129701Slinton 		m = p->in.type;
1139701Slinton 		ml = p->in.left->in.type;
1149701Slinton 		if( p->in.left->in.op == ICON ){ /* simulate the conversion here */
1159701Slinton 			CONSZ val;
1169701Slinton 			val = p->in.left->tn.lval;
1179701Slinton 			switch( m ){
1189701Slinton 			case CHAR:
1199701Slinton 				p->in.left->tn.lval = (char) val;
1209701Slinton 				break;
1219701Slinton 			case UCHAR:
1229701Slinton 				p->in.left->tn.lval = val & 0XFF;
1239701Slinton 				break;
1249701Slinton 			case USHORT:
1259701Slinton 				p->in.left->tn.lval = val & 0XFFFFL;
1269701Slinton 				break;
1279701Slinton 			case SHORT:
1289701Slinton 				p->in.left->tn.lval = (short)val;
1299701Slinton 				break;
1309701Slinton 			case UNSIGNED:
1319701Slinton 				p->in.left->tn.lval = val & 0xFFFFFFFFL;
1329701Slinton 				break;
1339701Slinton 			case INT:
1349701Slinton 				p->in.left->tn.lval = (int)val;
1359701Slinton 				break;
1369701Slinton 				}
1379701Slinton 			p->in.left->in.type = m;
1389701Slinton 			}
13916189Sralph 		else if( m != FLOAT && m != DOUBLE )
14016181Sralph 			break;
1419701Slinton 
1429701Slinton 		/* clobber conversion */
1439701Slinton 		p->in.op = FREE;
1449701Slinton 		return( p->in.left );  /* conversion gets clobbered */
1459701Slinton 
1469701Slinton 	case PVCONV:
1479701Slinton 	case PMCONV:
1489701Slinton 		if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
1499701Slinton 		p->in.op = FREE;
1509701Slinton 		return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
1519701Slinton 
1529701Slinton 	case RS:
1539701Slinton 	case ASG RS:
1549701Slinton 		/* convert >> to << with negative shift count */
1559701Slinton 		/* only if type of left operand is not unsigned */
1569701Slinton 
1579701Slinton 		if( ISUNSIGNED(p->in.left->in.type) ) break;
15817738Sralph 		if( p->in.right->in.op != UNARY MINUS )
15917738Sralph 			p->in.right = buildtree( UNARY MINUS, p->in.right, NIL );
16017738Sralph 		else {
16117738Sralph 			r = p->in.right;
16217738Sralph 			p->in.right = p->in.right->in.left;
16317738Sralph 			r->in.op = FREE;
16417738Sralph 		}
1659701Slinton 		if( p->in.op == RS ) p->in.op = LS;
1669701Slinton 		else p->in.op = ASG LS;
1679701Slinton 		break;
1689701Slinton 
1699701Slinton 	case FLD:
1709701Slinton 		/* make sure that the second pass does not make the
1719701Slinton 		   descendant of a FLD operator into a doubly indexed OREG */
1729701Slinton 
1739701Slinton 		if( p->in.left->in.op == UNARY MUL
1749701Slinton 				&& (r=p->in.left->in.left)->in.op == PCONV)
1759701Slinton 			if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
1769701Slinton 				if( ISPTR(r->in.type) ) {
1779701Slinton 					if( ISUNSIGNED(p->in.left->in.type) )
1789701Slinton 						p->in.left->in.type = UCHAR;
1799701Slinton 					else
1809701Slinton 						p->in.left->in.type = CHAR;
1819701Slinton 				}
1829701Slinton 		break;
1839701Slinton 		}
1849701Slinton 
1859701Slinton 	return(p);
1869701Slinton 	}
1879701Slinton 
1889701Slinton andable( p ) NODE *p; {
1899701Slinton 	return(1);  /* all names can have & taken on them */
1909701Slinton 	}
1919701Slinton 
1929701Slinton cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
1939701Slinton 	autooff = AUTOINIT;
1949701Slinton 	}
1959701Slinton 
1969701Slinton cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
1979701Slinton 
1989701Slinton #ifdef TRUST_REG_CHAR_AND_REG_SHORT
1999701Slinton 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* tbl */
2009701Slinton 		|| t==CHAR || t==UCHAR || t==SHORT 		/* tbl */
2019701Slinton 		|| t==USHORT || ISPTR(t)) return(1);		/* tbl */
2029701Slinton #else
2039701Slinton 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* wnj */
20417738Sralph #ifdef SPRECC
20517738Sralph 		|| t==FLOAT
20617738Sralph #endif
2079701Slinton 		|| ISPTR(t)) return (1);			/* wnj */
2089701Slinton #endif
2099701Slinton 	return(0);
2109701Slinton 	}
2119701Slinton 
2129701Slinton NODE *
2139701Slinton offcon( off, t, d, s ) OFFSZ off; TWORD t; {
2149701Slinton 
2159701Slinton 	/* return a node, for structure references, which is suitable for
2169701Slinton 	   being added to a pointer of type t, in order to be off bits offset
2179701Slinton 	   into a structure */
2189701Slinton 
2199701Slinton 	register NODE *p;
2209701Slinton 
2219701Slinton 	/* t, d, and s are the type, dimension offset, and sizeoffset */
2229701Slinton 	/* in general they  are necessary for offcon, but not on H'well */
2239701Slinton 
2249701Slinton 	p = bcon(0);
2259701Slinton 	p->tn.lval = off/SZCHAR;
2269701Slinton 	return(p);
2279701Slinton 
2289701Slinton 	}
2299701Slinton 
2309701Slinton 
2319701Slinton static inwd	/* current bit offsed in word */;
2329701Slinton static word	/* word being built from fields */;
2339701Slinton 
2349701Slinton incode( p, sz ) register NODE *p; {
2359701Slinton 
2369701Slinton 	/* generate initialization code for assigning a constant c
2379701Slinton 		to a field of width sz */
2389701Slinton 	/* we assume that the proper alignment has been obtained */
2399701Slinton 	/* inoff is updated to have the proper final value */
2409701Slinton 	/* we also assume sz  < SZINT */
2419701Slinton 
2429701Slinton 	if((sz+inwd) > SZINT) cerror("incode: field > int");
2439701Slinton 	word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
2449701Slinton 	inwd += sz;
2459701Slinton 	inoff += sz;
2469701Slinton 	if(inoff%SZINT == 0) {
2479701Slinton 		printf( "	.long	0x%x\n", word);
2489701Slinton 		word = inwd = 0;
2499701Slinton 		}
2509701Slinton 	}
2519701Slinton 
2529701Slinton fincode( d, sz ) double d; {
2539701Slinton 	/* output code to initialize space of size sz to the value d */
2549701Slinton 	/* the proper alignment has been obtained */
2559701Slinton 	/* inoff is updated to have the proper final value */
2569701Slinton 	/* on the target machine, write it out in octal! */
2579701Slinton 
2589701Slinton 
2599701Slinton 	printf("	%s	0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
2609701Slinton 		sz == SZDOUBLE ? 'd' : 'f', d);
2619701Slinton 	inoff += sz;
2629701Slinton 	}
2639701Slinton 
2649701Slinton cinit( p, sz ) NODE *p; {
26518437Smckusick 	NODE *l;
26618437Smckusick 
26718437Smckusick 	/*
26818437Smckusick 	 * as a favor (?) to people who want to write
26918437Smckusick 	 *     int i = 9600/134.5;
27018437Smckusick 	 * we will, under the proper circumstances, do
27118437Smckusick 	 * a coersion here.
27218437Smckusick 	 */
27318437Smckusick 	switch (p->in.type) {
27418437Smckusick 	case INT:
27518437Smckusick 	case UNSIGNED:
27618437Smckusick 		l = p->in.left;
277*18555Sralph 		if (l->in.op != SCONV ||
278*18555Sralph 		    (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
279*18555Sralph 			break;
28018437Smckusick 		l->in.op = FREE;
28118437Smckusick 		l = l->in.left;
282*18555Sralph 		l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
283*18555Sralph 			(long)(l->fpn.fval);
28418437Smckusick 		l->tn.rval = NONAME;
28518437Smckusick 		l->tn.op = ICON;
28618437Smckusick 		l->tn.type = INT;
28718437Smckusick 		p->in.left = l;
28818437Smckusick 		break;
28918437Smckusick 	}
29018437Smckusick 	/* arrange for the initialization of p into a space of size sz */
2919701Slinton 	/* the proper alignment has been opbtained */
2929701Slinton 	/* inoff is updated to have the proper final value */
2939701Slinton 	ecode( p );
2949701Slinton 	inoff += sz;
2959701Slinton 	}
2969701Slinton 
2979701Slinton vfdzero( n ){ /* define n bits of zeros in a vfd */
2989701Slinton 
2999701Slinton 	if( n <= 0 ) return;
3009701Slinton 
3019701Slinton 	inwd += n;
3029701Slinton 	inoff += n;
3039701Slinton 	if( inoff%ALINT ==0 ) {
3049701Slinton 		printf( "	.long	0x%x\n", word );
3059701Slinton 		word = inwd = 0;
3069701Slinton 		}
3079701Slinton 	}
3089701Slinton 
3099701Slinton char *
3109701Slinton exname( p ) char *p; {
3119701Slinton 	/* make a name look like an external name in the local machine */
3129701Slinton 
3139701Slinton #ifndef FLEXNAMES
3149701Slinton 	static char text[NCHNAM+1];
3159701Slinton #else
3169701Slinton 	static char text[BUFSIZ+1];
3179701Slinton #endif
3189701Slinton 
3199701Slinton 	register i;
3209701Slinton 
3219701Slinton 	text[0] = '_';
3229701Slinton #ifndef FLEXNAMES
3239701Slinton 	for( i=1; *p&&i<NCHNAM; ++i ){
3249701Slinton #else
3259701Slinton 	for( i=1; *p; ++i ){
3269701Slinton #endif
3279701Slinton 		text[i] = *p++;
3289701Slinton 		}
3299701Slinton 
3309701Slinton 	text[i] = '\0';
3319701Slinton #ifndef FLEXNAMES
3329701Slinton 	text[NCHNAM] = '\0';  /* truncate */
3339701Slinton #endif
3349701Slinton 
3359701Slinton 	return( text );
3369701Slinton 	}
3379701Slinton 
33817738Sralph ctype( type ) TWORD type;
33917738Sralph 	{ /* map types which are not defined on the local machine */
3409701Slinton 	switch( BTYPE(type) ){
3419701Slinton 
3429701Slinton 	case LONG:
3439701Slinton 		MODTYPE(type,INT);
3449701Slinton 		break;
3459701Slinton 
3469701Slinton 	case ULONG:
3479701Slinton 		MODTYPE(type,UNSIGNED);
3489701Slinton 		}
3499701Slinton 	return( type );
3509701Slinton 	}
3519701Slinton 
35217738Sralph noinit() { /* curid is a variable which is defined but
3539701Slinton 	is not initialized (and not a function );
3549701Slinton 	This routine returns the stroage class for an uninitialized declaration */
3559701Slinton 
3569701Slinton 	return(EXTERN);
3579701Slinton 
3589701Slinton 	}
3599701Slinton 
3609701Slinton commdec( id ){ /* make a common declaration for id, if reasonable */
3619701Slinton 	register struct symtab *q;
3629701Slinton 	OFFSZ off, tsize();
3639701Slinton 
3649701Slinton 	q = &stab[id];
3659701Slinton 	printf( "	.comm	%s,", exname( q->sname ) );
3669701Slinton 	off = tsize( q->stype, q->dimoff, q->sizoff );
3679701Slinton 	printf( CONFMT, off/SZCHAR );
3689701Slinton 	printf( "\n" );
3699701Slinton 	}
3709701Slinton 
3719701Slinton isitlong( cb, ce ){ /* is lastcon to be long or short */
3729701Slinton 	/* cb is the first character of the representation, ce the last */
3739701Slinton 
3749701Slinton 	if( ce == 'l' || ce == 'L' ||
3759701Slinton 		lastcon >= (1L << (SZINT-1) ) ) return (1);
3769701Slinton 	return(0);
3779701Slinton 	}
3789701Slinton 
3799701Slinton 
3809701Slinton isitfloat( s ) char *s; {
381*18555Sralph 	union cvt {
382*18555Sralph 		double	d;
383*18555Sralph 		int	n[2];
384*18555Sralph 	} cvt;
3859701Slinton 	double atof();
386*18555Sralph 
387*18555Sralph 	/* avoid floating point exception for double -> float conversions */
388*18555Sralph 	dcon = cvt.d = atof(s);
389*18555Sralph 	if( cvt.n[1] == 0 ){
390*18555Sralph 		fcon = dcon;
391*18555Sralph 		return( FCON );
392*18555Sralph 		}
393*18555Sralph 	return( DCON );
3949701Slinton 	}
3959701Slinton 
3969701Slinton ecode( p ) NODE *p; {
3979701Slinton 
3989701Slinton 	/* walk the tree and write out the nodes.. */
3999701Slinton 
4009701Slinton 	if( nerrors ) return;
4019701Slinton 	p2tree( p );
4029701Slinton 	p2compile( p );
4039701Slinton 	}
4049701Slinton 
4059701Slinton #ifndef ONEPASS
4069701Slinton tlen(p) NODE *p;
4079701Slinton {
4089701Slinton 	switch(p->in.type) {
4099701Slinton 		case CHAR:
4109701Slinton 		case UCHAR:
4119701Slinton 			return(1);
4129701Slinton 
4139701Slinton 		case SHORT:
4149701Slinton 		case USHORT:
4159701Slinton 			return(2);
4169701Slinton 
4179701Slinton 		case DOUBLE:
4189701Slinton 			return(8);
4199701Slinton 
4209701Slinton 		default:
4219701Slinton 			return(4);
4229701Slinton 		}
4239701Slinton 	}
4249701Slinton #endif
425