xref: /csrg-svn/old/pcc/ccom.vax/local.c (revision 16181)
1*16181Sralph static char *sccsid ="@(#)local.c	1.3 (Berkeley) 03/14/84";
29701Slinton # include "mfile1"
39701Slinton 
49701Slinton /*	this file contains code which is dependent on the target machine */
59701Slinton 
69701Slinton NODE *
79701Slinton cast( p, t ) register NODE *p; TWORD t; {
89701Slinton 	/* cast node p to type t */
99701Slinton 
109701Slinton 	p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
119701Slinton 	p->in.left->in.op = FREE;
129701Slinton 	p->in.op = FREE;
139701Slinton 	return( p->in.right );
149701Slinton 	}
159701Slinton 
169701Slinton NODE *
179701Slinton clocal(p) NODE *p; {
189701Slinton 
199701Slinton 	/* this is called to do local transformations on
209701Slinton 	   an expression tree preparitory to its being
219701Slinton 	   written out in intermediate code.
229701Slinton 	*/
239701Slinton 
249701Slinton 	/* the major essential job is rewriting the
259701Slinton 	   automatic variables and arguments in terms of
269701Slinton 	   REG and OREG nodes */
279701Slinton 	/* conversion ops which are not necessary are also clobbered here */
289701Slinton 	/* in addition, any special features (such as rewriting
299701Slinton 	   exclusive or) are easily handled here as well */
309701Slinton 
319701Slinton 	register struct symtab *q;
329701Slinton 	register NODE *r;
339701Slinton 	register o;
349701Slinton 	register m, ml;
359701Slinton 
369701Slinton 	switch( o = p->in.op ){
379701Slinton 
389701Slinton 	case NAME:
399701Slinton 		if( p->tn.rval < 0 ) { /* already processed; ignore... */
409701Slinton 			return(p);
419701Slinton 			}
429701Slinton 		q = &stab[p->tn.rval];
439701Slinton 		switch( q->sclass ){
449701Slinton 
459701Slinton 		case AUTO:
469701Slinton 		case PARAM:
479701Slinton 			/* fake up a structure reference */
489701Slinton 			r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
499701Slinton 			r->tn.lval = 0;
509701Slinton 			r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG);
519701Slinton 			p = stref( block( STREF, r, p, 0, 0, 0 ) );
529701Slinton 			break;
539701Slinton 
549701Slinton 		case ULABEL:
559701Slinton 		case LABEL:
569701Slinton 		case STATIC:
579701Slinton 			if( q->slevel == 0 ) break;
589701Slinton 			p->tn.lval = 0;
599701Slinton 			p->tn.rval = -q->offset;
609701Slinton 			break;
619701Slinton 
629701Slinton 		case REGISTER:
639701Slinton 			p->in.op = REG;
649701Slinton 			p->tn.lval = 0;
659701Slinton 			p->tn.rval = q->offset;
669701Slinton 			break;
679701Slinton 
689701Slinton 			}
699701Slinton 		break;
709701Slinton 
719701Slinton 	case PCONV:
729701Slinton 		/* do pointer conversions for char and longs */
739701Slinton 		ml = p->in.left->in.type;
749701Slinton 		if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
759701Slinton 
769701Slinton 		/* pointers all have the same representation; the type is inherited */
779701Slinton 
789701Slinton 	inherit:
799701Slinton 		p->in.left->in.type = p->in.type;
809701Slinton 		p->in.left->fn.cdim = p->fn.cdim;
819701Slinton 		p->in.left->fn.csiz = p->fn.csiz;
829701Slinton 		p->in.op = FREE;
839701Slinton 		return( p->in.left );
849701Slinton 
859701Slinton 	case SCONV:
869701Slinton 		m = (p->in.type == FLOAT || p->in.type == DOUBLE );
879701Slinton 		ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE );
889701Slinton 		if( m != ml ) break;
899701Slinton 
909701Slinton 		/* now, look for conversions downwards */
919701Slinton 
929701Slinton 		m = p->in.type;
939701Slinton 		ml = p->in.left->in.type;
949701Slinton 		if( p->in.left->in.op == ICON ){ /* simulate the conversion here */
959701Slinton 			CONSZ val;
969701Slinton 			val = p->in.left->tn.lval;
979701Slinton 			switch( m ){
989701Slinton 			case CHAR:
999701Slinton 				p->in.left->tn.lval = (char) val;
1009701Slinton 				break;
1019701Slinton 			case UCHAR:
1029701Slinton 				p->in.left->tn.lval = val & 0XFF;
1039701Slinton 				break;
1049701Slinton 			case USHORT:
1059701Slinton 				p->in.left->tn.lval = val & 0XFFFFL;
1069701Slinton 				break;
1079701Slinton 			case SHORT:
1089701Slinton 				p->in.left->tn.lval = (short)val;
1099701Slinton 				break;
1109701Slinton 			case UNSIGNED:
1119701Slinton 				p->in.left->tn.lval = val & 0xFFFFFFFFL;
1129701Slinton 				break;
1139701Slinton 			case INT:
1149701Slinton 				p->in.left->tn.lval = (int)val;
1159701Slinton 				break;
1169701Slinton 				}
1179701Slinton 			p->in.left->in.type = m;
1189701Slinton 			}
119*16181Sralph 		else
120*16181Sralph 			break;
1219701Slinton 
1229701Slinton 		/* clobber conversion */
1239701Slinton 		p->in.op = FREE;
1249701Slinton 		return( p->in.left );  /* conversion gets clobbered */
1259701Slinton 
1269701Slinton 	case PVCONV:
1279701Slinton 	case PMCONV:
1289701Slinton 		if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
1299701Slinton 		p->in.op = FREE;
1309701Slinton 		return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
1319701Slinton 
1329701Slinton 	case RS:
1339701Slinton 	case ASG RS:
1349701Slinton 		/* convert >> to << with negative shift count */
1359701Slinton 		/* only if type of left operand is not unsigned */
1369701Slinton 
1379701Slinton 		if( ISUNSIGNED(p->in.left->in.type) ) break;
1389701Slinton 		p->in.right = buildtree( UNARY MINUS, p->in.right, NIL );
1399701Slinton 		if( p->in.op == RS ) p->in.op = LS;
1409701Slinton 		else p->in.op = ASG LS;
1419701Slinton 		break;
1429701Slinton 
1439701Slinton 	case FLD:
1449701Slinton 		/* make sure that the second pass does not make the
1459701Slinton 		   descendant of a FLD operator into a doubly indexed OREG */
1469701Slinton 
1479701Slinton 		if( p->in.left->in.op == UNARY MUL
1489701Slinton 				&& (r=p->in.left->in.left)->in.op == PCONV)
1499701Slinton 			if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
1509701Slinton 				if( ISPTR(r->in.type) ) {
1519701Slinton 					if( ISUNSIGNED(p->in.left->in.type) )
1529701Slinton 						p->in.left->in.type = UCHAR;
1539701Slinton 					else
1549701Slinton 						p->in.left->in.type = CHAR;
1559701Slinton 				}
1569701Slinton 		break;
1579701Slinton 		}
1589701Slinton 
1599701Slinton 	return(p);
1609701Slinton 	}
1619701Slinton 
1629701Slinton andable( p ) NODE *p; {
1639701Slinton 	return(1);  /* all names can have & taken on them */
1649701Slinton 	}
1659701Slinton 
1669701Slinton cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
1679701Slinton 	autooff = AUTOINIT;
1689701Slinton 	}
1699701Slinton 
1709701Slinton cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
1719701Slinton 
1729701Slinton #ifdef TRUST_REG_CHAR_AND_REG_SHORT
1739701Slinton 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* tbl */
1749701Slinton 		|| t==CHAR || t==UCHAR || t==SHORT 		/* tbl */
1759701Slinton 		|| t==USHORT || ISPTR(t)) return(1);		/* tbl */
1769701Slinton #else
1779701Slinton 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* wnj */
1789701Slinton 		|| ISPTR(t)) return (1);			/* wnj */
1799701Slinton #endif
1809701Slinton 	return(0);
1819701Slinton 	}
1829701Slinton 
1839701Slinton NODE *
1849701Slinton offcon( off, t, d, s ) OFFSZ off; TWORD t; {
1859701Slinton 
1869701Slinton 	/* return a node, for structure references, which is suitable for
1879701Slinton 	   being added to a pointer of type t, in order to be off bits offset
1889701Slinton 	   into a structure */
1899701Slinton 
1909701Slinton 	register NODE *p;
1919701Slinton 
1929701Slinton 	/* t, d, and s are the type, dimension offset, and sizeoffset */
1939701Slinton 	/* in general they  are necessary for offcon, but not on H'well */
1949701Slinton 
1959701Slinton 	p = bcon(0);
1969701Slinton 	p->tn.lval = off/SZCHAR;
1979701Slinton 	return(p);
1989701Slinton 
1999701Slinton 	}
2009701Slinton 
2019701Slinton 
2029701Slinton static inwd	/* current bit offsed in word */;
2039701Slinton static word	/* word being built from fields */;
2049701Slinton 
2059701Slinton incode( p, sz ) register NODE *p; {
2069701Slinton 
2079701Slinton 	/* generate initialization code for assigning a constant c
2089701Slinton 		to a field of width sz */
2099701Slinton 	/* we assume that the proper alignment has been obtained */
2109701Slinton 	/* inoff is updated to have the proper final value */
2119701Slinton 	/* we also assume sz  < SZINT */
2129701Slinton 
2139701Slinton 	if((sz+inwd) > SZINT) cerror("incode: field > int");
2149701Slinton 	word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
2159701Slinton 	inwd += sz;
2169701Slinton 	inoff += sz;
2179701Slinton 	if(inoff%SZINT == 0) {
2189701Slinton 		printf( "	.long	0x%x\n", word);
2199701Slinton 		word = inwd = 0;
2209701Slinton 		}
2219701Slinton 	}
2229701Slinton 
2239701Slinton fincode( d, sz ) double d; {
2249701Slinton 	/* output code to initialize space of size sz to the value d */
2259701Slinton 	/* the proper alignment has been obtained */
2269701Slinton 	/* inoff is updated to have the proper final value */
2279701Slinton 	/* on the target machine, write it out in octal! */
2289701Slinton 
2299701Slinton 
2309701Slinton 	printf("	%s	0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
2319701Slinton 		sz == SZDOUBLE ? 'd' : 'f', d);
2329701Slinton 	inoff += sz;
2339701Slinton 	}
2349701Slinton 
2359701Slinton cinit( p, sz ) NODE *p; {
2369701Slinton 	/* arrange for the initialization of p into a space of
2379701Slinton 	size sz */
2389701Slinton 	/* the proper alignment has been opbtained */
2399701Slinton 	/* inoff is updated to have the proper final value */
2409701Slinton 	ecode( p );
2419701Slinton 	inoff += sz;
2429701Slinton 	}
2439701Slinton 
2449701Slinton vfdzero( n ){ /* define n bits of zeros in a vfd */
2459701Slinton 
2469701Slinton 	if( n <= 0 ) return;
2479701Slinton 
2489701Slinton 	inwd += n;
2499701Slinton 	inoff += n;
2509701Slinton 	if( inoff%ALINT ==0 ) {
2519701Slinton 		printf( "	.long	0x%x\n", word );
2529701Slinton 		word = inwd = 0;
2539701Slinton 		}
2549701Slinton 	}
2559701Slinton 
2569701Slinton char *
2579701Slinton exname( p ) char *p; {
2589701Slinton 	/* make a name look like an external name in the local machine */
2599701Slinton 
2609701Slinton #ifndef FLEXNAMES
2619701Slinton 	static char text[NCHNAM+1];
2629701Slinton #else
2639701Slinton 	static char text[BUFSIZ+1];
2649701Slinton #endif
2659701Slinton 
2669701Slinton 	register i;
2679701Slinton 
2689701Slinton 	text[0] = '_';
2699701Slinton #ifndef FLEXNAMES
2709701Slinton 	for( i=1; *p&&i<NCHNAM; ++i ){
2719701Slinton #else
2729701Slinton 	for( i=1; *p; ++i ){
2739701Slinton #endif
2749701Slinton 		text[i] = *p++;
2759701Slinton 		}
2769701Slinton 
2779701Slinton 	text[i] = '\0';
2789701Slinton #ifndef FLEXNAMES
2799701Slinton 	text[NCHNAM] = '\0';  /* truncate */
2809701Slinton #endif
2819701Slinton 
2829701Slinton 	return( text );
2839701Slinton 	}
2849701Slinton 
2859701Slinton ctype( type ){ /* map types which are not defined on the local machine */
2869701Slinton 	switch( BTYPE(type) ){
2879701Slinton 
2889701Slinton 	case LONG:
2899701Slinton 		MODTYPE(type,INT);
2909701Slinton 		break;
2919701Slinton 
2929701Slinton 	case ULONG:
2939701Slinton 		MODTYPE(type,UNSIGNED);
2949701Slinton 		}
2959701Slinton 	return( type );
2969701Slinton 	}
2979701Slinton 
2989701Slinton noinit( t ) { /* curid is a variable which is defined but
2999701Slinton 	is not initialized (and not a function );
3009701Slinton 	This routine returns the stroage class for an uninitialized declaration */
3019701Slinton 
3029701Slinton 	return(EXTERN);
3039701Slinton 
3049701Slinton 	}
3059701Slinton 
3069701Slinton commdec( id ){ /* make a common declaration for id, if reasonable */
3079701Slinton 	register struct symtab *q;
3089701Slinton 	OFFSZ off, tsize();
3099701Slinton 
3109701Slinton 	q = &stab[id];
3119701Slinton 	printf( "	.comm	%s,", exname( q->sname ) );
3129701Slinton 	off = tsize( q->stype, q->dimoff, q->sizoff );
3139701Slinton 	printf( CONFMT, off/SZCHAR );
3149701Slinton 	printf( "\n" );
3159701Slinton 	}
3169701Slinton 
3179701Slinton isitlong( cb, ce ){ /* is lastcon to be long or short */
3189701Slinton 	/* cb is the first character of the representation, ce the last */
3199701Slinton 
3209701Slinton 	if( ce == 'l' || ce == 'L' ||
3219701Slinton 		lastcon >= (1L << (SZINT-1) ) ) return (1);
3229701Slinton 	return(0);
3239701Slinton 	}
3249701Slinton 
3259701Slinton 
3269701Slinton isitfloat( s ) char *s; {
3279701Slinton 	double atof();
3289701Slinton 	dcon = atof(s);
3299701Slinton 	return( FCON );
3309701Slinton 	}
3319701Slinton 
3329701Slinton ecode( p ) NODE *p; {
3339701Slinton 
3349701Slinton 	/* walk the tree and write out the nodes.. */
3359701Slinton 
3369701Slinton 	if( nerrors ) return;
3379701Slinton 	p2tree( p );
3389701Slinton 	p2compile( p );
3399701Slinton 	}
3409701Slinton 
3419701Slinton #ifndef ONEPASS
3429701Slinton tlen(p) NODE *p;
3439701Slinton {
3449701Slinton 	switch(p->in.type) {
3459701Slinton 		case CHAR:
3469701Slinton 		case UCHAR:
3479701Slinton 			return(1);
3489701Slinton 
3499701Slinton 		case SHORT:
3509701Slinton 		case USHORT:
3519701Slinton 			return(2);
3529701Slinton 
3539701Slinton 		case DOUBLE:
3549701Slinton 			return(8);
3559701Slinton 
3569701Slinton 		default:
3579701Slinton 			return(4);
3589701Slinton 		}
3599701Slinton 	}
3609701Slinton #endif
361