xref: /original-bsd/old/pcc/ccom.vax/local.c (revision 4c01ad61)
1 #ifndef lint
2 static char *sccsid ="@(#)local.c	1.7 (Berkeley) 04/02/85";
3 #endif lint
4 
5 # include "pass1.h"
6 
7 /*	this file contains code which is dependent on the target machine */
8 
9 NODE *
10 cast( p, t ) register NODE *p; TWORD t; {
11 	/* cast node p to type t */
12 
13 	p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p );
14 	p->in.left->in.op = FREE;
15 	p->in.op = FREE;
16 	return( p->in.right );
17 	}
18 
19 NODE *
20 clocal(p) NODE *p; {
21 
22 	/* this is called to do local transformations on
23 	   an expression tree preparitory to its being
24 	   written out in intermediate code.
25 	*/
26 
27 	/* the major essential job is rewriting the
28 	   automatic variables and arguments in terms of
29 	   REG and OREG nodes */
30 	/* conversion ops which are not necessary are also clobbered here */
31 	/* in addition, any special features (such as rewriting
32 	   exclusive or) are easily handled here as well */
33 
34 	register struct symtab *q;
35 	register NODE *r;
36 	register o;
37 	register m, ml;
38 
39 	switch( o = p->in.op ){
40 
41 	case NAME:
42 		if( p->tn.rval < 0 ) { /* already processed; ignore... */
43 			return(p);
44 			}
45 		q = &stab[p->tn.rval];
46 		switch( q->sclass ){
47 
48 		case AUTO:
49 		case PARAM:
50 			/* fake up a structure reference */
51 			r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
52 			r->tn.lval = 0;
53 			r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG);
54 			p = stref( block( STREF, r, p, 0, 0, 0 ) );
55 			break;
56 
57 		case ULABEL:
58 		case LABEL:
59 		case STATIC:
60 			if( q->slevel == 0 ) break;
61 			p->tn.lval = 0;
62 			p->tn.rval = -q->offset;
63 			break;
64 
65 		case REGISTER:
66 			p->in.op = REG;
67 			p->tn.lval = 0;
68 			p->tn.rval = q->offset;
69 			break;
70 
71 			}
72 		break;
73 
74 	case PCONV:
75 		/* do pointer conversions for char and longs */
76 		ml = p->in.left->in.type;
77 		if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
78 
79 		/* pointers all have the same representation; the type is inherited */
80 
81 		p->in.left->in.type = p->in.type;
82 		p->in.left->fn.cdim = p->fn.cdim;
83 		p->in.left->fn.csiz = p->fn.csiz;
84 		p->in.op = FREE;
85 		return( p->in.left );
86 
87 	case SCONV:
88 		m = (p->in.type == FLOAT || p->in.type == DOUBLE );
89 		ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE );
90 		o = p->in.left->in.op;
91 		if( (o == FCON || o == DCON) && ml && !m ) {
92 			/* float type to int type */
93 			r = block( ICON, (NODE *)NULL, (NODE *)NULL, INT, 0, 0 );
94 			if( o == FCON )
95 				r->tn.lval = (int) p->in.left->fpn.fval;
96 			else
97 				r->tn.lval = (int) p->in.left->dpn.dval;
98 			r->tn.rval = NONAME;
99 			p->in.left->in.op = FREE;
100 			p->in.left = r;
101 			}
102 		else
103 #ifdef SPRECC
104 			if ( ml || m )
105 #else
106 			if ( ml != m )
107 #endif
108 				break;
109 
110 		/* now, look for conversions downwards */
111 
112 		m = p->in.type;
113 		ml = p->in.left->in.type;
114 		if( p->in.left->in.op == ICON ){ /* simulate the conversion here */
115 			CONSZ val;
116 			val = p->in.left->tn.lval;
117 			switch( m ){
118 			case CHAR:
119 				p->in.left->tn.lval = (char) val;
120 				break;
121 			case UCHAR:
122 				p->in.left->tn.lval = val & 0XFF;
123 				break;
124 			case USHORT:
125 				p->in.left->tn.lval = val & 0XFFFFL;
126 				break;
127 			case SHORT:
128 				p->in.left->tn.lval = (short)val;
129 				break;
130 			case UNSIGNED:
131 				p->in.left->tn.lval = val & 0xFFFFFFFFL;
132 				break;
133 			case INT:
134 				p->in.left->tn.lval = (int)val;
135 				break;
136 				}
137 			p->in.left->in.type = m;
138 			}
139 		else if( m != FLOAT && m != DOUBLE )
140 			break;
141 
142 		/* clobber conversion */
143 		p->in.op = FREE;
144 		return( p->in.left );  /* conversion gets clobbered */
145 
146 	case PVCONV:
147 	case PMCONV:
148 		if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
149 		p->in.op = FREE;
150 		return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
151 
152 	case RS:
153 	case ASG RS:
154 		/* convert >> to << with negative shift count */
155 		/* only if type of left operand is not unsigned */
156 
157 		if( ISUNSIGNED(p->in.left->in.type) ) break;
158 		if( p->in.right->in.op != UNARY MINUS )
159 			p->in.right = buildtree( UNARY MINUS, p->in.right, NIL );
160 		else {
161 			r = p->in.right;
162 			p->in.right = p->in.right->in.left;
163 			r->in.op = FREE;
164 		}
165 		if( p->in.op == RS ) p->in.op = LS;
166 		else p->in.op = ASG LS;
167 		break;
168 
169 	case FLD:
170 		/* make sure that the second pass does not make the
171 		   descendant of a FLD operator into a doubly indexed OREG */
172 
173 		if( p->in.left->in.op == UNARY MUL
174 				&& (r=p->in.left->in.left)->in.op == PCONV)
175 			if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
176 				if( ISPTR(r->in.type) ) {
177 					if( ISUNSIGNED(p->in.left->in.type) )
178 						p->in.left->in.type = UCHAR;
179 					else
180 						p->in.left->in.type = CHAR;
181 				}
182 		break;
183 		}
184 
185 	return(p);
186 	}
187 
188 andable( p ) NODE *p; {
189 	return(1);  /* all names can have & taken on them */
190 	}
191 
192 cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
193 	autooff = AUTOINIT;
194 	}
195 
196 cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
197 
198 #ifdef TRUST_REG_CHAR_AND_REG_SHORT
199 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* tbl */
200 		|| t==CHAR || t==UCHAR || t==SHORT 		/* tbl */
201 		|| t==USHORT || ISPTR(t)) return(1);		/* tbl */
202 #else
203 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* wnj */
204 #ifdef SPRECC
205 		|| t==FLOAT
206 #endif
207 		|| ISPTR(t)) return (1);			/* wnj */
208 #endif
209 	return(0);
210 	}
211 
212 NODE *
213 offcon( off, t, d, s ) OFFSZ off; TWORD t; {
214 
215 	/* return a node, for structure references, which is suitable for
216 	   being added to a pointer of type t, in order to be off bits offset
217 	   into a structure */
218 
219 	register NODE *p;
220 
221 	/* t, d, and s are the type, dimension offset, and sizeoffset */
222 	/* in general they  are necessary for offcon, but not on H'well */
223 
224 	p = bcon(0);
225 	p->tn.lval = off/SZCHAR;
226 	return(p);
227 
228 	}
229 
230 
231 static inwd	/* current bit offsed in word */;
232 static word	/* word being built from fields */;
233 
234 incode( p, sz ) register NODE *p; {
235 
236 	/* generate initialization code for assigning a constant c
237 		to a field of width sz */
238 	/* we assume that the proper alignment has been obtained */
239 	/* inoff is updated to have the proper final value */
240 	/* we also assume sz  < SZINT */
241 
242 	if((sz+inwd) > SZINT) cerror("incode: field > int");
243 	word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
244 	inwd += sz;
245 	inoff += sz;
246 	if(inoff%SZINT == 0) {
247 		printf( "	.long	0x%x\n", word);
248 		word = inwd = 0;
249 		}
250 	}
251 
252 fincode( d, sz ) double d; {
253 	/* output code to initialize space of size sz to the value d */
254 	/* the proper alignment has been obtained */
255 	/* inoff is updated to have the proper final value */
256 	/* on the target machine, write it out in octal! */
257 
258 
259 	printf("	%s	0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
260 		sz == SZDOUBLE ? 'd' : 'f', d);
261 	inoff += sz;
262 	}
263 
264 cinit( p, sz ) NODE *p; {
265 	NODE *l;
266 
267 	/*
268 	 * as a favor (?) to people who want to write
269 	 *     int i = 9600/134.5;
270 	 * we will, under the proper circumstances, do
271 	 * a coersion here.
272 	 */
273 	switch (p->in.type) {
274 	case INT:
275 	case UNSIGNED:
276 		l = p->in.left;
277 		if (l->in.op != SCONV ||
278 		    (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
279 			break;
280 		l->in.op = FREE;
281 		l = l->in.left;
282 		l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
283 			(long)(l->fpn.fval);
284 		l->tn.rval = NONAME;
285 		l->tn.op = ICON;
286 		l->tn.type = INT;
287 		p->in.left = l;
288 		break;
289 	}
290 	/* arrange for the initialization of p into a space of size sz */
291 	/* the proper alignment has been opbtained */
292 	/* inoff is updated to have the proper final value */
293 	ecode( p );
294 	inoff += sz;
295 	}
296 
297 vfdzero( n ){ /* define n bits of zeros in a vfd */
298 
299 	if( n <= 0 ) return;
300 
301 	inwd += n;
302 	inoff += n;
303 	if( inoff%ALINT ==0 ) {
304 		printf( "	.long	0x%x\n", word );
305 		word = inwd = 0;
306 		}
307 	}
308 
309 char *
310 exname( p ) char *p; {
311 	/* make a name look like an external name in the local machine */
312 
313 #ifndef FLEXNAMES
314 	static char text[NCHNAM+1];
315 #else
316 	static char text[BUFSIZ+1];
317 #endif
318 
319 	register i;
320 
321 	text[0] = '_';
322 #ifndef FLEXNAMES
323 	for( i=1; *p&&i<NCHNAM; ++i ){
324 #else
325 	for( i=1; *p; ++i ){
326 #endif
327 		text[i] = *p++;
328 		}
329 
330 	text[i] = '\0';
331 #ifndef FLEXNAMES
332 	text[NCHNAM] = '\0';  /* truncate */
333 #endif
334 
335 	return( text );
336 	}
337 
338 ctype( type ) TWORD type;
339 	{ /* map types which are not defined on the local machine */
340 	switch( BTYPE(type) ){
341 
342 	case LONG:
343 		MODTYPE(type,INT);
344 		break;
345 
346 	case ULONG:
347 		MODTYPE(type,UNSIGNED);
348 		}
349 	return( type );
350 	}
351 
352 noinit() { /* curid is a variable which is defined but
353 	is not initialized (and not a function );
354 	This routine returns the stroage class for an uninitialized declaration */
355 
356 	return(EXTERN);
357 
358 	}
359 
360 commdec( id ){ /* make a common declaration for id, if reasonable */
361 	register struct symtab *q;
362 	OFFSZ off, tsize();
363 
364 	q = &stab[id];
365 	printf( "	.comm	%s,", exname( q->sname ) );
366 	off = tsize( q->stype, q->dimoff, q->sizoff );
367 	printf( CONFMT, off/SZCHAR );
368 	printf( "\n" );
369 	}
370 
371 isitlong( cb, ce ){ /* is lastcon to be long or short */
372 	/* cb is the first character of the representation, ce the last */
373 
374 	if( ce == 'l' || ce == 'L' ||
375 		lastcon >= (1L << (SZINT-1) ) ) return (1);
376 	return(0);
377 	}
378 
379 
380 isitfloat( s ) char *s; {
381 	union cvt {
382 		double	d;
383 		int	n[2];
384 	} cvt;
385 	double atof();
386 
387 	/* avoid floating point exception for double -> float conversions */
388 	dcon = cvt.d = atof(s);
389 	if( cvt.n[1] == 0 ){
390 		fcon = dcon;
391 		return( FCON );
392 		}
393 	return( DCON );
394 	}
395 
396 ecode( p ) NODE *p; {
397 
398 	/* walk the tree and write out the nodes.. */
399 
400 	if( nerrors ) return;
401 	p2tree( p );
402 	p2compile( p );
403 	}
404 
405 #ifndef ONEPASS
406 tlen(p) NODE *p;
407 {
408 	switch(p->in.type) {
409 		case CHAR:
410 		case UCHAR:
411 			return(1);
412 
413 		case SHORT:
414 		case USHORT:
415 			return(2);
416 
417 		case DOUBLE:
418 			return(8);
419 
420 		default:
421 			return(4);
422 		}
423 	}
424 #endif
425