xref: /csrg-svn/old/pcc/ccom.vax/local.c (revision 32915)
1 #ifndef lint
2 static char *sccsid ="@(#)local.c	1.10 (Berkeley) 12/11/87";
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 /*ARGSUSED*/
189 andable( p ) NODE *p; {
190 	return(1);  /* all names can have & taken on them */
191 	}
192 
193 cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
194 	autooff = AUTOINIT;
195 	}
196 
197 cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
198 
199 #ifdef TRUST_REG_CHAR_AND_REG_SHORT
200 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* tbl */
201 		|| t==CHAR || t==UCHAR || t==SHORT 		/* tbl */
202 		|| t==USHORT || ISPTR(t)) return(1);		/* tbl */
203 #else
204 	if( t==INT || t==UNSIGNED || t==LONG || t==ULONG	/* wnj */
205 #ifdef SPRECC
206 		|| t==FLOAT
207 #endif
208 		|| ISPTR(t)) return (1);			/* wnj */
209 #endif
210 	return(0);
211 	}
212 
213 /*ARGSUSED*/
214 NODE *
215 offcon( off, t, d, s ) OFFSZ off; TWORD t; {
216 
217 	/* return a node, for structure references, which is suitable for
218 	   being added to a pointer of type t, in order to be off bits offset
219 	   into a structure */
220 
221 	register NODE *p;
222 
223 	/* t, d, and s are the type, dimension offset, and sizeoffset */
224 	/* in general they  are necessary for offcon, but not on VAX */
225 
226 	p = bcon(0);
227 	p->tn.lval = off/SZCHAR;
228 	return(p);
229 
230 	}
231 
232 
233 static inwd	/* current bit offsed in word */;
234 static word	/* word being built from fields */;
235 
236 incode( p, sz ) register NODE *p; {
237 
238 	/* generate initialization code for assigning a constant c
239 		to a field of width sz */
240 	/* we assume that the proper alignment has been obtained */
241 	/* inoff is updated to have the proper final value */
242 	/* we also assume sz  < SZINT */
243 
244 	if (nerrors) return;
245 	if((sz+inwd) > SZINT) cerror("incode: field > int");
246 	word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
247 	inwd += sz;
248 	inoff += sz;
249 	if(inoff%SZINT == 0) {
250 		printf( "	.long	0x%x\n", word);
251 		word = inwd = 0;
252 		}
253 	}
254 
255 fincode( d, sz ) double d; {
256 	/* output code to initialize space of size sz to the value d */
257 	/* the proper alignment has been obtained */
258 	/* inoff is updated to have the proper final value */
259 	/* on the target machine, write it out in octal! */
260 
261 
262 	if (nerrors) return;
263 	printf("	%s	0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
264 		sz == SZDOUBLE ? 'd' : 'f', d);
265 	inoff += sz;
266 	}
267 
268 cinit( p, sz ) NODE *p; {
269 	NODE *l;
270 
271 	/*
272 	 * as a favor (?) to people who want to write
273 	 *     int i = 9600/134.5;
274 	 * we will, under the proper circumstances, do
275 	 * a coersion here.
276 	 */
277 	switch (p->in.type) {
278 	case INT:
279 	case UNSIGNED:
280 		l = p->in.left;
281 		if (l->in.op != SCONV ||
282 		    (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
283 			break;
284 		l->in.op = FREE;
285 		l = l->in.left;
286 		l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
287 			(long)(l->fpn.fval);
288 		l->tn.rval = NONAME;
289 		l->tn.op = ICON;
290 		l->tn.type = INT;
291 		p->in.left = l;
292 		break;
293 	}
294 	/* arrange for the initialization of p into a space of size sz */
295 	/* the proper alignment has been opbtained */
296 	/* inoff is updated to have the proper final value */
297 	ecode( p );
298 	inoff += sz;
299 	}
300 
301 vfdzero( n ){ /* define n bits of zeros in a vfd */
302 
303 	if( n <= 0 ) return;
304 
305 	if (nerrors) return;
306 	inwd += n;
307 	inoff += n;
308 	if( inoff%ALINT ==0 ) {
309 		printf( "	.long	0x%x\n", word );
310 		word = inwd = 0;
311 		}
312 	}
313 
314 char *
315 exname( p ) char *p; {
316 	/* make a name look like an external name in the local machine */
317 
318 #ifndef FLEXNAMES
319 	static char text[NCHNAM+1];
320 #else
321 	static char text[BUFSIZ+1];
322 #endif
323 
324 	register i;
325 
326 	text[0] = '_';
327 #ifndef FLEXNAMES
328 	for( i=1; *p&&i<NCHNAM; ++i )
329 #else
330 	for( i=1; *p; ++i )
331 #endif
332 		text[i] = *p++;
333 
334 	text[i] = '\0';
335 #ifndef FLEXNAMES
336 	text[NCHNAM] = '\0';  /* truncate */
337 #endif
338 
339 	return( text );
340 	}
341 
342 ctype( type ) TWORD type;
343 	{ /* map types which are not defined on the local machine */
344 	switch( BTYPE(type) ){
345 
346 	case LONG:
347 		MODTYPE(type,INT);
348 		break;
349 
350 	case ULONG:
351 		MODTYPE(type,UNSIGNED);
352 		}
353 	return( type );
354 	}
355 
356 noinit() { /* curid is a variable which is defined but
357 	is not initialized (and not a function );
358 	This routine returns the stroage class for an uninitialized declaration */
359 
360 	return(EXTERN);
361 
362 	}
363 
364 commdec( id ){ /* make a common declaration for id, if reasonable */
365 	register struct symtab *q;
366 	OFFSZ off, tsize();
367 
368 	if (nerrors) return;
369 	q = &stab[id];
370 	printf( "	.comm	%s,", exname( q->sname ) );
371 	off = tsize( q->stype, q->dimoff, q->sizoff );
372 	printf( CONFMT, off/SZCHAR );
373 	printf( "\n" );
374 	}
375 
376 /*ARGSUSED*/
377 isitlong( cb, ce ){ /* is lastcon to be long or short */
378 	/* cb is the first character of the representation, ce the last */
379 
380 	if( ce == 'l' || ce == 'L' ||
381 		lastcon >= (1L << (SZINT-1) ) ) return (1);
382 	return(0);
383 	}
384 
385 
386 isitfloat( s ) char *s; {
387 	union cvt {
388 		double	d;
389 		int	n[2];
390 	} cvt;
391 	double atof();
392 
393 	/* avoid floating point exception for double -> float conversions */
394 	dcon = cvt.d = atof(s);
395 	if( cvt.n[1] == 0 ){
396 		fcon = dcon;
397 		return( FCON );
398 		}
399 	return( DCON );
400 	}
401 
402 ecode( p ) NODE *p; {
403 
404 	/* walk the tree and write out the nodes.. */
405 
406 	if( nerrors ) return;
407 	p2tree( p );
408 	p2compile( p );
409 	}
410 
411 #ifndef ONEPASS
412 tlen(p) NODE *p;
413 {
414 	switch(p->in.type) {
415 		case CHAR:
416 		case UCHAR:
417 			return(1);
418 
419 		case SHORT:
420 		case USHORT:
421 			return(2);
422 
423 		case DOUBLE:
424 			return(8);
425 
426 		default:
427 			return(4);
428 		}
429 	}
430 #endif
431